@papernote/ui 1.3.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ActionBar.d.ts +112 -0
- package/dist/components/ActionBar.d.ts.map +1 -0
- package/dist/components/BottomNavigation.d.ts +98 -0
- package/dist/components/BottomNavigation.d.ts.map +1 -0
- package/dist/components/Checkbox.d.ts +2 -0
- package/dist/components/Checkbox.d.ts.map +1 -1
- package/dist/components/CheckboxList.d.ts +81 -0
- package/dist/components/CheckboxList.d.ts.map +1 -0
- package/dist/components/Chip.d.ts +92 -1
- package/dist/components/Chip.d.ts.map +1 -1
- package/dist/components/ConfirmDialog.d.ts +43 -1
- package/dist/components/ConfirmDialog.d.ts.map +1 -1
- package/dist/components/DataTable.d.ts +10 -1
- package/dist/components/DataTable.d.ts.map +1 -1
- package/dist/components/DataTableCardView.d.ts +99 -0
- package/dist/components/DataTableCardView.d.ts.map +1 -0
- package/dist/components/ExpandablePanel.d.ts +142 -0
- package/dist/components/ExpandablePanel.d.ts.map +1 -0
- package/dist/components/FloatingActionButton.d.ts +98 -0
- package/dist/components/FloatingActionButton.d.ts.map +1 -0
- package/dist/components/Input.d.ts +45 -1
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/MobileHeader.d.ts +98 -0
- package/dist/components/MobileHeader.d.ts.map +1 -0
- package/dist/components/MobileLayout.d.ts +121 -0
- package/dist/components/MobileLayout.d.ts.map +1 -0
- package/dist/components/Modal.d.ts +78 -1
- package/dist/components/Modal.d.ts.map +1 -1
- package/dist/components/PageHeader.d.ts +86 -0
- package/dist/components/PageHeader.d.ts.map +1 -0
- package/dist/components/PullToRefresh.d.ts +87 -0
- package/dist/components/PullToRefresh.d.ts.map +1 -0
- package/dist/components/QueryTransparency.d.ts +1 -1
- package/dist/components/QueryTransparency.d.ts.map +1 -1
- package/dist/components/SearchableList.d.ts +83 -0
- package/dist/components/SearchableList.d.ts.map +1 -0
- package/dist/components/Select.d.ts +16 -2
- package/dist/components/Select.d.ts.map +1 -1
- package/dist/components/Sidebar.d.ts +40 -1
- package/dist/components/Sidebar.d.ts.map +1 -1
- package/dist/components/SwipeActions.d.ts +93 -0
- package/dist/components/SwipeActions.d.ts.map +1 -0
- package/dist/components/Switch.d.ts +1 -0
- package/dist/components/Switch.d.ts.map +1 -1
- package/dist/components/Textarea.d.ts +13 -0
- package/dist/components/Textarea.d.ts.map +1 -1
- package/dist/components/index.d.ts +31 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/context/MobileContext.d.ts +168 -0
- package/dist/context/MobileContext.d.ts.map +1 -0
- package/dist/hooks/useResponsive.d.ts +158 -0
- package/dist/hooks/useResponsive.d.ts.map +1 -0
- package/dist/index.d.ts +1871 -51
- package/dist/index.esm.js +3025 -196
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3063 -194
- package/dist/index.js.map +1 -1
- package/dist/styles.css +434 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ActionBar.stories.tsx +246 -0
- package/src/components/ActionBar.tsx +242 -0
- package/src/components/BottomNavigation.stories.tsx +142 -0
- package/src/components/BottomNavigation.tsx +225 -0
- package/src/components/Checkbox.stories.tsx +162 -0
- package/src/components/Checkbox.tsx +22 -6
- package/src/components/CheckboxList.stories.tsx +311 -0
- package/src/components/CheckboxList.tsx +433 -0
- package/src/components/Chip.stories.tsx +389 -0
- package/src/components/Chip.tsx +182 -3
- package/src/components/ConfirmDialog.tsx +56 -4
- package/src/components/DataTable.tsx +60 -1
- package/src/components/DataTableCardView.stories.tsx +307 -0
- package/src/components/DataTableCardView.tsx +419 -0
- package/src/components/ExpandablePanel.stories.tsx +620 -0
- package/src/components/ExpandablePanel.tsx +383 -0
- package/src/components/FloatingActionButton.stories.tsx +197 -0
- package/src/components/FloatingActionButton.tsx +301 -0
- package/src/components/Grid.stories.tsx +16 -16
- package/src/components/Input.stories.tsx +214 -0
- package/src/components/Input.tsx +81 -4
- package/src/components/MobileHeader.stories.tsx +205 -0
- package/src/components/MobileHeader.tsx +233 -0
- package/src/components/MobileLayout.stories.tsx +338 -0
- package/src/components/MobileLayout.tsx +313 -0
- package/src/components/Modal.stories.tsx +388 -0
- package/src/components/Modal.tsx +122 -4
- package/src/components/PageHeader.stories.tsx +198 -0
- package/src/components/PageHeader.tsx +217 -0
- package/src/components/PullToRefresh.stories.tsx +321 -0
- package/src/components/PullToRefresh.tsx +294 -0
- package/src/components/QueryTransparency.tsx +1 -1
- package/src/components/SearchableList.stories.tsx +437 -0
- package/src/components/SearchableList.tsx +326 -0
- package/src/components/Select.stories.tsx +190 -0
- package/src/components/Select.tsx +353 -137
- package/src/components/Sidebar.tsx +193 -10
- package/src/components/SwipeActions.stories.tsx +327 -0
- package/src/components/SwipeActions.tsx +387 -0
- package/src/components/Switch.stories.tsx +158 -0
- package/src/components/Switch.tsx +12 -3
- package/src/components/Textarea.tsx +31 -1
- package/src/components/index.ts +69 -3
- package/src/context/MobileContext.tsx +296 -0
- package/src/hooks/useResponsive.ts +360 -0
- package/src/types/index.ts +4 -0
- package/tailwind.config.js +56 -1
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tailwind breakpoint values in pixels
|
|
5
|
+
*/
|
|
6
|
+
export const BREAKPOINTS = {
|
|
7
|
+
xs: 0,
|
|
8
|
+
sm: 640,
|
|
9
|
+
md: 768,
|
|
10
|
+
lg: 1024,
|
|
11
|
+
xl: 1280,
|
|
12
|
+
'2xl': 1536,
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export type Breakpoint = keyof typeof BREAKPOINTS;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Viewport size state
|
|
19
|
+
*/
|
|
20
|
+
export interface ViewportSize {
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Orientation type
|
|
27
|
+
*/
|
|
28
|
+
export type Orientation = 'portrait' | 'landscape';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* SSR-safe check for window availability
|
|
32
|
+
*/
|
|
33
|
+
const isBrowser = typeof window !== 'undefined';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get initial viewport size (SSR-safe)
|
|
37
|
+
*/
|
|
38
|
+
const getInitialViewportSize = (): ViewportSize => {
|
|
39
|
+
if (!isBrowser) {
|
|
40
|
+
return { width: 1024, height: 768 }; // Default to desktop for SSR
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
width: window.innerWidth,
|
|
44
|
+
height: window.innerHeight,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* useViewportSize - Returns current viewport dimensions
|
|
50
|
+
*
|
|
51
|
+
* Updates on window resize with debouncing for performance.
|
|
52
|
+
* SSR-safe with sensible defaults.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const { width, height } = useViewportSize();
|
|
56
|
+
* console.log(`Viewport: ${width}x${height}`);
|
|
57
|
+
*/
|
|
58
|
+
export function useViewportSize(): ViewportSize {
|
|
59
|
+
const [size, setSize] = useState<ViewportSize>(getInitialViewportSize);
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (!isBrowser) return;
|
|
63
|
+
|
|
64
|
+
let timeoutId: ReturnType<typeof setTimeout>;
|
|
65
|
+
|
|
66
|
+
const handleResize = () => {
|
|
67
|
+
clearTimeout(timeoutId);
|
|
68
|
+
timeoutId = setTimeout(() => {
|
|
69
|
+
setSize({
|
|
70
|
+
width: window.innerWidth,
|
|
71
|
+
height: window.innerHeight,
|
|
72
|
+
});
|
|
73
|
+
}, 100); // Debounce 100ms
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
window.addEventListener('resize', handleResize);
|
|
77
|
+
|
|
78
|
+
// Set initial size on mount (in case SSR default differs)
|
|
79
|
+
handleResize();
|
|
80
|
+
|
|
81
|
+
return () => {
|
|
82
|
+
clearTimeout(timeoutId);
|
|
83
|
+
window.removeEventListener('resize', handleResize);
|
|
84
|
+
};
|
|
85
|
+
}, []);
|
|
86
|
+
|
|
87
|
+
return size;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* useBreakpoint - Returns the current Tailwind breakpoint
|
|
92
|
+
*
|
|
93
|
+
* Automatically updates when viewport crosses breakpoint thresholds.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* const breakpoint = useBreakpoint();
|
|
97
|
+
* // Returns: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
|
|
98
|
+
*/
|
|
99
|
+
export function useBreakpoint(): Breakpoint {
|
|
100
|
+
const { width } = useViewportSize();
|
|
101
|
+
|
|
102
|
+
if (width >= BREAKPOINTS['2xl']) return '2xl';
|
|
103
|
+
if (width >= BREAKPOINTS.xl) return 'xl';
|
|
104
|
+
if (width >= BREAKPOINTS.lg) return 'lg';
|
|
105
|
+
if (width >= BREAKPOINTS.md) return 'md';
|
|
106
|
+
if (width >= BREAKPOINTS.sm) return 'sm';
|
|
107
|
+
return 'xs';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* useMediaQuery - React hook for CSS media queries
|
|
112
|
+
*
|
|
113
|
+
* SSR-safe implementation that returns false during SSR and
|
|
114
|
+
* updates reactively when media query match state changes.
|
|
115
|
+
*
|
|
116
|
+
* @param query - CSS media query string (e.g., '(max-width: 768px)')
|
|
117
|
+
* @returns boolean indicating if the media query matches
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
|
121
|
+
* const isReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');
|
|
122
|
+
* const isPortrait = useMediaQuery('(orientation: portrait)');
|
|
123
|
+
*/
|
|
124
|
+
export function useMediaQuery(query: string): boolean {
|
|
125
|
+
const [matches, setMatches] = useState(() => {
|
|
126
|
+
if (!isBrowser) return false;
|
|
127
|
+
return window.matchMedia(query).matches;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (!isBrowser) return;
|
|
132
|
+
|
|
133
|
+
const media = window.matchMedia(query);
|
|
134
|
+
|
|
135
|
+
if (media.matches !== matches) {
|
|
136
|
+
setMatches(media.matches);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const listener = (event: MediaQueryListEvent) => {
|
|
140
|
+
setMatches(event.matches);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
media.addEventListener('change', listener);
|
|
144
|
+
return () => media.removeEventListener('change', listener);
|
|
145
|
+
}, [query, matches]);
|
|
146
|
+
|
|
147
|
+
return matches;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* useIsMobile - Returns true when viewport is mobile-sized (< 768px)
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* const isMobile = useIsMobile();
|
|
155
|
+
* return isMobile ? <MobileNav /> : <DesktopNav />;
|
|
156
|
+
*/
|
|
157
|
+
export function useIsMobile(): boolean {
|
|
158
|
+
return useMediaQuery(`(max-width: ${BREAKPOINTS.md - 1}px)`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* useIsTablet - Returns true when viewport is tablet-sized (768px - 1023px)
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* const isTablet = useIsTablet();
|
|
166
|
+
*/
|
|
167
|
+
export function useIsTablet(): boolean {
|
|
168
|
+
return useMediaQuery(`(min-width: ${BREAKPOINTS.md}px) and (max-width: ${BREAKPOINTS.lg - 1}px)`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* useIsDesktop - Returns true when viewport is desktop-sized (>= 1024px)
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* const isDesktop = useIsDesktop();
|
|
176
|
+
*/
|
|
177
|
+
export function useIsDesktop(): boolean {
|
|
178
|
+
return useMediaQuery(`(min-width: ${BREAKPOINTS.lg}px)`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* useIsTouchDevice - Detects if the device supports touch input
|
|
183
|
+
*
|
|
184
|
+
* Uses multiple detection methods for reliability:
|
|
185
|
+
* - Touch event support
|
|
186
|
+
* - Pointer coarse media query
|
|
187
|
+
* - Max touch points
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* const isTouchDevice = useIsTouchDevice();
|
|
191
|
+
* // Show swipe hints on touch devices
|
|
192
|
+
*/
|
|
193
|
+
export function useIsTouchDevice(): boolean {
|
|
194
|
+
const [isTouch, setIsTouch] = useState(() => {
|
|
195
|
+
if (!isBrowser) return false;
|
|
196
|
+
return (
|
|
197
|
+
'ontouchstart' in window ||
|
|
198
|
+
navigator.maxTouchPoints > 0 ||
|
|
199
|
+
window.matchMedia('(pointer: coarse)').matches
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
if (!isBrowser) return;
|
|
205
|
+
|
|
206
|
+
// Re-check on mount for accuracy
|
|
207
|
+
const touchSupported =
|
|
208
|
+
'ontouchstart' in window ||
|
|
209
|
+
navigator.maxTouchPoints > 0 ||
|
|
210
|
+
window.matchMedia('(pointer: coarse)').matches;
|
|
211
|
+
|
|
212
|
+
setIsTouch(touchSupported);
|
|
213
|
+
}, []);
|
|
214
|
+
|
|
215
|
+
return isTouch;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* useOrientation - Returns current screen orientation
|
|
220
|
+
*
|
|
221
|
+
* @returns 'portrait' | 'landscape'
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* const orientation = useOrientation();
|
|
225
|
+
* // Adjust layout based on orientation
|
|
226
|
+
*/
|
|
227
|
+
export function useOrientation(): Orientation {
|
|
228
|
+
const { width, height } = useViewportSize();
|
|
229
|
+
return height > width ? 'portrait' : 'landscape';
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* useBreakpointValue - Returns different values based on breakpoint
|
|
234
|
+
*
|
|
235
|
+
* Mobile-first: Returns the value for the current breakpoint or the
|
|
236
|
+
* closest smaller breakpoint that has a value defined.
|
|
237
|
+
*
|
|
238
|
+
* @param values - Object mapping breakpoints to values
|
|
239
|
+
* @param defaultValue - Fallback value if no breakpoint matches
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* const columns = useBreakpointValue({ xs: 1, sm: 2, lg: 4 }, 1);
|
|
243
|
+
* // Returns 1 on xs, 2 on sm/md, 4 on lg/xl/2xl
|
|
244
|
+
*
|
|
245
|
+
* const padding = useBreakpointValue({ xs: 'p-2', md: 'p-4', xl: 'p-8' });
|
|
246
|
+
*/
|
|
247
|
+
export function useBreakpointValue<T>(
|
|
248
|
+
values: Partial<Record<Breakpoint, T>>,
|
|
249
|
+
defaultValue?: T
|
|
250
|
+
): T | undefined {
|
|
251
|
+
const breakpoint = useBreakpoint();
|
|
252
|
+
|
|
253
|
+
// Breakpoints in order from largest to smallest
|
|
254
|
+
const breakpointOrder: Breakpoint[] = ['2xl', 'xl', 'lg', 'md', 'sm', 'xs'];
|
|
255
|
+
|
|
256
|
+
// Find the current breakpoint index
|
|
257
|
+
const currentIndex = breakpointOrder.indexOf(breakpoint);
|
|
258
|
+
|
|
259
|
+
// Look for value at current breakpoint or smaller (mobile-first)
|
|
260
|
+
for (let i = currentIndex; i < breakpointOrder.length; i++) {
|
|
261
|
+
const bp = breakpointOrder[i];
|
|
262
|
+
if (bp in values && values[bp] !== undefined) {
|
|
263
|
+
return values[bp];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return defaultValue;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* useResponsiveCallback - Returns a memoized callback that receives responsive info
|
|
272
|
+
*
|
|
273
|
+
* Useful for callbacks that need to behave differently based on viewport.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* const handleClick = useResponsiveCallback((isMobile) => {
|
|
277
|
+
* if (isMobile) {
|
|
278
|
+
* openBottomSheet();
|
|
279
|
+
* } else {
|
|
280
|
+
* openModal();
|
|
281
|
+
* }
|
|
282
|
+
* });
|
|
283
|
+
*/
|
|
284
|
+
export function useResponsiveCallback<T extends (...args: any[]) => any>(
|
|
285
|
+
callback: (isMobile: boolean, isTablet: boolean, isDesktop: boolean) => T
|
|
286
|
+
): T {
|
|
287
|
+
const isMobile = useIsMobile();
|
|
288
|
+
const isTablet = useIsTablet();
|
|
289
|
+
const isDesktop = useIsDesktop();
|
|
290
|
+
|
|
291
|
+
return useCallback(
|
|
292
|
+
(...args: Parameters<T>) => callback(isMobile, isTablet, isDesktop)(...args),
|
|
293
|
+
[callback, isMobile, isTablet, isDesktop]
|
|
294
|
+
) as T;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* useSafeAreaInsets - Returns safe area insets for notched devices
|
|
299
|
+
*
|
|
300
|
+
* Uses CSS environment variables (env(safe-area-inset-*)) to get
|
|
301
|
+
* safe area dimensions for devices with notches or home indicators.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* const { top, bottom } = useSafeAreaInsets();
|
|
305
|
+
* // Add padding-bottom for home indicator
|
|
306
|
+
*/
|
|
307
|
+
export function useSafeAreaInsets(): {
|
|
308
|
+
top: number;
|
|
309
|
+
right: number;
|
|
310
|
+
bottom: number;
|
|
311
|
+
left: number;
|
|
312
|
+
} {
|
|
313
|
+
const [insets, setInsets] = useState({
|
|
314
|
+
top: 0,
|
|
315
|
+
right: 0,
|
|
316
|
+
bottom: 0,
|
|
317
|
+
left: 0,
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
useEffect(() => {
|
|
321
|
+
if (!isBrowser) return;
|
|
322
|
+
|
|
323
|
+
// Create a temporary element to read CSS env() values
|
|
324
|
+
const el = document.createElement('div');
|
|
325
|
+
el.style.position = 'fixed';
|
|
326
|
+
el.style.top = 'env(safe-area-inset-top, 0px)';
|
|
327
|
+
el.style.right = 'env(safe-area-inset-right, 0px)';
|
|
328
|
+
el.style.bottom = 'env(safe-area-inset-bottom, 0px)';
|
|
329
|
+
el.style.left = 'env(safe-area-inset-left, 0px)';
|
|
330
|
+
el.style.visibility = 'hidden';
|
|
331
|
+
el.style.pointerEvents = 'none';
|
|
332
|
+
document.body.appendChild(el);
|
|
333
|
+
|
|
334
|
+
const computed = getComputedStyle(el);
|
|
335
|
+
setInsets({
|
|
336
|
+
top: parseInt(computed.top, 10) || 0,
|
|
337
|
+
right: parseInt(computed.right, 10) || 0,
|
|
338
|
+
bottom: parseInt(computed.bottom, 10) || 0,
|
|
339
|
+
left: parseInt(computed.left, 10) || 0,
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
document.body.removeChild(el);
|
|
343
|
+
}, []);
|
|
344
|
+
|
|
345
|
+
return insets;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* usePrefersMobile - Checks if user prefers reduced data/animations (mobile-friendly)
|
|
350
|
+
*
|
|
351
|
+
* Combines multiple preferences that might indicate mobile/low-power usage.
|
|
352
|
+
*/
|
|
353
|
+
export function usePrefersMobile(): boolean {
|
|
354
|
+
const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');
|
|
355
|
+
const prefersReducedData = useMediaQuery('(prefers-reduced-data: reduce)');
|
|
356
|
+
const isTouchDevice = useIsTouchDevice();
|
|
357
|
+
const isMobile = useIsMobile();
|
|
358
|
+
|
|
359
|
+
return isMobile || isTouchDevice || prefersReducedMotion || prefersReducedData;
|
|
360
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Core types for notebook-ui library
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { QueryTransparencyInfo } from '../components/QueryTransparency';
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Base interface for all data items that can be displayed in tables
|
|
7
9
|
*/
|
|
@@ -22,6 +24,8 @@ export interface PaginationResponse<T = BaseDataItem> {
|
|
|
22
24
|
// Query transparency fields (optional)
|
|
23
25
|
executedQuery?: string;
|
|
24
26
|
executionTimeMs?: number;
|
|
27
|
+
// Full query transparency info for QueryTransparency component
|
|
28
|
+
queryInfo?: QueryTransparencyInfo;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
/**
|
package/tailwind.config.js
CHANGED
|
@@ -175,6 +175,21 @@ export default {
|
|
|
175
175
|
'33': '8.25rem',
|
|
176
176
|
'34': '8.5rem',
|
|
177
177
|
'35': '8.75rem',
|
|
178
|
+
// Touch target sizes (Apple HIG / Material Design)
|
|
179
|
+
'touch-sm': '2.25rem', // 36px - minimum for secondary actions
|
|
180
|
+
'touch': '2.75rem', // 44px - standard touch target (Apple HIG)
|
|
181
|
+
'touch-lg': '3rem', // 48px - large touch target (Material Design)
|
|
182
|
+
},
|
|
183
|
+
// Minimum sizes for touch targets
|
|
184
|
+
minWidth: {
|
|
185
|
+
'touch-sm': '2.25rem',
|
|
186
|
+
'touch': '2.75rem',
|
|
187
|
+
'touch-lg': '3rem',
|
|
188
|
+
},
|
|
189
|
+
minHeight: {
|
|
190
|
+
'touch-sm': '2.25rem',
|
|
191
|
+
'touch': '2.75rem',
|
|
192
|
+
'touch-lg': '3rem',
|
|
178
193
|
},
|
|
179
194
|
borderRadius: {
|
|
180
195
|
'4xl': '2rem',
|
|
@@ -196,11 +211,19 @@ export default {
|
|
|
196
211
|
'fade-in-up': 'fadeInUp 0.5s ease-out',
|
|
197
212
|
'slide-in': 'slideIn 0.3s ease-out',
|
|
198
213
|
'slide-in-right': 'slideInRight 0.3s ease-out',
|
|
214
|
+
'slide-in-left': 'slideInLeft 0.3s ease-out',
|
|
215
|
+
'slide-in-bottom': 'slideInBottom 0.3s ease-out',
|
|
216
|
+
'slide-in-top': 'slideInTop 0.3s ease-out',
|
|
217
|
+
'slide-out-right': 'slideOutRight 0.3s ease-in',
|
|
218
|
+
'slide-out-left': 'slideOutLeft 0.3s ease-in',
|
|
219
|
+
'slide-out-bottom': 'slideOutBottom 0.3s ease-in',
|
|
220
|
+
'slide-out-top': 'slideOutTop 0.3s ease-in',
|
|
199
221
|
'bounce-subtle': 'bounceSubtle 2s infinite',
|
|
200
222
|
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
201
223
|
'shimmer': 'shimmer 2s linear infinite',
|
|
202
224
|
'float': 'float 6s ease-in-out infinite',
|
|
203
225
|
'scale-in': 'scaleIn 0.2s ease-out',
|
|
226
|
+
'scale-out': 'scaleOut 0.2s ease-in',
|
|
204
227
|
},
|
|
205
228
|
keyframes: {
|
|
206
229
|
fadeIn: {
|
|
@@ -216,9 +239,37 @@ export default {
|
|
|
216
239
|
'100%': { transform: 'translateX(0)', opacity: '1' },
|
|
217
240
|
},
|
|
218
241
|
slideInRight: {
|
|
219
|
-
'0%': { transform: 'translateX(
|
|
242
|
+
'0%': { transform: 'translateX(100%)', opacity: '0' },
|
|
243
|
+
'100%': { transform: 'translateX(0)', opacity: '1' },
|
|
244
|
+
},
|
|
245
|
+
slideInLeft: {
|
|
246
|
+
'0%': { transform: 'translateX(-100%)', opacity: '0' },
|
|
220
247
|
'100%': { transform: 'translateX(0)', opacity: '1' },
|
|
221
248
|
},
|
|
249
|
+
slideInBottom: {
|
|
250
|
+
'0%': { transform: 'translateY(100%)', opacity: '0' },
|
|
251
|
+
'100%': { transform: 'translateY(0)', opacity: '1' },
|
|
252
|
+
},
|
|
253
|
+
slideInTop: {
|
|
254
|
+
'0%': { transform: 'translateY(-100%)', opacity: '0' },
|
|
255
|
+
'100%': { transform: 'translateY(0)', opacity: '1' },
|
|
256
|
+
},
|
|
257
|
+
slideOutRight: {
|
|
258
|
+
'0%': { transform: 'translateX(0)', opacity: '1' },
|
|
259
|
+
'100%': { transform: 'translateX(100%)', opacity: '0' },
|
|
260
|
+
},
|
|
261
|
+
slideOutLeft: {
|
|
262
|
+
'0%': { transform: 'translateX(0)', opacity: '1' },
|
|
263
|
+
'100%': { transform: 'translateX(-100%)', opacity: '0' },
|
|
264
|
+
},
|
|
265
|
+
slideOutBottom: {
|
|
266
|
+
'0%': { transform: 'translateY(0)', opacity: '1' },
|
|
267
|
+
'100%': { transform: 'translateY(100%)', opacity: '0' },
|
|
268
|
+
},
|
|
269
|
+
slideOutTop: {
|
|
270
|
+
'0%': { transform: 'translateY(0)', opacity: '1' },
|
|
271
|
+
'100%': { transform: 'translateY(-100%)', opacity: '0' },
|
|
272
|
+
},
|
|
222
273
|
bounceSubtle: {
|
|
223
274
|
'0%, 100%': { transform: 'translateY(0)' },
|
|
224
275
|
'50%': { transform: 'translateY(-2px)' },
|
|
@@ -235,6 +286,10 @@ export default {
|
|
|
235
286
|
'0%': { transform: 'scale(0.9)', opacity: '0' },
|
|
236
287
|
'100%': { transform: 'scale(1)', opacity: '1' },
|
|
237
288
|
},
|
|
289
|
+
scaleOut: {
|
|
290
|
+
'0%': { transform: 'scale(1)', opacity: '1' },
|
|
291
|
+
'100%': { transform: 'scale(0.9)', opacity: '0' },
|
|
292
|
+
},
|
|
238
293
|
},
|
|
239
294
|
backdropBlur: {
|
|
240
295
|
'xs': '2px',
|