@papernote/ui 1.3.0 → 1.5.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/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 +50 -1
- package/dist/components/Modal.d.ts.map +1 -1
- 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/Spreadsheet.d.ts +5 -1
- package/dist/components/Spreadsheet.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 +27 -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 +1666 -65
- package/dist/index.esm.js +2875 -8619
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2908 -8617
- package/dist/index.js.map +1 -1
- package/dist/styles.css +404 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -4
- 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 +183 -0
- package/src/components/Modal.tsx +84 -3
- 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 +191 -8
- package/src/components/Spreadsheet.tsx +8 -57
- 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 +63 -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,142 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface ExpandablePanelProps {
|
|
3
|
+
/** Content shown in the collapsed header bar */
|
|
4
|
+
collapsedContent: ReactNode;
|
|
5
|
+
/** Full content shown when expanded */
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
/** Position of the panel */
|
|
8
|
+
position?: 'bottom' | 'top';
|
|
9
|
+
/**
|
|
10
|
+
* Positioning mode:
|
|
11
|
+
* - 'viewport': Fixed to viewport edges (default, for standalone use)
|
|
12
|
+
* - 'container': Sticky within parent container (for use inside Page/AppLayout)
|
|
13
|
+
*/
|
|
14
|
+
mode?: 'viewport' | 'container';
|
|
15
|
+
/** Whether the panel is expanded (controlled) */
|
|
16
|
+
expanded?: boolean;
|
|
17
|
+
/** Default expanded state (uncontrolled) */
|
|
18
|
+
defaultExpanded?: boolean;
|
|
19
|
+
/** Callback when expanded state changes */
|
|
20
|
+
onExpandedChange?: (expanded: boolean) => void;
|
|
21
|
+
/** Height when expanded */
|
|
22
|
+
expandedHeight?: string | number;
|
|
23
|
+
/**
|
|
24
|
+
* Maximum width of the panel (e.g., '1400px', '80%', 1200)
|
|
25
|
+
* When set, the panel will be centered horizontally within its container/viewport
|
|
26
|
+
*/
|
|
27
|
+
maxWidth?: string | number;
|
|
28
|
+
/** Whether to show the expand/collapse toggle button */
|
|
29
|
+
showToggle?: boolean;
|
|
30
|
+
/** Custom toggle button content */
|
|
31
|
+
toggleContent?: ReactNode;
|
|
32
|
+
/** Additional actions to show in the header (right side) */
|
|
33
|
+
headerActions?: ReactNode;
|
|
34
|
+
/** Close on Escape key */
|
|
35
|
+
closeOnEscape?: boolean;
|
|
36
|
+
/** Visual variant */
|
|
37
|
+
variant?: 'default' | 'elevated' | 'bordered';
|
|
38
|
+
/** Size variant affecting header height */
|
|
39
|
+
size?: 'sm' | 'md' | 'lg';
|
|
40
|
+
/** Additional CSS classes for the container */
|
|
41
|
+
className?: string;
|
|
42
|
+
/** Additional CSS classes for the header */
|
|
43
|
+
headerClassName?: string;
|
|
44
|
+
/** Additional CSS classes for the content */
|
|
45
|
+
contentClassName?: string;
|
|
46
|
+
/** Z-index for the panel (only applies in viewport mode) */
|
|
47
|
+
zIndex?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* ExpandablePanel - A panel that sticks to the bottom (or top) and can expand/collapse
|
|
51
|
+
*
|
|
52
|
+
* For bottom position: expands UPWARD (content appears above header)
|
|
53
|
+
* For top position: expands DOWNWARD (content appears below header)
|
|
54
|
+
*
|
|
55
|
+
* Two modes of operation:
|
|
56
|
+
* - `viewport`: Fixed to the viewport (for standalone pages, covers StatusBar)
|
|
57
|
+
* - `container`: Sticky within its parent container (for use inside Page/AppLayout, respects StatusBar)
|
|
58
|
+
*
|
|
59
|
+
* @example Basic usage (viewport mode - full page)
|
|
60
|
+
* ```tsx
|
|
61
|
+
* <ExpandablePanel
|
|
62
|
+
* mode="viewport"
|
|
63
|
+
* collapsedContent={<Text>3 items selected</Text>}
|
|
64
|
+
* expandedHeight="300px"
|
|
65
|
+
* >
|
|
66
|
+
* {content}
|
|
67
|
+
* </ExpandablePanel>
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @example Inside Page/AppLayout (container mode - respects StatusBar)
|
|
71
|
+
* ```tsx
|
|
72
|
+
* <Page>
|
|
73
|
+
* <ExpandablePanelContainer>
|
|
74
|
+
* <div className="flex-1 overflow-auto">
|
|
75
|
+
* {pageContent}
|
|
76
|
+
* </div>
|
|
77
|
+
* <ExpandablePanel
|
|
78
|
+
* mode="container"
|
|
79
|
+
* collapsedContent={<Text>3 items selected</Text>}
|
|
80
|
+
* expandedHeight="300px"
|
|
81
|
+
* >
|
|
82
|
+
* {selectedItemsContent}
|
|
83
|
+
* </ExpandablePanel>
|
|
84
|
+
* </ExpandablePanelContainer>
|
|
85
|
+
* </Page>
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example With maxWidth to match page content
|
|
89
|
+
* ```tsx
|
|
90
|
+
* <ExpandablePanel
|
|
91
|
+
* mode="container"
|
|
92
|
+
* maxWidth="1400px"
|
|
93
|
+
* collapsedContent={<Text>Generated SQL</Text>}
|
|
94
|
+
* expandedHeight="300px"
|
|
95
|
+
* >
|
|
96
|
+
* {sqlContent}
|
|
97
|
+
* </ExpandablePanel>
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export default function ExpandablePanel({ collapsedContent, children, position, mode, expanded: controlledExpanded, defaultExpanded, onExpandedChange, expandedHeight, maxWidth, showToggle, toggleContent, headerActions, closeOnEscape, variant, size, className, headerClassName, contentClassName, zIndex, }: ExpandablePanelProps): import("react/jsx-runtime").JSX.Element;
|
|
101
|
+
/**
|
|
102
|
+
* ExpandablePanelSpacer - Adds spacing to prevent content from being hidden behind the panel
|
|
103
|
+
* Only needed in viewport mode. In container mode, the panel is part of the flex layout.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```tsx
|
|
107
|
+
* <div>
|
|
108
|
+
* <MainContent />
|
|
109
|
+
* <ExpandablePanelSpacer size="md" />
|
|
110
|
+
* </div>
|
|
111
|
+
* <ExpandablePanel mode="viewport" position="bottom" size="md" {...props} />
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare function ExpandablePanelSpacer({ size }: {
|
|
115
|
+
size?: 'sm' | 'md' | 'lg';
|
|
116
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
117
|
+
/**
|
|
118
|
+
* ExpandablePanelContainer - Wrapper that sets up proper layout for container mode
|
|
119
|
+
* Use this to wrap your page content when using ExpandablePanel with mode="container"
|
|
120
|
+
*
|
|
121
|
+
* This creates a relative container with full height so the panel can position absolutely
|
|
122
|
+
* at the bottom while the content scrolls above it.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```tsx
|
|
126
|
+
* <Page>
|
|
127
|
+
* <ExpandablePanelContainer>
|
|
128
|
+
* <div className="flex-1 overflow-auto p-4">
|
|
129
|
+
* {pageContent}
|
|
130
|
+
* </div>
|
|
131
|
+
* <ExpandablePanel mode="container" {...props}>
|
|
132
|
+
* {panelContent}
|
|
133
|
+
* </ExpandablePanel>
|
|
134
|
+
* </ExpandablePanelContainer>
|
|
135
|
+
* </Page>
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export declare function ExpandablePanelContainer({ children, className, }: {
|
|
139
|
+
children: ReactNode;
|
|
140
|
+
className?: string;
|
|
141
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
142
|
+
//# sourceMappingURL=ExpandablePanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpandablePanel.d.ts","sourceRoot":"","sources":["../../src/components/ExpandablePanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvD,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,gBAAgB,EAAE,SAAS,CAAC;IAC5B,uCAAuC;IACvC,QAAQ,EAAE,SAAS,CAAC;IACpB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC5B;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IAChC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,wDAAwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mCAAmC;IACnC,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,4DAA4D;IAC5D,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,0BAA0B;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC9C,2CAA2C;IAC3C,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACtC,gBAAgB,EAChB,QAAQ,EACR,QAAmB,EACnB,IAAiB,EACjB,QAAQ,EAAE,kBAAkB,EAC5B,eAAuB,EACvB,gBAAgB,EAChB,cAAwB,EACxB,QAAQ,EACR,UAAiB,EACjB,aAAa,EACb,aAAa,EACb,aAAoB,EACpB,OAAoB,EACpB,IAAW,EACX,SAAc,EACd,eAAoB,EACpB,gBAAqB,EACrB,MAAW,GACZ,EAAE,oBAAoB,2CAqKtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,IAAW,EACZ,EAAE;IACD,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;CAC1B,2CAQA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,SAAc,GACf,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAMA"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Action item for FAB menu
|
|
4
|
+
*/
|
|
5
|
+
export interface FABAction {
|
|
6
|
+
/** Unique identifier */
|
|
7
|
+
id: string;
|
|
8
|
+
/** Icon for the action */
|
|
9
|
+
icon: React.ReactNode;
|
|
10
|
+
/** Label text (shown on hover/long-press) */
|
|
11
|
+
label: string;
|
|
12
|
+
/** Click handler */
|
|
13
|
+
onClick: () => void;
|
|
14
|
+
/** Disabled state */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* FloatingActionButton component props
|
|
19
|
+
*/
|
|
20
|
+
export interface FloatingActionButtonProps {
|
|
21
|
+
/** Primary action when FAB is clicked (without menu) */
|
|
22
|
+
onClick?: () => void;
|
|
23
|
+
/** Icon for the FAB - defaults to Plus */
|
|
24
|
+
icon?: React.ReactNode;
|
|
25
|
+
/** Secondary actions shown in menu */
|
|
26
|
+
actions?: FABAction[];
|
|
27
|
+
/** Position on screen */
|
|
28
|
+
position?: 'bottom-right' | 'bottom-left' | 'bottom-center';
|
|
29
|
+
/** Color variant */
|
|
30
|
+
variant?: 'primary' | 'secondary' | 'accent';
|
|
31
|
+
/** Size */
|
|
32
|
+
size?: 'md' | 'lg';
|
|
33
|
+
/** Accessible label */
|
|
34
|
+
label?: string;
|
|
35
|
+
/** Extended FAB with text label */
|
|
36
|
+
extended?: boolean;
|
|
37
|
+
/** Text for extended FAB */
|
|
38
|
+
extendedLabel?: string;
|
|
39
|
+
/** Hide FAB (useful for scroll-based show/hide) */
|
|
40
|
+
hidden?: boolean;
|
|
41
|
+
/** Custom offset from edge (in pixels) */
|
|
42
|
+
offset?: {
|
|
43
|
+
x?: number;
|
|
44
|
+
y?: number;
|
|
45
|
+
};
|
|
46
|
+
/** Additional class names */
|
|
47
|
+
className?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* FloatingActionButton - Material Design style FAB for mobile
|
|
51
|
+
*
|
|
52
|
+
* A prominent button for the primary action on a screen.
|
|
53
|
+
* Supports single action or expandable menu with multiple actions.
|
|
54
|
+
*
|
|
55
|
+
* @example Simple FAB
|
|
56
|
+
* ```tsx
|
|
57
|
+
* <FloatingActionButton
|
|
58
|
+
* onClick={() => openCreateModal()}
|
|
59
|
+
* label="Create new item"
|
|
60
|
+
* />
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example FAB with action menu
|
|
64
|
+
* ```tsx
|
|
65
|
+
* <FloatingActionButton
|
|
66
|
+
* actions={[
|
|
67
|
+
* { id: 'photo', icon: <Camera />, label: 'Take Photo', onClick: takePhoto },
|
|
68
|
+
* { id: 'upload', icon: <Upload />, label: 'Upload File', onClick: uploadFile },
|
|
69
|
+
* { id: 'note', icon: <FileText />, label: 'Create Note', onClick: createNote },
|
|
70
|
+
* ]}
|
|
71
|
+
* />
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @example Extended FAB
|
|
75
|
+
* ```tsx
|
|
76
|
+
* <FloatingActionButton
|
|
77
|
+
* extended
|
|
78
|
+
* extendedLabel="New Task"
|
|
79
|
+
* icon={<Plus />}
|
|
80
|
+
* onClick={createTask}
|
|
81
|
+
* />
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export default function FloatingActionButton({ onClick, icon, actions, position, variant, size, label, extended, extendedLabel, hidden, offset, className, }: FloatingActionButtonProps): React.ReactPortal;
|
|
85
|
+
/**
|
|
86
|
+
* Hook for scroll-based FAB visibility
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```tsx
|
|
90
|
+
* const { hidden, scrollDirection } = useFABScroll();
|
|
91
|
+
* <FloatingActionButton hidden={hidden} />
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function useFABScroll(threshold?: number): {
|
|
95
|
+
hidden: boolean;
|
|
96
|
+
scrollDirection: 'up' | 'down' | null;
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=FloatingActionButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FloatingActionButton.d.ts","sourceRoot":"","sources":["../../src/components/FloatingActionButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAI3D;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,0BAA0B;IAC1B,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,sCAAsC;IACtC,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;IACtB,yBAAyB;IACzB,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,GAAG,eAAe,CAAC;IAC5D,oBAAoB;IACpB,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC7C,WAAW;IACX,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,MAAM,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAwBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,OAAO,EACP,IAAI,EACJ,OAAO,EACP,QAAyB,EACzB,OAAmB,EACnB,IAAW,EACX,KAAuB,EACvB,QAAgB,EAChB,aAAa,EACb,MAAc,EACd,MAAM,EACN,SAAc,GACf,EAAE,yBAAyB,qBA8I3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,SAAS,SAAK,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE,CA2BvG"}
|
|
@@ -6,7 +6,7 @@ export type ValidationState = 'error' | 'success' | 'warning' | null;
|
|
|
6
6
|
/**
|
|
7
7
|
* Input component props
|
|
8
8
|
*/
|
|
9
|
-
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
9
|
+
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
10
10
|
/** Input label text */
|
|
11
11
|
label?: string;
|
|
12
12
|
/** Helper text displayed below input */
|
|
@@ -37,6 +37,31 @@ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement>
|
|
|
37
37
|
onClear?: () => void;
|
|
38
38
|
/** Show loading spinner in input */
|
|
39
39
|
loading?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Input mode hint for mobile keyboards.
|
|
42
|
+
* 'none' - No virtual keyboard
|
|
43
|
+
* 'text' - Standard text keyboard (default)
|
|
44
|
+
* 'decimal' - Decimal number keyboard
|
|
45
|
+
* 'numeric' - Numeric keyboard
|
|
46
|
+
* 'tel' - Telephone keypad
|
|
47
|
+
* 'search' - Search optimized keyboard
|
|
48
|
+
* 'email' - Email optimized keyboard
|
|
49
|
+
* 'url' - URL optimized keyboard
|
|
50
|
+
*/
|
|
51
|
+
inputMode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';
|
|
52
|
+
/**
|
|
53
|
+
* Enter key hint for mobile keyboards.
|
|
54
|
+
* 'enter' - Standard enter key
|
|
55
|
+
* 'done' - Done action
|
|
56
|
+
* 'go' - Go/navigate action
|
|
57
|
+
* 'next' - Move to next field
|
|
58
|
+
* 'previous' - Move to previous field
|
|
59
|
+
* 'search' - Search action
|
|
60
|
+
* 'send' - Send action
|
|
61
|
+
*/
|
|
62
|
+
enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
|
|
63
|
+
/** Size variant - 'md' is default, 'lg' provides larger touch target (44px min) */
|
|
64
|
+
size?: 'sm' | 'md' | 'lg';
|
|
40
65
|
}
|
|
41
66
|
/**
|
|
42
67
|
* Input - Text input component with validation, icons, and prefixes/suffixes
|
|
@@ -44,12 +69,19 @@ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement>
|
|
|
44
69
|
* A feature-rich text input with support for validation states, character counting,
|
|
45
70
|
* password visibility toggle, prefix/suffix text and icons, and clearable functionality.
|
|
46
71
|
*
|
|
72
|
+
* Mobile optimizations:
|
|
73
|
+
* - inputMode prop for appropriate mobile keyboard
|
|
74
|
+
* - enterKeyHint prop for mobile keyboard action button
|
|
75
|
+
* - Size variants with touch-friendly targets (44px for 'lg')
|
|
76
|
+
*
|
|
47
77
|
* @example Basic input with label
|
|
48
78
|
* ```tsx
|
|
49
79
|
* <Input
|
|
50
80
|
* label="Email"
|
|
51
81
|
* type="email"
|
|
52
82
|
* placeholder="Enter your email"
|
|
83
|
+
* inputMode="email"
|
|
84
|
+
* enterKeyHint="next"
|
|
53
85
|
* />
|
|
54
86
|
* ```
|
|
55
87
|
*
|
|
@@ -75,11 +107,23 @@ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement>
|
|
|
75
107
|
* />
|
|
76
108
|
* ```
|
|
77
109
|
*
|
|
110
|
+
* @example Mobile-optimized phone input
|
|
111
|
+
* ```tsx
|
|
112
|
+
* <Input
|
|
113
|
+
* label="Phone Number"
|
|
114
|
+
* type="tel"
|
|
115
|
+
* inputMode="tel"
|
|
116
|
+
* enterKeyHint="done"
|
|
117
|
+
* size="lg"
|
|
118
|
+
* />
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
78
121
|
* @example With prefix/suffix
|
|
79
122
|
* ```tsx
|
|
80
123
|
* <Input
|
|
81
124
|
* label="Amount"
|
|
82
125
|
* type="number"
|
|
126
|
+
* inputMode="decimal"
|
|
83
127
|
* prefixIcon={<DollarSign />}
|
|
84
128
|
* suffix="USD"
|
|
85
129
|
* clearable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAGpD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAGpD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC3F,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,wDAAwD;IACxD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;IACzF;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;IACjF,mFAAmF;IACnF,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,QAAA,MAAM,KAAK,qFAmQV,CAAC;AAIF,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* MobileHeader component props
|
|
4
|
+
*/
|
|
5
|
+
export interface MobileHeaderProps {
|
|
6
|
+
/** Page/section title */
|
|
7
|
+
title: string;
|
|
8
|
+
/** Subtitle or breadcrumb text */
|
|
9
|
+
subtitle?: string;
|
|
10
|
+
/** Handler for menu button click (hamburger) */
|
|
11
|
+
onMenuClick?: () => void;
|
|
12
|
+
/** Handler for back button click - shows back arrow instead of menu */
|
|
13
|
+
onBackClick?: () => void;
|
|
14
|
+
/** Handler for close button click - shows X instead of menu */
|
|
15
|
+
onCloseClick?: () => void;
|
|
16
|
+
/** Right side action element (button, icon, etc.) */
|
|
17
|
+
rightAction?: React.ReactNode;
|
|
18
|
+
/** Left side action element (overrides menu/back/close buttons) */
|
|
19
|
+
leftAction?: React.ReactNode;
|
|
20
|
+
/** Make header sticky at top */
|
|
21
|
+
sticky?: boolean;
|
|
22
|
+
/** Show border at bottom */
|
|
23
|
+
bordered?: boolean;
|
|
24
|
+
/** Background style */
|
|
25
|
+
variant?: 'solid' | 'transparent' | 'blur';
|
|
26
|
+
/** Additional CSS classes */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Safe area handling for notched devices */
|
|
29
|
+
safeArea?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* MobileHeader - Mobile app header with navigation controls
|
|
33
|
+
*
|
|
34
|
+
* A flexible mobile header component with support for:
|
|
35
|
+
* - Hamburger menu button (default)
|
|
36
|
+
* - Back navigation arrow
|
|
37
|
+
* - Close button (X)
|
|
38
|
+
* - Custom left/right actions
|
|
39
|
+
* - Sticky positioning
|
|
40
|
+
* - Blur/transparent variants
|
|
41
|
+
*
|
|
42
|
+
* @example Basic with menu button
|
|
43
|
+
* ```tsx
|
|
44
|
+
* <MobileHeader
|
|
45
|
+
* title="Dashboard"
|
|
46
|
+
* onMenuClick={() => setDrawerOpen(true)}
|
|
47
|
+
* />
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example With back button
|
|
51
|
+
* ```tsx
|
|
52
|
+
* <MobileHeader
|
|
53
|
+
* title="User Details"
|
|
54
|
+
* subtitle="Profile"
|
|
55
|
+
* onBackClick={() => navigate(-1)}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example With right action
|
|
60
|
+
* ```tsx
|
|
61
|
+
* <MobileHeader
|
|
62
|
+
* title="Settings"
|
|
63
|
+
* onMenuClick={openMenu}
|
|
64
|
+
* rightAction={
|
|
65
|
+
* <Button variant="ghost" iconOnly onClick={save}>
|
|
66
|
+
* <Check className="w-5 h-5" />
|
|
67
|
+
* </Button>
|
|
68
|
+
* }
|
|
69
|
+
* />
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example Transparent with blur
|
|
73
|
+
* ```tsx
|
|
74
|
+
* <MobileHeader
|
|
75
|
+
* title="Photo Gallery"
|
|
76
|
+
* variant="blur"
|
|
77
|
+
* onBackClick={goBack}
|
|
78
|
+
* />
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export default function MobileHeader({ title, subtitle, onMenuClick, onBackClick, onCloseClick, rightAction, leftAction, sticky, bordered, variant, className, safeArea, }: MobileHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
82
|
+
/**
|
|
83
|
+
* MobileHeaderSpacer - Spacer to prevent content from being hidden behind sticky MobileHeader
|
|
84
|
+
*
|
|
85
|
+
* Place this at the top of your content when NOT using sticky header
|
|
86
|
+
* to maintain consistent spacing.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```tsx
|
|
90
|
+
* <MobileHeader title="Page" sticky={false} />
|
|
91
|
+
* <MobileHeaderSpacer />
|
|
92
|
+
* <main>Content here</main>
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function MobileHeaderSpacer({ safeArea }: {
|
|
96
|
+
safeArea?: boolean;
|
|
97
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
98
|
+
//# sourceMappingURL=MobileHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MobileHeader.d.ts","sourceRoot":"","sources":["../../src/components/MobileHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,qDAAqD;IACrD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,mEAAmE;IACnE,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,gCAAgC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uBAAuB;IACvB,OAAO,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,MAAM,CAAC;IAC3C,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,KAAK,EACL,QAAQ,EACR,WAAW,EACX,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,MAAa,EACb,QAAe,EACf,OAAiB,EACjB,SAAc,EACd,QAAe,GAChB,EAAE,iBAAiB,2CAkHnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,QAAe,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,2CAO7E"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SidebarItem } from './Sidebar';
|
|
3
|
+
import { MobileHeaderProps } from './MobileHeader';
|
|
4
|
+
import { BottomNavItem } from './BottomNavigation';
|
|
5
|
+
export interface Section {
|
|
6
|
+
/** Unique identifier for the section */
|
|
7
|
+
id: string;
|
|
8
|
+
/** Display label for the section in navigation */
|
|
9
|
+
label: string;
|
|
10
|
+
}
|
|
11
|
+
export interface MobileLayoutProps {
|
|
12
|
+
/** Main page content */
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
/** Sidebar navigation items (required for both desktop sidebar and mobile drawer) */
|
|
15
|
+
sidebarItems: SidebarItem[];
|
|
16
|
+
/** Current active path for highlighting */
|
|
17
|
+
currentPath?: string;
|
|
18
|
+
/** Handler for navigation clicks */
|
|
19
|
+
onNavigate?: (href: string) => void;
|
|
20
|
+
/** Header component for sidebar (logo, branding, etc.) */
|
|
21
|
+
header?: React.ReactNode;
|
|
22
|
+
/** User profile button for sidebar footer */
|
|
23
|
+
userProfile?: React.ReactNode;
|
|
24
|
+
/** Additional sidebar content */
|
|
25
|
+
sidebarFooter?: React.ReactNode;
|
|
26
|
+
/** Title displayed in mobile header (required for mobile layout) */
|
|
27
|
+
title: string;
|
|
28
|
+
/** Subtitle displayed in mobile header */
|
|
29
|
+
subtitle?: string;
|
|
30
|
+
/** Right action for mobile header */
|
|
31
|
+
headerRightAction?: React.ReactNode;
|
|
32
|
+
/** Custom left action for mobile header (overrides menu button) */
|
|
33
|
+
headerLeftAction?: React.ReactNode;
|
|
34
|
+
/** Mobile header variant */
|
|
35
|
+
headerVariant?: MobileHeaderProps['variant'];
|
|
36
|
+
/** Bottom navigation items for mobile (if not provided, uses sidebarItems) */
|
|
37
|
+
bottomNavItems?: BottomNavItem[];
|
|
38
|
+
/** Active bottom nav item ID */
|
|
39
|
+
activeBottomNavId?: string;
|
|
40
|
+
/** Show labels on bottom nav */
|
|
41
|
+
showBottomNavLabels?: boolean;
|
|
42
|
+
/** Optional status bar component displayed at the bottom (desktop only) */
|
|
43
|
+
statusBar?: React.ReactNode;
|
|
44
|
+
/** Additional CSS classes */
|
|
45
|
+
className?: string;
|
|
46
|
+
/** Page sections for navigation dots in desktop gutter */
|
|
47
|
+
sections?: Section[];
|
|
48
|
+
/** Force mobile layout even on desktop */
|
|
49
|
+
forceMobile?: boolean;
|
|
50
|
+
/** Force desktop layout even on mobile */
|
|
51
|
+
forceDesktop?: boolean;
|
|
52
|
+
/** Hide bottom navigation on mobile */
|
|
53
|
+
hideBottomNav?: boolean;
|
|
54
|
+
/** Hide mobile header */
|
|
55
|
+
hideMobileHeader?: boolean;
|
|
56
|
+
/** Use safe area insets for notched devices */
|
|
57
|
+
safeArea?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* MobileLayout - Auto-responsive layout that switches between desktop and mobile patterns
|
|
61
|
+
*
|
|
62
|
+
* This component automatically detects the viewport size and renders the appropriate layout:
|
|
63
|
+
* - **Desktop** (≥1024px): Standard Layout with sidebar, gutter, and scrollable content
|
|
64
|
+
* - **Mobile/Tablet** (<1024px): Mobile header, drawer navigation, bottom tab bar
|
|
65
|
+
*
|
|
66
|
+
* The mobile layout features:
|
|
67
|
+
* - Sticky header with hamburger menu to open drawer
|
|
68
|
+
* - Sidebar rendered as a slide-in drawer
|
|
69
|
+
* - Bottom navigation bar for primary navigation
|
|
70
|
+
* - Safe area support for notched devices
|
|
71
|
+
*
|
|
72
|
+
* @example Basic usage
|
|
73
|
+
* ```tsx
|
|
74
|
+
* <MobileLayout
|
|
75
|
+
* sidebarItems={[
|
|
76
|
+
* { id: 'home', label: 'Home', icon: <Home />, href: '/' },
|
|
77
|
+
* { id: 'tasks', label: 'Tasks', icon: <CheckSquare />, href: '/tasks' },
|
|
78
|
+
* { id: 'settings', label: 'Settings', icon: <Settings />, href: '/settings' }
|
|
79
|
+
* ]}
|
|
80
|
+
* currentPath={location.pathname}
|
|
81
|
+
* onNavigate={(href) => navigate(href)}
|
|
82
|
+
* title="My App"
|
|
83
|
+
* header={<Logo />}
|
|
84
|
+
* userProfile={<UserProfileButton user={user} />}
|
|
85
|
+
* >
|
|
86
|
+
* <Page>
|
|
87
|
+
* <h1>Dashboard</h1>
|
|
88
|
+
* </Page>
|
|
89
|
+
* </MobileLayout>
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @example With custom bottom nav items
|
|
93
|
+
* ```tsx
|
|
94
|
+
* <MobileLayout
|
|
95
|
+
* sidebarItems={fullNavItems}
|
|
96
|
+
* bottomNavItems={[
|
|
97
|
+
* { id: 'home', label: 'Home', icon: <Home />, href: '/' },
|
|
98
|
+
* { id: 'search', label: 'Search', icon: <Search />, href: '/search' },
|
|
99
|
+
* { id: 'profile', label: 'Profile', icon: <User />, href: '/profile' }
|
|
100
|
+
* ]}
|
|
101
|
+
* currentPath={location.pathname}
|
|
102
|
+
* title="My App"
|
|
103
|
+
* >
|
|
104
|
+
* {children}
|
|
105
|
+
* </MobileLayout>
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example Force mobile layout for testing
|
|
109
|
+
* ```tsx
|
|
110
|
+
* <MobileLayout
|
|
111
|
+
* sidebarItems={items}
|
|
112
|
+
* title="Mobile Preview"
|
|
113
|
+
* forceMobile
|
|
114
|
+
* >
|
|
115
|
+
* {children}
|
|
116
|
+
* </MobileLayout>
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare const MobileLayout: React.FC<MobileLayoutProps>;
|
|
120
|
+
export default MobileLayout;
|
|
121
|
+
//# sourceMappingURL=MobileLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MobileLayout.d.ts","sourceRoot":"","sources":["../../src/components/MobileLayout.tsx"],"names":[],"mappings":"AAIA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACjD,OAAqB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAyB,EAAE,aAAa,EAA0B,MAAM,oBAAoB,CAAC;AAG7F,MAAM,WAAW,OAAO;IACtB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,wBAAwB;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAG1B,qFAAqF;IACrF,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,iCAAiC;IACjC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAGhC,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACpC,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACnC,4BAA4B;IAC5B,aAAa,CAAC,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAG7C,8EAA8E;IAC9E,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,gCAAgC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gCAAgC;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAG9B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA+KpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -8,8 +8,57 @@ export interface ModalProps {
|
|
|
8
8
|
showCloseButton?: boolean;
|
|
9
9
|
/** Animation variant for modal entrance (default: 'scale') */
|
|
10
10
|
animation?: 'scale' | 'slide-up' | 'slide-down' | 'fade' | 'none';
|
|
11
|
+
/** Mobile display mode: 'auto' uses BottomSheet on mobile, 'modal' always uses modal, 'sheet' always uses BottomSheet */
|
|
12
|
+
mobileMode?: 'auto' | 'modal' | 'sheet';
|
|
13
|
+
/** Height preset for BottomSheet on mobile (default: 'lg') */
|
|
14
|
+
mobileHeight?: 'sm' | 'md' | 'lg' | 'full';
|
|
15
|
+
/** Show drag handle on BottomSheet (default: true) */
|
|
16
|
+
mobileShowHandle?: boolean;
|
|
11
17
|
}
|
|
12
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Modal - Adaptive dialog component
|
|
20
|
+
*
|
|
21
|
+
* On desktop, renders as a centered modal dialog.
|
|
22
|
+
* On mobile (when mobileMode='auto'), automatically renders as a BottomSheet
|
|
23
|
+
* for better touch interaction and visibility.
|
|
24
|
+
*
|
|
25
|
+
* @example Basic modal
|
|
26
|
+
* ```tsx
|
|
27
|
+
* <Modal isOpen={isOpen} onClose={handleClose} title="Edit User">
|
|
28
|
+
* <form>...</form>
|
|
29
|
+
* <ModalFooter>
|
|
30
|
+
* <Button onClick={handleClose}>Cancel</Button>
|
|
31
|
+
* <Button variant="primary" onClick={handleSave}>Save</Button>
|
|
32
|
+
* </ModalFooter>
|
|
33
|
+
* </Modal>
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example Force modal on mobile
|
|
37
|
+
* ```tsx
|
|
38
|
+
* <Modal
|
|
39
|
+
* isOpen={isOpen}
|
|
40
|
+
* onClose={handleClose}
|
|
41
|
+
* title="Settings"
|
|
42
|
+
* mobileMode="modal"
|
|
43
|
+
* >
|
|
44
|
+
* ...
|
|
45
|
+
* </Modal>
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example Always use BottomSheet
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <Modal
|
|
51
|
+
* isOpen={isOpen}
|
|
52
|
+
* onClose={handleClose}
|
|
53
|
+
* title="Select Option"
|
|
54
|
+
* mobileMode="sheet"
|
|
55
|
+
* mobileHeight="md"
|
|
56
|
+
* >
|
|
57
|
+
* ...
|
|
58
|
+
* </Modal>
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export default function Modal({ isOpen, onClose, title, children, size, showCloseButton, animation, mobileMode, mobileHeight, mobileShowHandle, }: ModalProps): import("react/jsx-runtime").JSX.Element | null;
|
|
13
62
|
export declare function ModalFooter({ children }: {
|
|
14
63
|
children: React.ReactNode;
|
|
15
64
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/components/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/components/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmC,MAAM,OAAO,CAAC;AAKxD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC1C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;IAGlE,yHAAyH;IACzH,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACxC,8DAA8D;IAC9D,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC3C,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,KAAK,EACL,QAAQ,EACR,IAAW,EACX,eAAsB,EACtB,SAAmB,EACnB,UAAmB,EACnB,YAAmB,EACnB,gBAAuB,GACxB,EAAE,UAAU,kDAwHZ;AAED,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAMtE"}
|