@oxyhq/bloom 0.79.0 → 0.80.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/README.md +3 -3
- package/lib/commonjs/provider/index.js +11 -7
- package/lib/commonjs/provider/index.js.map +1 -1
- package/lib/commonjs/scroll/context.js +96 -0
- package/lib/commonjs/scroll/context.js.map +1 -0
- package/lib/commonjs/scroll/expo-router/index.js +133 -0
- package/lib/commonjs/scroll/expo-router/index.js.map +1 -0
- package/lib/commonjs/scroll/index.js +85 -21
- package/lib/commonjs/scroll/index.js.map +1 -1
- package/lib/commonjs/scroll/index.web.js +221 -121
- package/lib/commonjs/scroll/index.web.js.map +1 -1
- package/lib/commonjs/scroll/scrollable.native.js +58 -0
- package/lib/commonjs/scroll/scrollable.native.js.map +1 -0
- package/lib/commonjs/scroll/scrollable.web.js +9 -3
- package/lib/commonjs/scroll/scrollable.web.js.map +1 -1
- package/lib/commonjs/scroll/store.js +47 -25
- package/lib/commonjs/scroll/store.js.map +1 -1
- package/lib/commonjs/tabs/Tabs.js +263 -63
- package/lib/commonjs/tabs/Tabs.js.map +1 -1
- package/lib/commonjs/tabs/expo-router/RouterTabs.js +215 -0
- package/lib/commonjs/tabs/expo-router/RouterTabs.js.map +1 -0
- package/lib/commonjs/tabs/expo-router/index.js +13 -0
- package/lib/commonjs/tabs/expo-router/index.js.map +1 -0
- package/lib/commonjs/theme/color-policy.js +11 -10
- package/lib/commonjs/theme/color-policy.js.map +1 -1
- package/lib/module/provider/index.js +10 -6
- package/lib/module/provider/index.js.map +1 -1
- package/lib/module/scroll/context.js +90 -0
- package/lib/module/scroll/context.js.map +1 -0
- package/lib/module/scroll/expo-router/index.js +128 -0
- package/lib/module/scroll/expo-router/index.js.map +1 -0
- package/lib/module/scroll/index.js +80 -21
- package/lib/module/scroll/index.js.map +1 -1
- package/lib/module/scroll/index.web.js +218 -122
- package/lib/module/scroll/index.web.js.map +1 -1
- package/lib/module/scroll/scrollable.native.js +54 -0
- package/lib/module/scroll/scrollable.native.js.map +1 -0
- package/lib/module/scroll/scrollable.web.js +9 -3
- package/lib/module/scroll/scrollable.web.js.map +1 -1
- package/lib/module/scroll/store.js +47 -25
- package/lib/module/scroll/store.js.map +1 -1
- package/lib/module/tabs/Tabs.js +271 -65
- package/lib/module/tabs/Tabs.js.map +1 -1
- package/lib/module/tabs/expo-router/RouterTabs.js +210 -0
- package/lib/module/tabs/expo-router/RouterTabs.js.map +1 -0
- package/lib/module/tabs/expo-router/index.js +10 -0
- package/lib/module/tabs/expo-router/index.js.map +1 -0
- package/lib/module/theme/color-policy.js +11 -10
- package/lib/module/theme/color-policy.js.map +1 -1
- package/lib/typescript/commonjs/provider/index.d.ts +7 -5
- package/lib/typescript/commonjs/provider/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/scroll/context.d.ts +14 -0
- package/lib/typescript/commonjs/scroll/context.d.ts.map +1 -0
- package/lib/typescript/commonjs/scroll/expo-router/index.d.ts +7 -0
- package/lib/typescript/commonjs/scroll/expo-router/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/scroll/index.d.ts +14 -23
- package/lib/typescript/commonjs/scroll/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/scroll/index.web.d.ts +17 -19
- package/lib/typescript/commonjs/scroll/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/scroll/scrollable.native.d.ts +23 -0
- package/lib/typescript/commonjs/scroll/scrollable.native.d.ts.map +1 -0
- package/lib/typescript/commonjs/scroll/scrollable.web.d.ts +18 -5
- package/lib/typescript/commonjs/scroll/scrollable.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/scroll/store.d.ts +41 -22
- package/lib/typescript/commonjs/scroll/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/scroll/types.d.ts +82 -12
- package/lib/typescript/commonjs/scroll/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/tabs/Tabs.d.ts +41 -1
- package/lib/typescript/commonjs/tabs/Tabs.d.ts.map +1 -1
- package/lib/typescript/commonjs/tabs/expo-router/RouterTabs.d.ts +80 -0
- package/lib/typescript/commonjs/tabs/expo-router/RouterTabs.d.ts.map +1 -0
- package/lib/typescript/commonjs/tabs/expo-router/index.d.ts +9 -0
- package/lib/typescript/commonjs/tabs/expo-router/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/tabs/types.d.ts +48 -4
- package/lib/typescript/commonjs/tabs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-policy.d.ts.map +1 -1
- package/lib/typescript/module/provider/index.d.ts +7 -5
- package/lib/typescript/module/provider/index.d.ts.map +1 -1
- package/lib/typescript/module/scroll/context.d.ts +14 -0
- package/lib/typescript/module/scroll/context.d.ts.map +1 -0
- package/lib/typescript/module/scroll/expo-router/index.d.ts +7 -0
- package/lib/typescript/module/scroll/expo-router/index.d.ts.map +1 -0
- package/lib/typescript/module/scroll/index.d.ts +14 -23
- package/lib/typescript/module/scroll/index.d.ts.map +1 -1
- package/lib/typescript/module/scroll/index.web.d.ts +17 -19
- package/lib/typescript/module/scroll/index.web.d.ts.map +1 -1
- package/lib/typescript/module/scroll/scrollable.native.d.ts +23 -0
- package/lib/typescript/module/scroll/scrollable.native.d.ts.map +1 -0
- package/lib/typescript/module/scroll/scrollable.web.d.ts +18 -5
- package/lib/typescript/module/scroll/scrollable.web.d.ts.map +1 -1
- package/lib/typescript/module/scroll/store.d.ts +41 -22
- package/lib/typescript/module/scroll/store.d.ts.map +1 -1
- package/lib/typescript/module/scroll/types.d.ts +82 -12
- package/lib/typescript/module/scroll/types.d.ts.map +1 -1
- package/lib/typescript/module/tabs/Tabs.d.ts +41 -1
- package/lib/typescript/module/tabs/Tabs.d.ts.map +1 -1
- package/lib/typescript/module/tabs/expo-router/RouterTabs.d.ts +80 -0
- package/lib/typescript/module/tabs/expo-router/RouterTabs.d.ts.map +1 -0
- package/lib/typescript/module/tabs/expo-router/index.d.ts +9 -0
- package/lib/typescript/module/tabs/expo-router/index.d.ts.map +1 -0
- package/lib/typescript/module/tabs/types.d.ts +48 -4
- package/lib/typescript/module/tabs/types.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-policy.d.ts.map +1 -1
- package/package.json +29 -1
- package/src/__tests__/BloomProvider.web.test.tsx +8 -15
- package/src/__tests__/Tabs.test.tsx +187 -0
- package/src/__tests__/optional-peer-imports.test.ts +7 -2
- package/src/__tests__/scroll-expo-router-adapter.test.tsx +164 -0
- package/src/__tests__/scroll-native.test.tsx +465 -0
- package/src/__tests__/scroll-store.test.ts +41 -17
- package/src/__tests__/scroll-web.test.tsx +797 -108
- package/src/provider/index.tsx +10 -7
- package/src/scroll/context.tsx +107 -0
- package/src/scroll/expo-router/index.ts +140 -0
- package/src/scroll/index.ts +92 -25
- package/src/scroll/index.web.tsx +255 -162
- package/src/scroll/scrollable.native.ts +64 -0
- package/src/scroll/scrollable.web.ts +30 -8
- package/src/scroll/store.ts +47 -25
- package/src/scroll/types.ts +82 -12
- package/src/tabs/Tabs.tsx +352 -77
- package/src/tabs/expo-router/RouterTabs.tsx +268 -0
- package/src/tabs/expo-router/index.ts +8 -0
- package/src/tabs/types.ts +48 -4
- package/src/theme/__tests__/__fixtures__/golden-resolved-tokens.json +5 -5
- package/src/theme/__tests__/__snapshots__/visual-gallery.test.tsx.snap +11 -11
- package/src/theme/__tests__/policy-legibility.test.ts +10 -7
- package/src/theme/color-policy.ts +11 -10
- package/lib/commonjs/provider/scroll-provider.js +0 -13
- package/lib/commonjs/provider/scroll-provider.js.map +0 -1
- package/lib/commonjs/provider/scroll-provider.web.js +0 -13
- package/lib/commonjs/provider/scroll-provider.web.js.map +0 -1
- package/lib/module/provider/scroll-provider.js +0 -16
- package/lib/module/provider/scroll-provider.js.map +0 -1
- package/lib/module/provider/scroll-provider.web.js +0 -5
- package/lib/module/provider/scroll-provider.web.js.map +0 -1
- package/lib/typescript/commonjs/provider/scroll-provider.d.ts +0 -14
- package/lib/typescript/commonjs/provider/scroll-provider.d.ts.map +0 -1
- package/lib/typescript/commonjs/provider/scroll-provider.web.d.ts +0 -3
- package/lib/typescript/commonjs/provider/scroll-provider.web.d.ts.map +0 -1
- package/lib/typescript/module/provider/scroll-provider.d.ts +0 -14
- package/lib/typescript/module/provider/scroll-provider.d.ts.map +0 -1
- package/lib/typescript/module/provider/scroll-provider.web.d.ts +0 -3
- package/lib/typescript/module/provider/scroll-provider.web.d.ts.map +0 -1
- package/src/__tests__/scroll-native.test.ts +0 -25
- package/src/provider/scroll-provider.ts +0 -13
- package/src/provider/scroll-provider.web.ts +0 -2
|
@@ -1,42 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Derive the storage key for a scrollable from WHAT its screen is showing plus
|
|
3
|
+
* an optional caller sub-key.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* The key is CONTENT identity, deliberately not the navigation entry. An offset
|
|
6
|
+
* belongs to what the user was looking at, so returning to it restores however
|
|
7
|
+
* they got there — browser Back or Forward, a tab press, an in-app link — and
|
|
8
|
+
* only content never seen this session opens at the top. Keying on the entry
|
|
9
|
+
* would defeat that: a tab press and `router.replace` both mint a fresh entry,
|
|
10
|
+
* so both would open at the top even though the user has been there.
|
|
11
|
+
*
|
|
12
|
+
* The trade, chosen rather than overlooked: the same content occupying two LIVE
|
|
13
|
+
* entries now shares one offset. Pushing `/@alice` on top of `/@alice` in a
|
|
14
|
+
* native stack restores the first one's position instead of opening at the top,
|
|
15
|
+
* and while both are mounted each writes to the same key. That is the price of
|
|
16
|
+
* a tab press restoring, which is the behaviour that was asked for.
|
|
12
17
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
18
|
+
* The key is always the same two-field composite, with an absent sub-key
|
|
19
|
+
* written as empty, so two different identities can never collapse onto one key
|
|
20
|
+
* by omission.
|
|
15
21
|
*
|
|
16
|
-
* Returns `null` when there is no
|
|
17
|
-
* is not inside a navigator
|
|
22
|
+
* Returns `null` when there is no content id to anchor against (the scrollable
|
|
23
|
+
* is not inside a navigator, or the adapter cannot answer), which every caller
|
|
24
|
+
* treats as "do not persist and do not restore".
|
|
18
25
|
*/
|
|
19
|
-
export declare function deriveScrollKey(
|
|
26
|
+
export declare function deriveScrollKey(contentId: string | null, subKey?: string): string | null;
|
|
20
27
|
/**
|
|
21
28
|
* In-memory map of `scrollKey -> last-known scroll offset`.
|
|
22
29
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
30
|
+
* Offsets live only for the lifetime of the document/session. We never persist
|
|
31
|
+
* them — a full reload should start at the top — and we never auto-evict,
|
|
32
|
+
* because an entry can be revisited via browser Forward/Back long after it
|
|
33
|
+
* blurred.
|
|
34
|
+
*
|
|
35
|
+
* Deliberately an instance held in React context rather than a module-level
|
|
36
|
+
* singleton: a dependency tree can legitimately contain two copies of Bloom
|
|
37
|
+
* (a hoisted one plus a nested one under another Oxy package), and a
|
|
38
|
+
* module-global would then exist twice with no way for either half to see the
|
|
39
|
+
* other's offsets.
|
|
27
40
|
*/
|
|
28
41
|
export declare class ScrollOffsetStore {
|
|
29
42
|
private readonly offsets;
|
|
30
43
|
/** Persist the offset for a key. A negative offset is clamped to 0. */
|
|
31
44
|
save(key: string, offset: number): void;
|
|
32
45
|
/**
|
|
33
|
-
* Read the saved offset for a key. Returns `0` when nothing was saved,
|
|
34
|
-
*
|
|
46
|
+
* Read the saved offset for a key. Returns `0` when nothing was saved, which
|
|
47
|
+
* is the same value a caller writes when {@link has} is false — an unseen
|
|
48
|
+
* list restores to the top.
|
|
35
49
|
*/
|
|
36
50
|
read(key: string): number;
|
|
37
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Whether an offset was ever saved for this key. This — not `read() > 0` —
|
|
53
|
+
* is what separates "restore" from "reset": a key that was never seen and a
|
|
54
|
+
* key deliberately saved at the top both read 0, and only the store knows
|
|
55
|
+
* which is which.
|
|
56
|
+
*/
|
|
38
57
|
has(key: string): boolean;
|
|
39
|
-
/** Drop a saved offset (e.g. when
|
|
58
|
+
/** Drop a saved offset (e.g. when an entry is permanently removed). */
|
|
40
59
|
forget(key: string): void;
|
|
41
60
|
/** Clear every saved offset. Primarily for tests and full resets. */
|
|
42
61
|
clear(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/scroll/store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/scroll/store.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAGf;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IAErD,uEAAuE;IACvE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIvC;;;;OAIG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIzB;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,uEAAuE;IACvE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,qEAAqE;IACrE,KAAK,IAAI,IAAI;IAIb,iDAAiD;IACjD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import type { ReactNode, RefObject } from 'react';
|
|
2
|
+
import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
2
3
|
/**
|
|
3
4
|
* Anything `useScrollRestoration` knows how to read/write a vertical scroll
|
|
4
5
|
* offset from. The hook accepts a ref to one of these:
|
|
5
6
|
*
|
|
6
|
-
* - a React Native `ScrollView` / `FlatList` ref (which on web is
|
|
7
|
-
* DOM node and exposes `getScrollableNode()`),
|
|
7
|
+
* - a React Native `ScrollView` / `FlatList` / `FlashList` ref (which on web is
|
|
8
|
+
* backed by a DOM node and exposes `getScrollableNode()`),
|
|
8
9
|
* - a raw DOM element ref (when a component renders its own scroll container),
|
|
9
|
-
* - the literal `'window'` sentinel, for the
|
|
10
|
-
*
|
|
10
|
+
* - the literal `'window'` sentinel, for the layout where the list IS the
|
|
11
|
+
* document scroller.
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* The two imperative methods are the native write path; web writes `scrollTop`
|
|
14
|
+
* on the resolved DOM node instead. Both are optional because a given ref only
|
|
15
|
+
* ever exposes one of them (list vs. scroll view).
|
|
14
16
|
*/
|
|
15
17
|
export interface ScrollableHandle {
|
|
16
|
-
/**
|
|
18
|
+
/** `ScrollView`'s imperative scroll API. */
|
|
17
19
|
scrollTo?: (options: {
|
|
18
20
|
x?: number;
|
|
19
21
|
y?: number;
|
|
20
22
|
animated?: boolean;
|
|
21
23
|
}) => void;
|
|
24
|
+
/** `FlatList`/`FlashList`'s imperative scroll API. */
|
|
25
|
+
scrollToOffset?: (options: {
|
|
26
|
+
offset: number;
|
|
27
|
+
animated?: boolean;
|
|
28
|
+
}) => void;
|
|
22
29
|
/** Web/RNW path: returns the underlying DOM node. */
|
|
23
30
|
getScrollableNode?: () => unknown;
|
|
24
31
|
}
|
|
@@ -26,21 +33,84 @@ export interface ScrollableHandle {
|
|
|
26
33
|
* The accepted ref shapes. `'window'` is a sentinel for the document scroller.
|
|
27
34
|
*/
|
|
28
35
|
export type ScrollRestorationTarget = RefObject<ScrollableHandle | null> | RefObject<unknown> | 'window';
|
|
36
|
+
/** The effect shape `useScreenFocusEffect` runs — mirrors `useEffect`'s. */
|
|
37
|
+
export type ScreenFocusEffect = () => (() => void) | void;
|
|
38
|
+
/**
|
|
39
|
+
* The router bindings the scroll core needs, and the ONLY thing it knows about
|
|
40
|
+
* routing. Keeping this to two hooks is what lets the core ship without a
|
|
41
|
+
* router import, so a Vite/SPA consumer can supply its own adapter (or none).
|
|
42
|
+
*
|
|
43
|
+
* Both members are HOOKS: the core calls them from `useScrollRestoration`, so
|
|
44
|
+
* the adapter value must be referentially stable for the lifetime of the
|
|
45
|
+
* provider (a module-level constant, which is what every adapter Bloom ships
|
|
46
|
+
* is). Swapping in a different adapter at runtime would change the hook order
|
|
47
|
+
* of every consumer below it.
|
|
48
|
+
*/
|
|
49
|
+
export interface ScrollRouterAdapter {
|
|
50
|
+
/**
|
|
51
|
+
* Identify WHAT the calling screen is showing — its route and params, not the
|
|
52
|
+
* history slot it occupies. Offsets are remembered per content, so returning
|
|
53
|
+
* to something already seen restores it however the user got there.
|
|
54
|
+
*
|
|
55
|
+
* It must describe the screen the CALLER is rendered inside, never the
|
|
56
|
+
* globally focused one: a background screen has to keep reporting its own
|
|
57
|
+
* content, or it would save its offset under the foreground screen's key.
|
|
58
|
+
*
|
|
59
|
+
* `null` when the adapter cannot answer (a scrollable rendered outside any
|
|
60
|
+
* navigator), which makes the hook inert rather than guessing.
|
|
61
|
+
*/
|
|
62
|
+
useScreenContentId(): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* Run `effect` while the calling screen is focused, and its cleanup on blur.
|
|
65
|
+
* Re-runs when `effect`'s identity changes AND the screen is focused — that
|
|
66
|
+
* is what makes an in-screen key change (a tab or folder swap) visible to a
|
|
67
|
+
* hook that never blurred.
|
|
68
|
+
*/
|
|
69
|
+
useScreenFocusEffect(effect: ScreenFocusEffect): void;
|
|
70
|
+
}
|
|
29
71
|
export interface UseScrollRestorationOptions {
|
|
30
72
|
/**
|
|
31
|
-
* Sub-key
|
|
32
|
-
*
|
|
33
|
-
*
|
|
73
|
+
* Sub-key distinguishing scrollables that share one screen AND one content
|
|
74
|
+
* id — the tabs of a profile, the folders of a saved-items screen. Changing
|
|
75
|
+
* it while the screen stays focused saves the outgoing list's offset and
|
|
76
|
+
* restores (or resets) the incoming one.
|
|
34
77
|
*/
|
|
35
78
|
key?: string;
|
|
36
79
|
/**
|
|
37
|
-
* When `false
|
|
38
|
-
*
|
|
80
|
+
* When `false` the hook is completely inert: no save, no restore, no reset.
|
|
81
|
+
*
|
|
82
|
+
* On NATIVE this is load-bearing rather than a feature flag. Restoring into a
|
|
83
|
+
* list whose rows have not been laid out yet lands at the wrong place (or is
|
|
84
|
+
* clamped away), and native has no equivalent of the web path's re-apply
|
|
85
|
+
* loop — so the caller gates on its own content being present, e.g.
|
|
86
|
+
* `enabled: rows.length > 0`. Flipping it from `false` to `true` is what
|
|
87
|
+
* triggers the restore.
|
|
88
|
+
*
|
|
39
89
|
* Defaults to `true`.
|
|
40
90
|
*/
|
|
41
91
|
enabled?: boolean;
|
|
42
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* What `useScrollRestoration` hands back. Identical on both platforms so call
|
|
95
|
+
* sites are written once.
|
|
96
|
+
*/
|
|
97
|
+
export interface ScrollRestorationBinding {
|
|
98
|
+
/**
|
|
99
|
+
* Wire onto the list being restored: `<FlashList onScroll={scroll.onScroll}>`.
|
|
100
|
+
*
|
|
101
|
+
* Native has no way to observe a list's offset from outside it, so this is
|
|
102
|
+
* how offsets are recorded there. On web it is a stable no-op — the web path
|
|
103
|
+
* subscribes to the resolved DOM node's own `scroll` event, which needs
|
|
104
|
+
* nothing from the caller — and passing it costs nothing.
|
|
105
|
+
*/
|
|
106
|
+
onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
107
|
+
}
|
|
43
108
|
export interface ScrollRestorationProviderProps {
|
|
44
109
|
children: ReactNode;
|
|
110
|
+
/**
|
|
111
|
+
* Binds the store to a router. Must be referentially stable — see
|
|
112
|
+
* {@link ScrollRouterAdapter}.
|
|
113
|
+
*/
|
|
114
|
+
adapter: ScrollRouterAdapter;
|
|
45
115
|
}
|
|
46
116
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/scroll/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/scroll/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,sDAAsD;IACtD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3E,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAClC,SAAS,CAAC,OAAO,CAAC,GAClB,QAAQ,CAAC;AAEb,4EAA4E;AAC5E,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;OAWG;IACH,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAAC;IACpC;;;;;OAKG;IACH,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,2BAA2B;IAC1C;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;;;OAOG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CACpE;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,OAAO,EAAE,mBAAmB,CAAC;CAC9B"}
|
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { TabsProps, TabsTriggerProps, TabsContentProps } from './types';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* The imperative surface a horizontal drag gesture drives the underline through.
|
|
5
|
+
*
|
|
6
|
+
* It lives here rather than in the gesture's own code because every quantity the
|
|
7
|
+
* drag needs — where the neighbouring trigger is, how wide it is, whether there
|
|
8
|
+
* IS a neighbour — is measured layout the strip already holds and nothing
|
|
9
|
+
* outside it can see. The gesture supplies one number, the finger's delta; the
|
|
10
|
+
* strip decides what that means.
|
|
11
|
+
*
|
|
12
|
+
* Obtained via a `ref` on `Tabs`. The gesture belongs in the LAYOUT beside the
|
|
13
|
+
* strip, never inside a tab screen — a gesture mounted in a screen is destroyed
|
|
14
|
+
* by the navigation it commits, mid-release.
|
|
15
|
+
*/
|
|
16
|
+
export interface TabsDragController {
|
|
17
|
+
/**
|
|
18
|
+
* Feed the raw horizontal finger delta (`translationX`).
|
|
19
|
+
*
|
|
20
|
+
* The underline travels OPPOSITE the finger, because that is where the
|
|
21
|
+
* incoming tab is: dragging left reveals the NEXT tab, which sits to the
|
|
22
|
+
* right. Travel is clamped at the neighbour — the underline stops exactly
|
|
23
|
+
* where it would land, so it never promises more than the release delivers —
|
|
24
|
+
* and at the first/last tab it rubber-bands instead.
|
|
25
|
+
*
|
|
26
|
+
* Returns the value that releasing NOW would commit, or `null` for "no
|
|
27
|
+
* commit": either the drag has not passed the threshold, or there is no
|
|
28
|
+
* neighbour in that direction.
|
|
29
|
+
*/
|
|
30
|
+
drag(translationX: number): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* End the drag. Pass the value `drag` last returned to keep the underline
|
|
33
|
+
* where the finger left it while the caller navigates; pass `null` to spring
|
|
34
|
+
* it home.
|
|
35
|
+
*
|
|
36
|
+
* On a commit the offset is FOLDED into the underline's base position rather
|
|
37
|
+
* than zeroed, so the focus change that follows springs from where the finger
|
|
38
|
+
* actually let go. Zeroing first would snap backwards for a frame and then
|
|
39
|
+
* animate forwards from the wrong place.
|
|
40
|
+
*/
|
|
41
|
+
release(committed: string | null): void;
|
|
42
|
+
}
|
|
43
|
+
export declare const Tabs: React.NamedExoticComponent<TabsProps & React.RefAttributes<TabsDragController>>;
|
|
4
44
|
export declare const TabsTrigger: React.NamedExoticComponent<TabsTriggerProps>;
|
|
5
45
|
export declare const TabsContent: React.NamedExoticComponent<TabsContentProps>;
|
|
6
46
|
//# sourceMappingURL=Tabs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../../src/tabs/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../../src/tabs/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAUN,MAAM,OAAO,CAAC;AA4Bf,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAe,MAAM,SAAS,CAAC;AAwD1F;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1C;;;;;;;;;OASG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;CACzC;AAmbD,eAAO,MAAM,IAAI,iFAAyB,CAAC;AAG3C,eAAO,MAAM,WAAW,8CAAqB,CAAC;AAG9C,eAAO,MAAM,WAAW,8CAA0B,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* expo-router bindings for the in-screen tab strip.
|
|
3
|
+
*
|
|
4
|
+
* This subpath (`@oxyhq/bloom/tabs/expo-router`) is the ONLY place in the tabs
|
|
5
|
+
* feature allowed to import `expo-router`, which is why it is a separate entry:
|
|
6
|
+
* the core `@oxyhq/bloom/tabs` stays usable in an app with a different router,
|
|
7
|
+
* or none, and the optional peer is never pulled into a bundle that does not
|
|
8
|
+
* ask for it. Same split as `tab-bar` / `tab-bar/expo-router` and
|
|
9
|
+
* `scroll` / `scroll/expo-router`.
|
|
10
|
+
*
|
|
11
|
+
* Everything routing-shaped lives here on purpose: which tab the route means,
|
|
12
|
+
* what a committed swipe navigates to, and which links to warm. The strip
|
|
13
|
+
* itself stays presentational and knows only about measured geometry.
|
|
14
|
+
*/
|
|
15
|
+
import { type ReactNode } from 'react';
|
|
16
|
+
import { type Href } from 'expo-router';
|
|
17
|
+
import type { TabsProps } from '../types';
|
|
18
|
+
export interface RouterTabItem {
|
|
19
|
+
/** Stable id for the tab. Used as a React key and a callback argument. */
|
|
20
|
+
value: string;
|
|
21
|
+
/** Tab label text. */
|
|
22
|
+
label: string;
|
|
23
|
+
/** The route this tab shows. Must be the tab's EXACT path. */
|
|
24
|
+
href: Href;
|
|
25
|
+
/** Icon rendered before the label. */
|
|
26
|
+
icon?: ReactNode;
|
|
27
|
+
/** Optional tally beside the label; `0` or omitted renders nothing. */
|
|
28
|
+
count?: number;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export type RouterTabsProps = Omit<TabsProps, 'value' | 'onValueChange' | 'hasSelection' | 'children'> & {
|
|
32
|
+
items: RouterTabItem[];
|
|
33
|
+
/**
|
|
34
|
+
* Called instead of navigating when the ALREADY-active tab is pressed.
|
|
35
|
+
*
|
|
36
|
+
* Without it a re-tap would push a second history entry for the route the
|
|
37
|
+
* user is already on, so Back would appear to do nothing. Re-tapping the
|
|
38
|
+
* active tab conventionally means "refresh" or "scroll to top", and that is
|
|
39
|
+
* the caller's to define.
|
|
40
|
+
*/
|
|
41
|
+
onReselect?: (value: string) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Enable the horizontal swipe between neighbouring tabs. Defaults to `true`.
|
|
44
|
+
*
|
|
45
|
+
* The gesture is INDICATOR-LED: the underline tracks the finger toward the
|
|
46
|
+
* neighbour and commits on release past a threshold, while the content stays
|
|
47
|
+
* where it is. That asymmetry is deliberate — the underline has somewhere
|
|
48
|
+
* real to go and can complete its journey, whereas under a `<Slot/>` there is
|
|
49
|
+
* no neighbouring screen mounted to bring in, so translating the content
|
|
50
|
+
* would only open a blank gutter on the trailing edge.
|
|
51
|
+
*/
|
|
52
|
+
swipeEnabled?: boolean;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* A tab strip whose selection IS the route.
|
|
56
|
+
*
|
|
57
|
+
* Render it in the LAYOUT that owns the tabs, above the `<Slot/>` that renders
|
|
58
|
+
* them — not inside the tab screens themselves. That placement is the whole
|
|
59
|
+
* point, and it is load-bearing twice over: a strip inside the screens is
|
|
60
|
+
* unmounted and rebuilt by every navigation, so its underline has nothing to
|
|
61
|
+
* animate from and the chrome blanks while the incoming route's chunk loads;
|
|
62
|
+
* and a GESTURE inside the screens would be destroyed by the very navigation it
|
|
63
|
+
* commits, mid-release.
|
|
64
|
+
*
|
|
65
|
+
* ```tsx
|
|
66
|
+
* // app/(app)/[username]/_layout.tsx
|
|
67
|
+
* <RouterTabs
|
|
68
|
+
* items={[
|
|
69
|
+
* { value: 'posts', label: 'Posts', href: `/${username}` },
|
|
70
|
+
* { value: 'replies', label: 'Replies', href: `/${username}/replies` },
|
|
71
|
+
* ]}
|
|
72
|
+
* />
|
|
73
|
+
* <Slot />
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function RouterTabs({ items, onReselect, swipeEnabled, ...tabsProps }: RouterTabsProps): import("react/jsx-runtime").JSX.Element;
|
|
77
|
+
export declare namespace RouterTabs {
|
|
78
|
+
var displayName: string;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=RouterTabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouterTabs.d.ts","sourceRoot":"","sources":["../../../../../src/tabs/expo-router/RouterTabs.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAA2C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGhF,OAAO,EAAuB,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAG7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,IAAI,EAAE,IAAI,CAAC;IACX,sCAAsC;IACtC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,SAAS,EAGT,OAAO,GAAG,eAAe,GAAG,cAAc,GAAG,UAAU,CACxD,GAAG;IACF,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAuCF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,UAAU,EACV,YAAmB,EACnB,GAAG,SAAS,EACb,EAAE,eAAe,2CAwIjB;yBA7Ie,UAAU"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entry for `@oxyhq/bloom/tabs/expo-router`. The component lives in a sibling
|
|
3
|
+
* module because this file is the published entry path and must stay stable;
|
|
4
|
+
* the split also keeps the router binding in one place, which is what the
|
|
5
|
+
* optional-peer allowlist asserts about.
|
|
6
|
+
*/
|
|
7
|
+
export { RouterTabs } from './RouterTabs';
|
|
8
|
+
export type { RouterTabItem, RouterTabsProps } from './RouterTabs';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/tabs/expo-router/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1,10 +1,38 @@
|
|
|
1
1
|
import type { StyleProp, ViewStyle, TextStyle } from 'react-native';
|
|
2
2
|
export type TabsVariant = 'underline' | 'filled' | 'outlined';
|
|
3
3
|
export interface TabsProps {
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The currently selected tab value — the CONTROLLED path, where the bar owns
|
|
6
|
+
* the underline and reports presses through {@link TabsProps.onValueChange}.
|
|
7
|
+
*
|
|
8
|
+
* OMIT it for the focus-driven path, where each trigger supplies its own
|
|
9
|
+
* {@link TabsTriggerProps.isFocused} and performs its own navigation. That is
|
|
10
|
+
* how `@oxyhq/bloom/tabs/expo-router` keeps the underline correct through
|
|
11
|
+
* deep links, browser Back and back gestures — none of which pass through a
|
|
12
|
+
* press handler. Providing both would put two writers on one shared value.
|
|
13
|
+
*/
|
|
14
|
+
value?: string;
|
|
15
|
+
/** Called when a tab is selected. Controlled path only. */
|
|
16
|
+
onValueChange?: (value: string) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Focus-driven path only: whether ANY trigger is currently focused.
|
|
19
|
+
*
|
|
20
|
+
* `false` fades the underline out where it stands. This is not the same as
|
|
21
|
+
* "the selection moved", and it is not hypothetical: a strip rendered by a
|
|
22
|
+
* LAYOUT keeps rendering while the layout's other, non-tab children are
|
|
23
|
+
* showing — a profile's `/followers` sits beside its tab routes under one
|
|
24
|
+
* layout — and without this the underline stays parked on whichever tab was
|
|
25
|
+
* last visited, asserting a selection that is not there.
|
|
26
|
+
*
|
|
27
|
+
* Fading is the whole response; the underline is deliberately NOT moved,
|
|
28
|
+
* because there is no position that means "nowhere" and travelling to a
|
|
29
|
+
* sentinel would drag it across every tab on the way out.
|
|
30
|
+
*
|
|
31
|
+
* `RouterTabs` sets it, so an app author never passes it by hand. Defaults to
|
|
32
|
+
* `true`, which is correct for the controlled path (a `value` naming no
|
|
33
|
+
* trigger simply leaves the underline where it was, as it always has).
|
|
34
|
+
*/
|
|
35
|
+
hasSelection?: boolean;
|
|
8
36
|
/** Visual variant for the tab bar. */
|
|
9
37
|
variant?: TabsVariant;
|
|
10
38
|
/**
|
|
@@ -26,8 +54,24 @@ export interface TabsTriggerProps {
|
|
|
26
54
|
label: string;
|
|
27
55
|
/** Icon rendered before the label. */
|
|
28
56
|
icon?: React.ReactNode;
|
|
57
|
+
/**
|
|
58
|
+
* Optional tally rendered as a small muted number beside the label. Omitted
|
|
59
|
+
* (or `0`) renders nothing. The underline tracks the trigger's measured
|
|
60
|
+
* width, so a count never changes where it sits.
|
|
61
|
+
*/
|
|
62
|
+
count?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Whether the ROUTER considers this tab focused — the focus-driven path.
|
|
65
|
+
* Supplying it makes this trigger, not the bar, the writer of the shared
|
|
66
|
+
* underline, and suppresses {@link TabsProps.onValueChange} on press because
|
|
67
|
+
* navigation is then the caller's job. Leave it `undefined` on the controlled
|
|
68
|
+
* path.
|
|
69
|
+
*/
|
|
70
|
+
isFocused?: boolean;
|
|
29
71
|
/** Whether this tab is disabled. */
|
|
30
72
|
disabled?: boolean;
|
|
73
|
+
/** Extra press handler. Runs on both paths, before any selection is reported. */
|
|
74
|
+
onPress?: () => void;
|
|
31
75
|
style?: StyleProp<ViewStyle>;
|
|
32
76
|
textStyle?: StyleProp<TextStyle>;
|
|
33
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/tabs/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE9D,MAAM,WAAW,SAAS;IACxB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/tabs/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE9D,MAAM,WAAW,SAAS;IACxB;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sCAAsC;IACtC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qDAAqD;IACrD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-policy.d.ts","sourceRoot":"","sources":["../../../../src/theme/color-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAK9D,sFAAsF;AACtF,eAAO,MAAM,YAAY;;;;;CAKf,CAAC;AAEX,wFAAwF;AACxF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,kFAAkF;AAClF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"color-policy.d.ts","sourceRoot":"","sources":["../../../../src/theme/color-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAK9D,sFAAsF;AACtF,eAAO,MAAM,YAAY;;;;;CAKf,CAAC;AAEX,wFAAwF;AACxF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,kFAAkF;AAClF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAkPlD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,UAAU,EACjB,MAAM,GAAE,aAAkB,GACzB,YAAY,CAgHd"}
|
|
@@ -18,11 +18,13 @@
|
|
|
18
18
|
* Nesting extra contexts costs nothing at runtime — the win is that scope is no
|
|
19
19
|
* longer a per-app decision.
|
|
20
20
|
*
|
|
21
|
-
* EXPO/EXPO-ROUTER APPS ONLY
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
21
|
+
* EXPO/EXPO-ROUTER APPS ONLY, and now for one narrow reason: it binds the
|
|
22
|
+
* scroll store to the expo-router ADAPTER, which is the only module in the
|
|
23
|
+
* scroll primitive that imports `expo-router`. The scroll core itself is
|
|
24
|
+
* router-agnostic, so a Vite/SPA consumer can mount
|
|
25
|
+
* `<ScrollRestorationProvider adapter={...}>` from `@oxyhq/bloom/scroll` with
|
|
26
|
+
* an adapter for its own router — alongside `BloomThemeProvider` and whatever
|
|
27
|
+
* else it needs — rather than going without.
|
|
26
28
|
*
|
|
27
29
|
* NOT included, on purpose — these are OUTLETS, not state, and their placement
|
|
28
30
|
* in the tree is a real app decision (z-order, safe areas, and mounting a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/provider/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/provider/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAG9E,OAAO,EAAsB,KAAK,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAI5E,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC;IACnF,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,wFAAwF;IACxF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,aAAa,EACb,OAAc,EACd,GAAG,UAAU,EACd,EAAE,kBAAkB,2CAcpB;yBAnBe,aAAa"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ScrollOffsetStore } from './store';
|
|
2
|
+
import type { ScrollRestorationProviderProps, ScrollRouterAdapter } from './types';
|
|
3
|
+
export interface ScrollRestorationContextValue {
|
|
4
|
+
store: ScrollOffsetStore;
|
|
5
|
+
adapter: ScrollRouterAdapter;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Holds the offset map and the router binding for the subtree. One provider
|
|
9
|
+
* near the app root is enough; the store lives as long as the provider, so
|
|
10
|
+
* offsets survive navigating away and back (including browser Back/Forward).
|
|
11
|
+
*/
|
|
12
|
+
export declare function ScrollRestorationProvider({ children, adapter, }: ScrollRestorationProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare function useScrollRestorationContext(): ScrollRestorationContextValue;
|
|
14
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/scroll/context.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EACV,8BAA8B,EAC9B,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,iBAAiB,CAAC;IACzB,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAMD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,OAAO,GACR,EAAE,8BAA8B,2CAWhC;AAED,wBAAgB,2BAA2B,IAAI,6BAA6B,CAQ3E"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ScrollRouterAdapter } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* The adapter to hand `<ScrollRestorationProvider adapter={...}>` in an
|
|
4
|
+
* expo-router app. A module-level constant, as the adapter contract requires.
|
|
5
|
+
*/
|
|
6
|
+
export declare const expoRouterScrollAdapter: ScrollRouterAdapter;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/scroll/expo-router/index.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAqB,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAkHvE;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAGrC,CAAC"}
|
|
@@ -1,27 +1,18 @@
|
|
|
1
|
+
import type { ScrollRestorationBinding, ScrollRestorationTarget, UseScrollRestorationOptions } from './types';
|
|
2
|
+
export { ScrollRestorationProvider } from './context';
|
|
3
|
+
export type { ScreenFocusEffect, ScrollableHandle, ScrollRestorationBinding, ScrollRestorationProviderProps, ScrollRestorationTarget, ScrollRouterAdapter, UseScrollRestorationOptions, } from './types';
|
|
1
4
|
/**
|
|
2
|
-
*
|
|
5
|
+
* Preserve and restore the scroll offset of `target` across content changes,
|
|
6
|
+
* keyed by the content its screen is showing plus an optional `options.key`.
|
|
3
7
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* nothing.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `package.json`; native bundlers fall through to this file.
|
|
13
|
-
*/
|
|
14
|
-
import type { ReactElement } from 'react';
|
|
15
|
-
import type { ScrollRestorationProviderProps, ScrollRestorationTarget, UseScrollRestorationOptions } from './types';
|
|
16
|
-
export type { ScrollableHandle, ScrollRestorationProviderProps, ScrollRestorationTarget, UseScrollRestorationOptions, } from './types';
|
|
17
|
-
/**
|
|
18
|
-
* No-op provider. Renders children unchanged — native scroll persistence is
|
|
19
|
-
* handled by the navigator, so no per-route state is kept.
|
|
20
|
-
*/
|
|
21
|
-
export declare function ScrollRestorationProvider({ children, }: ScrollRestorationProviderProps): ReactElement;
|
|
22
|
-
/**
|
|
23
|
-
* No-op hook. Accepts the same arguments as the web implementation so call
|
|
24
|
-
* sites are identical across platforms.
|
|
8
|
+
* Behaviour (native):
|
|
9
|
+
* - Offsets are recorded from the returned `onScroll` binding, which the caller
|
|
10
|
+
* wires onto the list. There is no other way to observe a list's offset.
|
|
11
|
+
* - When the storage key changes — a re-keyed list, a remount, or `enabled`
|
|
12
|
+
* turning on — the saved offset is applied, or 0 when the key was never seen.
|
|
13
|
+
* - A push/pop that re-focuses the same screen scrolls nothing. The navigator
|
|
14
|
+
* already preserved the position, and re-applying it would at best be a
|
|
15
|
+
* no-op and at worst fight a list that has legitimately moved on.
|
|
25
16
|
*/
|
|
26
|
-
export declare function useScrollRestoration(
|
|
17
|
+
export declare function useScrollRestoration(target: ScrollRestorationTarget, options?: UseScrollRestorationOptions): ScrollRestorationBinding;
|
|
27
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/scroll/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/scroll/index.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAEtD,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,8BAA8B,EAC9B,uBAAuB,EACvB,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,uBAAuB,EAC/B,OAAO,CAAC,EAAE,2BAA2B,GACpC,wBAAwB,CAyD1B"}
|