@scripso-homepad/ui 0.4.28 → 0.4.30
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/index.cjs +10 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +10 -5
- package/dist/index.js.map +1 -1
- package/dist/web/index.cjs +23 -6
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.d.cts +3 -1
- package/dist/web/index.d.ts +3 -1
- package/dist/web/index.js +23 -6
- package/dist/web/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CountryCodeSelector.tsx +9 -3
- package/src/components/PhoneInput.tsx +6 -0
- package/src/web/components/ConfirmModal.tsx +1 -1
- package/src/web/components/Drawer.tsx +25 -3
- package/src/web/layout/AppHeader.tsx +5 -0
- package/src/web/layout/SidebarNavItem.tsx +3 -1
package/package.json
CHANGED
|
@@ -42,6 +42,10 @@ export interface CountryCodeSelectorProps {
|
|
|
42
42
|
/** Country list (defaults to built-in list). */
|
|
43
43
|
options?: Country[];
|
|
44
44
|
disabled?: boolean;
|
|
45
|
+
/** Outer trigger height. Defaults to shared input height. */
|
|
46
|
+
height?: number;
|
|
47
|
+
/** Trigger border color. Defaults to shared input border token. */
|
|
48
|
+
borderColor?: string;
|
|
45
49
|
style?: StyleProp<ViewStyle>;
|
|
46
50
|
className?: string;
|
|
47
51
|
}
|
|
@@ -70,6 +74,8 @@ export function CountryCodeSelector({
|
|
|
70
74
|
onValueChange,
|
|
71
75
|
options = countries,
|
|
72
76
|
disabled = false,
|
|
77
|
+
height = TRIGGER_HEIGHT,
|
|
78
|
+
borderColor = colors.stormGray50,
|
|
73
79
|
style,
|
|
74
80
|
className,
|
|
75
81
|
}: CountryCodeSelectorProps) {
|
|
@@ -157,6 +163,7 @@ export function CountryCodeSelector({
|
|
|
157
163
|
onPress={handleOpen}
|
|
158
164
|
style={[
|
|
159
165
|
styles.trigger,
|
|
166
|
+
{ height, borderColor },
|
|
160
167
|
disabled ? styles.triggerDisabled : styles.triggerEnabled,
|
|
161
168
|
Platform.OS === "web" ? styles.triggerWeb : null,
|
|
162
169
|
]}
|
|
@@ -207,15 +214,14 @@ const styles = StyleSheet.create({
|
|
|
207
214
|
height: TRIGGER_HEIGHT,
|
|
208
215
|
borderRadius: radii.lg,
|
|
209
216
|
borderWidth: 1,
|
|
210
|
-
|
|
217
|
+
paddingHorizontal: spacing.lg,
|
|
218
|
+
paddingVertical: 0,
|
|
211
219
|
gap: spacing.sm,
|
|
212
220
|
},
|
|
213
221
|
triggerEnabled: {
|
|
214
|
-
borderColor: colors.stormGray50,
|
|
215
222
|
backgroundColor: colors.white,
|
|
216
223
|
},
|
|
217
224
|
triggerDisabled: {
|
|
218
|
-
borderColor: colors.stormGray50,
|
|
219
225
|
backgroundColor: colors.stormGray50,
|
|
220
226
|
},
|
|
221
227
|
triggerWeb: {
|
|
@@ -16,6 +16,7 @@ import { Label } from "./Label";
|
|
|
16
16
|
import {
|
|
17
17
|
getInputFieldStyles,
|
|
18
18
|
inputFieldMetrics,
|
|
19
|
+
INPUT_HEIGHT,
|
|
19
20
|
INPUT_ICON_GAP,
|
|
20
21
|
INPUT_OUTLINE_WIDTH,
|
|
21
22
|
resolveInputVisualState,
|
|
@@ -38,6 +39,8 @@ export interface PhoneInputProps extends Omit<TextInputProps, "style"> {
|
|
|
38
39
|
onCountryCodeChange?: (countryCode: string) => void;
|
|
39
40
|
error?: string;
|
|
40
41
|
hint?: string;
|
|
42
|
+
/** Outer field height for country trigger + national number. Defaults to shared input height. */
|
|
43
|
+
height?: number;
|
|
41
44
|
containerStyle?: StyleProp<ViewStyle>;
|
|
42
45
|
style?: StyleProp<TextStyle>;
|
|
43
46
|
className?: string;
|
|
@@ -60,6 +63,7 @@ export function PhoneInput({
|
|
|
60
63
|
onCountryCodeChange,
|
|
61
64
|
error,
|
|
62
65
|
hint,
|
|
66
|
+
height = INPUT_HEIGHT,
|
|
63
67
|
containerStyle,
|
|
64
68
|
style,
|
|
65
69
|
className,
|
|
@@ -124,6 +128,7 @@ export function PhoneInput({
|
|
|
124
128
|
value={countryCode}
|
|
125
129
|
onValueChange={onCountryCodeChange}
|
|
126
130
|
disabled={isDisabled}
|
|
131
|
+
height={height}
|
|
127
132
|
style={styles.countrySelector}
|
|
128
133
|
/>
|
|
129
134
|
</View>
|
|
@@ -132,6 +137,7 @@ export function PhoneInput({
|
|
|
132
137
|
style={[
|
|
133
138
|
inputFieldMetrics.containerBase,
|
|
134
139
|
inputFieldMetrics.container,
|
|
140
|
+
{ height },
|
|
135
141
|
phoneFieldStyles.container,
|
|
136
142
|
styles.phoneField,
|
|
137
143
|
]}
|
|
@@ -74,7 +74,7 @@ export function ConfirmModal({
|
|
|
74
74
|
aria-labelledby="homepad-confirm-modal-title"
|
|
75
75
|
aria-describedby="homepad-confirm-modal-description"
|
|
76
76
|
className={cn(
|
|
77
|
-
'flex w-full max-w-md flex-col gap-8 rounded-
|
|
77
|
+
'flex w-full max-w-md flex-col gap-8 rounded-3xl bg-white p-6 opacity-100 md:p-8',
|
|
78
78
|
containerClassName,
|
|
79
79
|
)}
|
|
80
80
|
onClick={(event) => {
|
|
@@ -71,10 +71,12 @@ export function Drawer({
|
|
|
71
71
|
}: DrawerProps) {
|
|
72
72
|
const [isPresent, setIsPresent] = useState(open);
|
|
73
73
|
const [isAnimatedIn, setIsAnimatedIn] = useState(false);
|
|
74
|
+
const [isTransformSettled, setIsTransformSettled] = useState(open);
|
|
74
75
|
|
|
75
76
|
useEffect(() => {
|
|
76
77
|
if (open) {
|
|
77
78
|
setIsPresent(true);
|
|
79
|
+
setIsTransformSettled(false);
|
|
78
80
|
|
|
79
81
|
const frame = window.requestAnimationFrame(() => {
|
|
80
82
|
window.requestAnimationFrame(() => {
|
|
@@ -82,18 +84,32 @@ export function Drawer({
|
|
|
82
84
|
});
|
|
83
85
|
});
|
|
84
86
|
|
|
87
|
+
const settleTimeout = window.setTimeout(() => {
|
|
88
|
+
setIsTransformSettled(true);
|
|
89
|
+
}, DRAWER_TRANSITION_MS);
|
|
90
|
+
|
|
85
91
|
return () => {
|
|
86
92
|
window.cancelAnimationFrame(frame);
|
|
93
|
+
window.clearTimeout(settleTimeout);
|
|
87
94
|
};
|
|
88
95
|
}
|
|
89
96
|
|
|
90
|
-
|
|
97
|
+
// Re-enable transform at the open position, then slide out.
|
|
98
|
+
setIsTransformSettled(false);
|
|
99
|
+
setIsAnimatedIn(true);
|
|
100
|
+
|
|
101
|
+
const frame = window.requestAnimationFrame(() => {
|
|
102
|
+
window.requestAnimationFrame(() => {
|
|
103
|
+
setIsAnimatedIn(false);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
91
106
|
|
|
92
107
|
const timeout = window.setTimeout(() => {
|
|
93
108
|
setIsPresent(false);
|
|
94
109
|
}, DRAWER_TRANSITION_MS);
|
|
95
110
|
|
|
96
111
|
return () => {
|
|
112
|
+
window.cancelAnimationFrame(frame);
|
|
97
113
|
window.clearTimeout(timeout);
|
|
98
114
|
};
|
|
99
115
|
}, [open]);
|
|
@@ -144,8 +160,14 @@ export function Drawer({
|
|
|
144
160
|
aria-labelledby="homepad-drawer-title"
|
|
145
161
|
{...(subtitle ? { 'aria-describedby': 'homepad-drawer-subtitle' } : {})}
|
|
146
162
|
className={cn(
|
|
147
|
-
'relative z-10 flex h-[calc(100dvh-16px)] min-h-0 flex-col overflow-hidden rounded-[16px] bg-white shadow-2xl transition-transform duration-300 ease-in-out
|
|
148
|
-
|
|
163
|
+
'relative z-10 flex h-[calc(100dvh-16px)] min-h-0 flex-col overflow-hidden rounded-[16px] bg-white shadow-2xl transition-transform duration-300 ease-in-out max-md:h-dvh max-md:rounded-none',
|
|
164
|
+
// Keep GPU transform only while animating — settled translate-x-0 blurs text.
|
|
165
|
+
!isTransformSettled && 'will-change-transform',
|
|
166
|
+
isAnimatedIn
|
|
167
|
+
? isTransformSettled
|
|
168
|
+
? 'transform-none'
|
|
169
|
+
: 'translate-x-0'
|
|
170
|
+
: 'translate-x-full',
|
|
149
171
|
widthClassName,
|
|
150
172
|
className,
|
|
151
173
|
)}
|
|
@@ -25,6 +25,8 @@ export type AppHeaderProps = {
|
|
|
25
25
|
notificationsIcon?: ReactNode;
|
|
26
26
|
searchIcon?: ReactNode;
|
|
27
27
|
buildingChevronIcon?: ReactNode;
|
|
28
|
+
/** Rendered before the building select (e.g. month period control). */
|
|
29
|
+
actions?: ReactNode;
|
|
28
30
|
buildingSelectDisabled?: boolean;
|
|
29
31
|
searchDisabled?: boolean;
|
|
30
32
|
notificationsDisabled?: boolean;
|
|
@@ -60,6 +62,7 @@ export function AppHeader({
|
|
|
60
62
|
notificationsIcon,
|
|
61
63
|
searchIcon,
|
|
62
64
|
buildingChevronIcon,
|
|
65
|
+
actions,
|
|
63
66
|
buildingSelectDisabled = false,
|
|
64
67
|
searchDisabled = false,
|
|
65
68
|
notificationsDisabled = false,
|
|
@@ -77,6 +80,8 @@ export function AppHeader({
|
|
|
77
80
|
<h1 className="truncate typography-title text-slate-blue">{title}</h1>
|
|
78
81
|
|
|
79
82
|
<div className="flex shrink-0 items-center gap-3">
|
|
83
|
+
{actions}
|
|
84
|
+
|
|
80
85
|
{hasBuildingSelect ? (
|
|
81
86
|
<BuildingSelect
|
|
82
87
|
options={buildingOptions}
|
|
@@ -38,7 +38,9 @@ export function SidebarNavItem({ item, isOpen, isActive, onNavigate }: SidebarNa
|
|
|
38
38
|
'relative flex items-center rounded-xl px-4 py-3 transition-[background-color,color,gap,padding] duration-300 ease-in-out',
|
|
39
39
|
isOpen ? 'w-full gap-4' : 'w-full justify-center gap-0 px-3',
|
|
40
40
|
item.disabled && 'pointer-events-none opacity-50',
|
|
41
|
-
isActive
|
|
41
|
+
isActive
|
|
42
|
+
? 'bg-black/12 text-white shadow-none'
|
|
43
|
+
: 'text-navy-100 shadow-none hover:bg-white/5',
|
|
42
44
|
)}
|
|
43
45
|
>
|
|
44
46
|
<span
|