@oxyhq/bloom 0.45.0 → 0.46.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.
Files changed (111) hide show
  1. package/lib/commonjs/dialog/Dialog.js +12 -3
  2. package/lib/commonjs/dialog/Dialog.js.map +1 -1
  3. package/lib/commonjs/dialog/Dialog.web.js +23 -8
  4. package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
  5. package/lib/commonjs/index.js +29 -0
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/index.web.js +73 -44
  8. package/lib/commonjs/index.web.js.map +1 -1
  9. package/lib/commonjs/surfaces/SurfaceHost.js +189 -0
  10. package/lib/commonjs/surfaces/SurfaceHost.js.map +1 -0
  11. package/lib/commonjs/surfaces/api.js +83 -0
  12. package/lib/commonjs/surfaces/api.js.map +1 -0
  13. package/lib/commonjs/surfaces/index.js +82 -0
  14. package/lib/commonjs/surfaces/index.js.map +1 -0
  15. package/lib/commonjs/surfaces/index.web.js +77 -0
  16. package/lib/commonjs/surfaces/index.web.js.map +1 -0
  17. package/lib/commonjs/surfaces/prompts.js +154 -0
  18. package/lib/commonjs/surfaces/prompts.js.map +1 -0
  19. package/lib/commonjs/surfaces/surfaceStore.js +172 -0
  20. package/lib/commonjs/surfaces/surfaceStore.js.map +1 -0
  21. package/lib/commonjs/surfaces/types.js +6 -0
  22. package/lib/commonjs/surfaces/types.js.map +1 -0
  23. package/lib/commonjs/surfaces/useSurface.js +36 -0
  24. package/lib/commonjs/surfaces/useSurface.js.map +1 -0
  25. package/lib/module/dialog/Dialog.js +13 -4
  26. package/lib/module/dialog/Dialog.js.map +1 -1
  27. package/lib/module/dialog/Dialog.web.js +23 -8
  28. package/lib/module/dialog/Dialog.web.js.map +1 -1
  29. package/lib/module/index.js +5 -0
  30. package/lib/module/index.js.map +1 -1
  31. package/lib/module/index.web.js +5 -0
  32. package/lib/module/index.web.js.map +1 -1
  33. package/lib/module/surfaces/SurfaceHost.js +184 -0
  34. package/lib/module/surfaces/SurfaceHost.js.map +1 -0
  35. package/lib/module/surfaces/api.js +48 -0
  36. package/lib/module/surfaces/api.js.map +1 -0
  37. package/lib/module/surfaces/index.js +24 -0
  38. package/lib/module/surfaces/index.js.map +1 -0
  39. package/lib/module/surfaces/index.web.js +19 -0
  40. package/lib/module/surfaces/index.web.js.map +1 -0
  41. package/lib/module/surfaces/prompts.js +148 -0
  42. package/lib/module/surfaces/prompts.js.map +1 -0
  43. package/lib/module/surfaces/surfaceStore.js +159 -0
  44. package/lib/module/surfaces/surfaceStore.js.map +1 -0
  45. package/lib/module/surfaces/types.js +4 -0
  46. package/lib/module/surfaces/types.js.map +1 -0
  47. package/lib/module/surfaces/useSurface.js +31 -0
  48. package/lib/module/surfaces/useSurface.js.map +1 -0
  49. package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -1
  50. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
  51. package/lib/typescript/commonjs/dialog/types.d.ts +10 -0
  52. package/lib/typescript/commonjs/dialog/types.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/index.d.ts +2 -0
  54. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  55. package/lib/typescript/commonjs/index.web.d.ts +2 -0
  56. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  57. package/lib/typescript/commonjs/surfaces/SurfaceHost.d.ts +25 -0
  58. package/lib/typescript/commonjs/surfaces/SurfaceHost.d.ts.map +1 -0
  59. package/lib/typescript/commonjs/surfaces/api.d.ts +41 -0
  60. package/lib/typescript/commonjs/surfaces/api.d.ts.map +1 -0
  61. package/lib/typescript/commonjs/surfaces/index.d.ts +25 -0
  62. package/lib/typescript/commonjs/surfaces/index.d.ts.map +1 -0
  63. package/lib/typescript/commonjs/surfaces/index.web.d.ts +20 -0
  64. package/lib/typescript/commonjs/surfaces/index.web.d.ts.map +1 -0
  65. package/lib/typescript/commonjs/surfaces/prompts.d.ts +13 -0
  66. package/lib/typescript/commonjs/surfaces/prompts.d.ts.map +1 -0
  67. package/lib/typescript/commonjs/surfaces/surfaceStore.d.ts +51 -0
  68. package/lib/typescript/commonjs/surfaces/surfaceStore.d.ts.map +1 -0
  69. package/lib/typescript/commonjs/surfaces/types.d.ts +145 -0
  70. package/lib/typescript/commonjs/surfaces/types.d.ts.map +1 -0
  71. package/lib/typescript/commonjs/surfaces/useSurface.d.ts +21 -0
  72. package/lib/typescript/commonjs/surfaces/useSurface.d.ts.map +1 -0
  73. package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -1
  74. package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
  75. package/lib/typescript/module/dialog/types.d.ts +10 -0
  76. package/lib/typescript/module/dialog/types.d.ts.map +1 -1
  77. package/lib/typescript/module/index.d.ts +2 -0
  78. package/lib/typescript/module/index.d.ts.map +1 -1
  79. package/lib/typescript/module/index.web.d.ts +2 -0
  80. package/lib/typescript/module/index.web.d.ts.map +1 -1
  81. package/lib/typescript/module/surfaces/SurfaceHost.d.ts +25 -0
  82. package/lib/typescript/module/surfaces/SurfaceHost.d.ts.map +1 -0
  83. package/lib/typescript/module/surfaces/api.d.ts +41 -0
  84. package/lib/typescript/module/surfaces/api.d.ts.map +1 -0
  85. package/lib/typescript/module/surfaces/index.d.ts +25 -0
  86. package/lib/typescript/module/surfaces/index.d.ts.map +1 -0
  87. package/lib/typescript/module/surfaces/index.web.d.ts +20 -0
  88. package/lib/typescript/module/surfaces/index.web.d.ts.map +1 -0
  89. package/lib/typescript/module/surfaces/prompts.d.ts +13 -0
  90. package/lib/typescript/module/surfaces/prompts.d.ts.map +1 -0
  91. package/lib/typescript/module/surfaces/surfaceStore.d.ts +51 -0
  92. package/lib/typescript/module/surfaces/surfaceStore.d.ts.map +1 -0
  93. package/lib/typescript/module/surfaces/types.d.ts +145 -0
  94. package/lib/typescript/module/surfaces/types.d.ts.map +1 -0
  95. package/lib/typescript/module/surfaces/useSurface.d.ts +21 -0
  96. package/lib/typescript/module/surfaces/useSurface.d.ts.map +1 -0
  97. package/package.json +17 -1
  98. package/src/__tests__/surfaceStore.test.ts +219 -0
  99. package/src/dialog/Dialog.tsx +14 -3
  100. package/src/dialog/Dialog.web.tsx +25 -6
  101. package/src/dialog/types.ts +10 -0
  102. package/src/index.ts +15 -0
  103. package/src/index.web.ts +15 -0
  104. package/src/surfaces/SurfaceHost.tsx +207 -0
  105. package/src/surfaces/api.ts +55 -0
  106. package/src/surfaces/index.ts +38 -0
  107. package/src/surfaces/index.web.ts +33 -0
  108. package/src/surfaces/prompts.tsx +178 -0
  109. package/src/surfaces/surfaceStore.ts +168 -0
  110. package/src/surfaces/types.ts +156 -0
  111. package/src/surfaces/useSurface.ts +33 -0
@@ -0,0 +1,156 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { StyleProp, ViewStyle } from 'react-native';
3
+
4
+ import type { DialogInset, ResponsiveDialogPlacement } from '../dialog/types';
5
+
6
+ /**
7
+ * How a surface renders — the placement + the `Dialog` sizing/chrome options a
8
+ * surface needs. This is the CONTENT-AGNOSTIC presentation config: it never
9
+ * references a route or screen name (Bloom's stack knows nothing about routes;
10
+ * the SDK layers its route registry on top).
11
+ *
12
+ * The values map 1:1 onto the shared {@link ../dialog/types#DialogProps}, so a
13
+ * surface reads/behaves identically to a hand-mounted `<Dialog>` with the same
14
+ * props — only stacked/coordinated by {@link SurfaceHost}.
15
+ */
16
+ export interface SurfacePresentation {
17
+ /**
18
+ * Surface anchor. Defaults to `{ base: 'bottom', md: 'center' }` — a bottom
19
+ * sheet on narrow viewports that becomes a centered modal on wide ones (the
20
+ * ecosystem's canonical responsive "sheet"). Pass `'center'` for a plain
21
+ * modal, `'left'`/`'right'` for a drawer, or any responsive placement map.
22
+ */
23
+ placement?: ResponsiveDialogPlacement;
24
+ /** Side-sheet width (px) on wide screens. Forwarded to `Dialog`. */
25
+ width?: number;
26
+ /** Centered-card max width (px). Forwarded to `Dialog`. */
27
+ maxWidth?: number;
28
+ /** Bottom-sheet max height as a fraction of the viewport height. */
29
+ maxHeightRatio?: number;
30
+ /** Side-sheet inset (px) from the root overlay's edges. */
31
+ inset?: DialogInset;
32
+ /** Whether to render the drag handle in bottom-sheet mode. */
33
+ showHandle?: boolean;
34
+ /**
35
+ * Whether tapping the backdrop / pressing Escape / Android-back dismisses the
36
+ * surface. Defaults to `true`. Set `false` for a blocking surface that must be
37
+ * dismissed programmatically (e.g. an unanswered required prompt).
38
+ */
39
+ dismissOnBackdrop?: boolean;
40
+ /** Inner padding (px) of the surface content container. Forwarded to `Dialog`. */
41
+ contentPadding?: number;
42
+ /** Style overrides applied to the inner content container. */
43
+ style?: StyleProp<ViewStyle>;
44
+ /** Style overrides for the side/bottom placement panel surface. */
45
+ panelStyle?: StyleProp<ViewStyle>;
46
+ /** NativeWind classes for the side/bottom placement panel surface. */
47
+ panelClassName?: string;
48
+ /** Style for the root overlay (theme-var scope, rail offset, etc.). */
49
+ containerStyle?: StyleProp<ViewStyle>;
50
+ /** NativeWind classes for the root overlay. */
51
+ containerClassName?: string;
52
+ /** Accessibility label applied to the surface's dialog role. */
53
+ label?: string;
54
+ /** Stable testID forwarded to the underlying `Dialog`. */
55
+ testID?: string;
56
+ }
57
+
58
+ /** Options accepted by `present` / `SurfaceControls.present`. */
59
+ export type PresentOptions = SurfacePresentation;
60
+
61
+ /**
62
+ * Controls handed to a presented surface — both as the argument to its render
63
+ * function AND via {@link ../surfaces/useSurface#useSurface}. This is the DEPTH
64
+ * axis only: a surface can dismiss ITSELF (resolving its own `present()`
65
+ * promise) or `present` a CHILD surface stacked above it. Navigation WITHIN a
66
+ * surface (route history / drill-in) is deliberately NOT here — that is the
67
+ * SDK's route layer, which composes on top of this stack.
68
+ */
69
+ export interface SurfaceControls {
70
+ /**
71
+ * Dismiss THIS surface, resolving the promise returned by the `present` call
72
+ * that created it with `result` (or `undefined`). Resolves immediately; the
73
+ * exit animation is cosmetic.
74
+ */
75
+ dismiss: (result?: unknown) => void;
76
+ /**
77
+ * Stack a CHILD surface directly above this one. Resolves with the child's
78
+ * dismissal result. The child paints above (higher layer) and captures
79
+ * backdrop/Escape/back until it is dismissed.
80
+ */
81
+ present: <Result = unknown>(
82
+ render: SurfaceRenderFn,
83
+ opts?: PresentOptions,
84
+ ) => Promise<Result>;
85
+ }
86
+
87
+ /** A surface's content factory — receives its own {@link SurfaceControls}. */
88
+ export type SurfaceRenderFn = (surface: SurfaceControls) => ReactNode;
89
+
90
+ /** Lifecycle status of a stacked surface. */
91
+ export type SurfaceStatus = 'open' | 'closing';
92
+
93
+ /**
94
+ * One entry in the surface stack. `resolve` fulfils the `present()` promise; the
95
+ * `settled` guard makes resolution idempotent (resolve-once); `generation` is
96
+ * the per-entry stale-callback guard (carried from `BottomSheetBase`'s
97
+ * `closeGenerationRef`, keyed per entry id) so a completion callback from a
98
+ * superseded close cycle can never tear down the wrong state.
99
+ */
100
+ export interface SurfaceEntry {
101
+ id: string;
102
+ render: SurfaceRenderFn;
103
+ presentation: SurfacePresentation;
104
+ status: SurfaceStatus;
105
+ resolve: (result: unknown) => void;
106
+ settled: boolean;
107
+ generation: number;
108
+ }
109
+
110
+ /** Options for the built-in {@link ../surfaces/prompts#confirm} surface. */
111
+ export interface SurfaceConfirmOptions {
112
+ /** Headline. */
113
+ title: string;
114
+ /** Supporting copy. */
115
+ message?: string;
116
+ /** Confirm button label. Defaults to `'Confirm'`. */
117
+ confirmLabel?: string;
118
+ /** Cancel button label. Defaults to `'Cancel'`. */
119
+ cancelLabel?: string;
120
+ /** Style the confirm button as destructive (negative color). */
121
+ destructive?: boolean;
122
+ /** Hide the cancel button (a single-action acknowledgement). */
123
+ hideCancel?: boolean;
124
+ /**
125
+ * Backdrop / Escape / back dismiss (resolving `false`). Defaults to `true`;
126
+ * pass `false` for a blocking confirm that must be answered by a button.
127
+ */
128
+ dismissible?: boolean;
129
+ /** Placement override. Defaults to `'center'`. */
130
+ placement?: ResponsiveDialogPlacement;
131
+ }
132
+
133
+ /** Options for the built-in {@link ../surfaces/prompts#prompt} surface. */
134
+ export interface SurfacePromptOptions {
135
+ /** Headline. */
136
+ title: string;
137
+ /** Supporting copy. */
138
+ message?: string;
139
+ /** Input placeholder. */
140
+ placeholder?: string;
141
+ /** Initial input value. */
142
+ defaultValue?: string;
143
+ /** Accessibility label for the input. Defaults to the `title`. */
144
+ inputLabel?: string;
145
+ /** Submit button label. Defaults to `'OK'`. */
146
+ confirmLabel?: string;
147
+ /** Cancel button label. Defaults to `'Cancel'`. */
148
+ cancelLabel?: string;
149
+ /**
150
+ * Backdrop / Escape / back dismiss (resolving `null`). Defaults to `true`;
151
+ * pass `false` for a blocking prompt.
152
+ */
153
+ dismissible?: boolean;
154
+ /** Placement override. Defaults to `'center'`. */
155
+ placement?: ResponsiveDialogPlacement;
156
+ }
@@ -0,0 +1,33 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ import type { SurfaceControls } from './types';
4
+
5
+ /**
6
+ * Context carrying the CURRENT surface's controls. The host wraps each presented
7
+ * surface's content in a provider bound to that entry's id, so a nested surface
8
+ * reads its OWN controls — `dismiss` targets this surface, `present` stacks a
9
+ * child above it.
10
+ */
11
+ export const SurfaceContext = createContext<SurfaceControls | null>(null);
12
+ SurfaceContext.displayName = 'BloomSurfaceContext';
13
+
14
+ /**
15
+ * Read the current surface's {@link SurfaceControls} from inside a presented
16
+ * surface. Equivalent to the `surface` argument the render function receives —
17
+ * use whichever is convenient (props vs. context).
18
+ *
19
+ * DEPTH only: `dismiss` (resolve this surface's promise + close) and `present`
20
+ * (stack a child). Navigation within a surface is the SDK's route layer, not
21
+ * this hook.
22
+ *
23
+ * @throws if called outside a presented surface.
24
+ */
25
+ export function useSurface(): SurfaceControls {
26
+ const controls = useContext(SurfaceContext);
27
+ if (!controls) {
28
+ throw new Error(
29
+ 'useSurface must be called from within a presented surface (rendered by <SurfaceProvider>/<SurfaceHost>).',
30
+ );
31
+ }
32
+ return controls;
33
+ }