@oxyhq/bloom 0.50.1 → 0.50.2
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/lib/commonjs/bottom-sheet/index.web.js +3 -2
- package/lib/commonjs/bottom-sheet/index.web.js.map +1 -1
- package/lib/commonjs/context-menu/index.web.js +3 -7
- package/lib/commonjs/context-menu/index.web.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.js +12 -7
- package/lib/commonjs/dialog/Dialog.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.web.js +14 -19
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/dialog/DialogHeader.js +61 -12
- package/lib/commonjs/dialog/DialogHeader.js.map +1 -1
- package/lib/commonjs/menu/index.web.js +3 -7
- package/lib/commonjs/menu/index.web.js.map +1 -1
- package/lib/commonjs/popover/index.web.js +5 -7
- package/lib/commonjs/popover/index.web.js.map +1 -1
- package/lib/commonjs/select/index.web.js +3 -7
- package/lib/commonjs/select/index.web.js.map +1 -1
- package/lib/commonjs/slider/Slider.js +4 -9
- package/lib/commonjs/slider/Slider.js.map +1 -1
- package/lib/commonjs/switch/Switch.js +4 -8
- package/lib/commonjs/switch/Switch.js.map +1 -1
- package/lib/commonjs/tabs/Tabs.js +3 -8
- package/lib/commonjs/tabs/Tabs.js.map +1 -1
- package/lib/commonjs/toast/Toast.js +3 -8
- package/lib/commonjs/toast/Toast.js.map +1 -1
- package/lib/module/bottom-sheet/index.web.js +3 -2
- package/lib/module/bottom-sheet/index.web.js.map +1 -1
- package/lib/module/context-menu/index.web.js +3 -7
- package/lib/module/context-menu/index.web.js.map +1 -1
- package/lib/module/dialog/Dialog.js +12 -7
- package/lib/module/dialog/Dialog.js.map +1 -1
- package/lib/module/dialog/Dialog.web.js +14 -19
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/dialog/DialogHeader.js +61 -12
- package/lib/module/dialog/DialogHeader.js.map +1 -1
- package/lib/module/menu/index.web.js +3 -7
- package/lib/module/menu/index.web.js.map +1 -1
- package/lib/module/popover/index.web.js +5 -7
- package/lib/module/popover/index.web.js.map +1 -1
- package/lib/module/select/index.web.js +3 -7
- package/lib/module/select/index.web.js.map +1 -1
- package/lib/module/slider/Slider.js +4 -9
- package/lib/module/slider/Slider.js.map +1 -1
- package/lib/module/switch/Switch.js +4 -8
- package/lib/module/switch/Switch.js.map +1 -1
- package/lib/module/tabs/Tabs.js +3 -8
- package/lib/module/tabs/Tabs.js.map +1 -1
- package/lib/module/toast/Toast.js +3 -8
- package/lib/module/toast/Toast.js.map +1 -1
- package/lib/typescript/commonjs/context-menu/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/DialogHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/menu/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/popover/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/select/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/slider/Slider.d.ts.map +1 -1
- package/lib/typescript/commonjs/switch/Switch.d.ts.map +1 -1
- package/lib/typescript/commonjs/tabs/Tabs.d.ts.map +1 -1
- package/lib/typescript/commonjs/toast/Toast.d.ts.map +1 -1
- package/lib/typescript/module/context-menu/index.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/DialogHeader.d.ts.map +1 -1
- package/lib/typescript/module/menu/index.web.d.ts.map +1 -1
- package/lib/typescript/module/popover/index.web.d.ts.map +1 -1
- package/lib/typescript/module/select/index.web.d.ts.map +1 -1
- package/lib/typescript/module/slider/Slider.d.ts.map +1 -1
- package/lib/typescript/module/switch/Switch.d.ts.map +1 -1
- package/lib/typescript/module/tabs/Tabs.d.ts.map +1 -1
- package/lib/typescript/module/toast/Toast.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/bottom-sheet/index.web.tsx +1 -1
- package/src/context-menu/index.web.tsx +3 -4
- package/src/dialog/Dialog.tsx +7 -4
- package/src/dialog/Dialog.web.tsx +10 -11
- package/src/dialog/DialogHeader.tsx +72 -17
- package/src/menu/index.web.tsx +3 -4
- package/src/popover/index.web.tsx +5 -4
- package/src/select/index.web.tsx +3 -4
- package/src/slider/Slider.tsx +3 -5
- package/src/switch/Switch.tsx +4 -5
- package/src/tabs/Tabs.tsx +3 -5
- package/src/toast/Toast.tsx +3 -5
|
@@ -106,6 +106,62 @@ interface HeaderStore {
|
|
|
106
106
|
subscribe: (listener: () => void) => () => void;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
type PrimaryAction = NonNullable<DialogHeaderConfig['primaryAction']>;
|
|
110
|
+
type HeaderAction = NonNullable<DialogHeaderConfig['actions']>[number];
|
|
111
|
+
type HeaderSearch = NonNullable<DialogHeaderConfig['search']>;
|
|
112
|
+
type HeaderSegments = NonNullable<DialogHeaderConfig['segments']>;
|
|
113
|
+
type HeaderProgress = NonNullable<DialogHeaderConfig['progress']>;
|
|
114
|
+
|
|
115
|
+
function primaryActionEqual(a: PrimaryAction | undefined, b: PrimaryAction | undefined): boolean {
|
|
116
|
+
if (a === b) return true;
|
|
117
|
+
if (!a || !b) return false;
|
|
118
|
+
// `onPress` is a fresh closure each render — its identity never changes what the
|
|
119
|
+
// button renders, so compare only the render-affecting scalars.
|
|
120
|
+
return a.label === b.label && !!a.disabled === !!b.disabled && !!a.loading === !!b.loading;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function actionsEqual(a: HeaderAction[] | undefined, b: HeaderAction[] | undefined): boolean {
|
|
124
|
+
if (a === b) return true;
|
|
125
|
+
if (!a || !b || a.length !== b.length) return false;
|
|
126
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
127
|
+
const x = a[i];
|
|
128
|
+
const y = b[i];
|
|
129
|
+
if (!x || !y) return false;
|
|
130
|
+
// `icon` is a memoized node (compared by identity); `onPress` is ignored.
|
|
131
|
+
if (
|
|
132
|
+
x.accessibilityLabel !== y.accessibilityLabel ||
|
|
133
|
+
!!x.disabled !== !!y.disabled ||
|
|
134
|
+
x.icon !== y.icon
|
|
135
|
+
) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function searchEqual(a: HeaderSearch | undefined, b: HeaderSearch | undefined): boolean {
|
|
143
|
+
if (a === b) return true;
|
|
144
|
+
if (!a || !b) return false;
|
|
145
|
+
return a.value === b.value && a.placeholder === b.placeholder;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function segmentsEqual(a: HeaderSegments | undefined, b: HeaderSegments | undefined): boolean {
|
|
149
|
+
if (a === b) return true;
|
|
150
|
+
if (!a || !b || a.value !== b.value || a.items.length !== b.items.length) return false;
|
|
151
|
+
for (let i = 0; i < a.items.length; i += 1) {
|
|
152
|
+
const ai = a.items[i];
|
|
153
|
+
const bi = b.items[i];
|
|
154
|
+
if (!ai || !bi || ai.key !== bi.key || ai.label !== bi.label) return false;
|
|
155
|
+
}
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function progressEqual(a: HeaderProgress | undefined, b: HeaderProgress | undefined): boolean {
|
|
160
|
+
if (a === b) return true;
|
|
161
|
+
if (!a || !b) return false;
|
|
162
|
+
return a.step === b.step && a.total === b.total;
|
|
163
|
+
}
|
|
164
|
+
|
|
109
165
|
function configsEqual(a: DialogHeaderConfig | null, b: DialogHeaderConfig | null): boolean {
|
|
110
166
|
if (a === b) return true;
|
|
111
167
|
if (!a || !b) return false;
|
|
@@ -116,16 +172,20 @@ function configsEqual(a: DialogHeaderConfig | null, b: DialogHeaderConfig | null
|
|
|
116
172
|
a.largeTitle === b.largeTitle &&
|
|
117
173
|
a.left === b.left &&
|
|
118
174
|
a.right === b.right &&
|
|
119
|
-
|
|
175
|
+
// `onBack` legitimately gets a fresh closure each render; its identity never
|
|
176
|
+
// changes what the header renders, so compare by PRESENCE, never identity —
|
|
177
|
+
// treating a new ref as "changed" is exactly what drives the update loop.
|
|
178
|
+
!!a.onBack === !!b.onBack &&
|
|
120
179
|
a.showClose === b.showClose &&
|
|
121
|
-
// Rich fields —
|
|
122
|
-
// `
|
|
123
|
-
a
|
|
124
|
-
a.actions === b.actions &&
|
|
125
|
-
a.search === b.search &&
|
|
126
|
-
a.segments === b.segments &&
|
|
180
|
+
// Rich fields — compared by VALUE (render-affecting scalars only). A caller
|
|
181
|
+
// passing an inline `primaryAction`/`actions`/… object (a fresh reference
|
|
182
|
+
// every render) must NOT force a store update: that is React error #185.
|
|
127
183
|
a.tone === b.tone &&
|
|
128
|
-
a.
|
|
184
|
+
primaryActionEqual(a.primaryAction, b.primaryAction) &&
|
|
185
|
+
actionsEqual(a.actions, b.actions) &&
|
|
186
|
+
searchEqual(a.search, b.search) &&
|
|
187
|
+
segmentsEqual(a.segments, b.segments) &&
|
|
188
|
+
progressEqual(a.progress, b.progress)
|
|
129
189
|
);
|
|
130
190
|
}
|
|
131
191
|
|
|
@@ -474,28 +534,23 @@ export const DialogNavHeader = memo(function DialogNavHeader({
|
|
|
474
534
|
) : null);
|
|
475
535
|
|
|
476
536
|
return (
|
|
477
|
-
<View
|
|
478
|
-
pointerEvents="box-none"
|
|
479
|
-
style={[styles.overlay, style]}
|
|
480
|
-
>
|
|
537
|
+
<View style={[styles.overlay, style, { pointerEvents: 'box-none' }]}>
|
|
481
538
|
{/* Opaque (surface bg) at the top → transparent at the bottom, so scrolled
|
|
482
539
|
content fades out under the bar. `onImage` swaps to a dark scrim so the
|
|
483
540
|
chrome reads over media. Pure NativeWind — no SVG dependency. */}
|
|
484
541
|
<View
|
|
485
|
-
pointerEvents="none"
|
|
486
542
|
className={
|
|
487
543
|
onImage
|
|
488
544
|
? 'bg-gradient-to-b from-black/60 to-transparent'
|
|
489
545
|
: 'bg-gradient-to-b from-bg to-transparent'
|
|
490
546
|
}
|
|
491
|
-
style={[StyleSheet.absoluteFill, { height: DIALOG_HEADER_OVERLAY_HEIGHT }]}
|
|
547
|
+
style={[StyleSheet.absoluteFill, { height: DIALOG_HEADER_OVERLAY_HEIGHT, pointerEvents: 'none' }]}
|
|
492
548
|
/>
|
|
493
|
-
<View
|
|
549
|
+
<View style={[styles.navRow, { pointerEvents: 'box-none' }]}>
|
|
494
550
|
<View style={styles.side}>{left}</View>
|
|
495
551
|
<Animated.View
|
|
496
|
-
pointerEvents="none"
|
|
497
552
|
testID="dialog-nav-title"
|
|
498
|
-
style={[styles.centerTitle, titleStyle]}
|
|
553
|
+
style={[styles.centerTitle, titleStyle, { pointerEvents: 'none' }]}
|
|
499
554
|
>
|
|
500
555
|
{config.titleContent ?? null}
|
|
501
556
|
{!config.titleContent && config.title ? (
|
package/src/menu/index.web.tsx
CHANGED
|
@@ -17,6 +17,7 @@ import { Text } from '../typography';
|
|
|
17
17
|
import type { DialogControlProps } from '../dialog/types';
|
|
18
18
|
import { Portal } from '../portal/index.web';
|
|
19
19
|
import { createDropdownZIndex } from '../styles/z-index';
|
|
20
|
+
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
20
21
|
import {
|
|
21
22
|
MenuContext,
|
|
22
23
|
ItemContext,
|
|
@@ -255,7 +256,7 @@ export function MenuContent({
|
|
|
255
256
|
? theme.colors.backgroundSecondary
|
|
256
257
|
: theme.colors.background,
|
|
257
258
|
borderColor: theme.colors.borderLight,
|
|
258
|
-
|
|
259
|
+
...bloomShadowStyle('m'),
|
|
259
260
|
},
|
|
260
261
|
style,
|
|
261
262
|
styles.portaledDropdown,
|
|
@@ -393,9 +394,7 @@ const styles = StyleSheet.create({
|
|
|
393
394
|
borderWidth: 1,
|
|
394
395
|
overflow: 'hidden',
|
|
395
396
|
zIndex: menuZIndex.surface,
|
|
396
|
-
|
|
397
|
-
shadowRadius: 12,
|
|
398
|
-
shadowOffset: { width: 0, height: 4 },
|
|
397
|
+
// Overlay elevation applied at the usage site via `bloomShadowStyle('m')`.
|
|
399
398
|
minWidth: 180,
|
|
400
399
|
},
|
|
401
400
|
portaledDropdown: {
|
|
@@ -12,6 +12,7 @@ import { Pressable, StyleSheet, View } from 'react-native';
|
|
|
12
12
|
import { useTheme } from '../theme/use-theme';
|
|
13
13
|
import { Portal } from '../portal/index.web';
|
|
14
14
|
import { createOverlayZIndex } from '../styles/z-index';
|
|
15
|
+
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
15
16
|
import { PopoverContext, usePopoverContext } from './context';
|
|
16
17
|
import type {
|
|
17
18
|
PopoverContentProps,
|
|
@@ -288,7 +289,9 @@ export function PopoverContent({
|
|
|
288
289
|
? theme.colors.backgroundSecondary
|
|
289
290
|
: theme.colors.background,
|
|
290
291
|
borderColor: theme.colors.borderLight,
|
|
291
|
-
|
|
292
|
+
// Design-system overlay elevation (`shadow-m`) as a `boxShadow` —
|
|
293
|
+
// RN-Web deprecated the `shadow*` style props.
|
|
294
|
+
...bloomShadowStyle('m'),
|
|
292
295
|
// Hide until measured to avoid a one-frame jump.
|
|
293
296
|
opacity: panelSize ? 1 : 0,
|
|
294
297
|
},
|
|
@@ -320,9 +323,7 @@ const styles = StyleSheet.create({
|
|
|
320
323
|
borderWidth: 1,
|
|
321
324
|
paddingVertical: 4,
|
|
322
325
|
overflow: 'hidden',
|
|
323
|
-
|
|
324
|
-
shadowRadius: 12,
|
|
325
|
-
shadowOffset: { width: 0, height: 4 },
|
|
326
|
+
// Elevation applied at the usage site via `bloomShadowStyle('m')` (boxShadow).
|
|
326
327
|
pointerEvents: 'auto',
|
|
327
328
|
},
|
|
328
329
|
});
|
package/src/select/index.web.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import { useTheme } from '../theme/use-theme';
|
|
|
5
5
|
import { Text } from '../typography';
|
|
6
6
|
import { Portal } from '../portal/index.web';
|
|
7
7
|
import { createOverlayZIndex } from '../styles/z-index';
|
|
8
|
+
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
8
9
|
import { RadioIndicator } from '../radio-indicator';
|
|
9
10
|
import { useInteractionState } from '../hooks/useInteractionState';
|
|
10
11
|
import {
|
|
@@ -201,7 +202,7 @@ export function SelectContent<T>({
|
|
|
201
202
|
? theme.colors.backgroundSecondary
|
|
202
203
|
: theme.colors.background,
|
|
203
204
|
borderColor: theme.colors.borderLight,
|
|
204
|
-
|
|
205
|
+
...bloomShadowStyle('m'),
|
|
205
206
|
},
|
|
206
207
|
]}
|
|
207
208
|
>
|
|
@@ -348,9 +349,7 @@ const styles = StyleSheet.create({
|
|
|
348
349
|
overflow: 'hidden',
|
|
349
350
|
padding: 4,
|
|
350
351
|
minWidth: 180,
|
|
351
|
-
|
|
352
|
-
shadowRadius: 12,
|
|
353
|
-
shadowOffset: { width: 0, height: 4 },
|
|
352
|
+
// Overlay elevation applied at the usage site via `bloomShadowStyle('m')`.
|
|
354
353
|
// Opt back in from the Portal root's `pointer-events: none`.
|
|
355
354
|
pointerEvents: 'auto',
|
|
356
355
|
},
|
package/src/slider/Slider.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
|
|
13
13
|
import { useTheme } from '../theme/use-theme';
|
|
14
14
|
import { animation } from '../styles/tokens';
|
|
15
|
+
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
15
16
|
import type { SliderProps } from './types';
|
|
16
17
|
|
|
17
18
|
function clamp(v: number, min: number, max: number): number {
|
|
@@ -236,7 +237,6 @@ const SliderComponent = function Slider({
|
|
|
236
237
|
backgroundColor: thumbColor,
|
|
237
238
|
left: thumbLeft,
|
|
238
239
|
transform: [{ scale: thumbScale }],
|
|
239
|
-
shadowColor: theme.colors.shadow,
|
|
240
240
|
},
|
|
241
241
|
]}
|
|
242
242
|
/>
|
|
@@ -261,10 +261,8 @@ const styles = StyleSheet.create({
|
|
|
261
261
|
thumb: {
|
|
262
262
|
position: 'absolute',
|
|
263
263
|
top: '50%',
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
shadowRadius: 2,
|
|
267
|
-
elevation: 2,
|
|
264
|
+
// Subtle raise (`shadow-s`) — `boxShadow` on web, RN shadow/elevation on native.
|
|
265
|
+
...bloomShadowStyle('s'),
|
|
268
266
|
},
|
|
269
267
|
disabled: {
|
|
270
268
|
opacity: 0.5,
|
package/src/switch/Switch.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { Pressable, Animated, StyleSheet } from 'react-native';
|
|
|
3
3
|
|
|
4
4
|
import { useTheme } from '../theme/use-theme';
|
|
5
5
|
import { animation } from '../styles/tokens';
|
|
6
|
+
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
6
7
|
import type { SwitchProps } from './types';
|
|
7
8
|
|
|
8
9
|
const TRACK = { default: { w: 44, h: 26 }, sm: { w: 36, h: 22 } } as const;
|
|
@@ -128,10 +129,8 @@ const styles = StyleSheet.create({
|
|
|
128
129
|
},
|
|
129
130
|
thumb: {
|
|
130
131
|
backgroundColor: '#fff',
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
shadowRadius: 3,
|
|
135
|
-
elevation: 3,
|
|
132
|
+
// Subtle raise (`shadow-s`) — `boxShadow` on web (RN-Web deprecated `shadow*`),
|
|
133
|
+
// RN elevation/shadow on native.
|
|
134
|
+
...bloomShadowStyle('s'),
|
|
136
135
|
},
|
|
137
136
|
});
|
package/src/tabs/Tabs.tsx
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
import { useTheme } from '../theme/use-theme';
|
|
23
23
|
import { usePressAnimation } from '../hooks/usePressAnimation';
|
|
24
24
|
import { borderRadius, space } from '../styles/tokens';
|
|
25
|
+
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
25
26
|
import type { TabsProps, TabsTriggerProps, TabsContentProps, TabsVariant } from './types';
|
|
26
27
|
|
|
27
28
|
type TriggerLayout = Pick<LayoutRectangle, 'x' | 'width'>;
|
|
@@ -226,11 +227,8 @@ const TabComponent: React.FC<TabsTriggerProps> = ({
|
|
|
226
227
|
if (isSelected) {
|
|
227
228
|
base.backgroundColor = theme.colors.card;
|
|
228
229
|
base.borderRadius = borderRadius.xs + 2;
|
|
229
|
-
|
|
230
|
-
base
|
|
231
|
-
base.shadowOpacity = 0.1;
|
|
232
|
-
base.shadowRadius = 2;
|
|
233
|
-
base.elevation = 1;
|
|
230
|
+
// Subtle raise (`shadow-s`) — `boxShadow` on web, RN shadow/elevation on native.
|
|
231
|
+
Object.assign(base, bloomShadowStyle('s'));
|
|
234
232
|
}
|
|
235
233
|
break;
|
|
236
234
|
case 'outlined':
|
package/src/toast/Toast.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
import { useTheme } from '../theme/use-theme';
|
|
11
11
|
import { useInteractionState } from '../hooks/useInteractionState';
|
|
12
|
+
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
12
13
|
import type { ThemeColors } from '../theme/types';
|
|
13
14
|
import { dismiss } from './sonner';
|
|
14
15
|
import type { ToastType } from './types';
|
|
@@ -242,11 +243,8 @@ const styles = StyleSheet.create({
|
|
|
242
243
|
flexDirection: 'row',
|
|
243
244
|
gap: 8,
|
|
244
245
|
paddingVertical: 14,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
shadowOpacity: 0.05,
|
|
248
|
-
shadowRadius: 2,
|
|
249
|
-
elevation: 2,
|
|
246
|
+
// Subtle raise (`shadow-s`) — `boxShadow` on web, RN shadow/elevation on native.
|
|
247
|
+
...bloomShadowStyle('s'),
|
|
250
248
|
},
|
|
251
249
|
textContainer: {
|
|
252
250
|
flex: 1,
|