@storybook/react-native-ui-lite 9.0.0-beta.15 → 9.0.0-rc.5
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.d.ts +251 -203
- package/dist/index.js +168 -57
- package/package.json +6 -6
- package/src/Layout.tsx +3 -15
- package/src/MobileAddonsPanel.tsx +100 -28
- package/src/MobileMenuDrawer.tsx +82 -22
- package/src/Tree.tsx +2 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as _storybook_react_native_theming from '@storybook/react-native-theming';
|
|
2
|
-
import { useTheme
|
|
2
|
+
import { useTheme } from '@storybook/react-native-theming';
|
|
3
3
|
import * as react_native from 'react-native';
|
|
4
4
|
import { View } from 'react-native';
|
|
5
|
-
import React, { FC, ComponentProps, ReactNode
|
|
6
|
-
import { Item, ExpandAction, CombinedDataset, Selection,
|
|
5
|
+
import React, { FC, ComponentProps, ReactNode } from 'react';
|
|
6
|
+
import { Item, ExpandAction, CombinedDataset, Selection, SBUI } from '@storybook/react-native-ui-common';
|
|
7
7
|
import { State, StoriesHash } from 'storybook/internal/manager-api';
|
|
8
8
|
import { API_LoadedRefData, API_IndexHash } from 'storybook/internal/types';
|
|
9
9
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
@@ -113,37 +113,44 @@ declare global {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
interface SBBaseType {
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
required?: boolean;
|
|
117
|
+
raw?: string;
|
|
118
118
|
}
|
|
119
119
|
type SBScalarType = SBBaseType & {
|
|
120
|
-
|
|
120
|
+
name: 'boolean' | 'string' | 'number' | 'function' | 'symbol';
|
|
121
121
|
};
|
|
122
122
|
type SBArrayType = SBBaseType & {
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
name: 'array';
|
|
124
|
+
value: SBType;
|
|
125
125
|
};
|
|
126
126
|
type SBObjectType = SBBaseType & {
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
name: 'object';
|
|
128
|
+
value: Record<string, SBType>;
|
|
129
129
|
};
|
|
130
130
|
type SBEnumType = SBBaseType & {
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
name: 'enum';
|
|
132
|
+
value: (string | number)[];
|
|
133
133
|
};
|
|
134
134
|
type SBIntersectionType = SBBaseType & {
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
name: 'intersection';
|
|
136
|
+
value: SBType[];
|
|
137
137
|
};
|
|
138
138
|
type SBUnionType = SBBaseType & {
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
name: 'union';
|
|
140
|
+
value: SBType[];
|
|
141
141
|
};
|
|
142
142
|
type SBOtherType = SBBaseType & {
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
name: 'other';
|
|
144
|
+
value: string;
|
|
145
145
|
};
|
|
146
|
-
type SBType =
|
|
146
|
+
type SBType =
|
|
147
|
+
| SBScalarType
|
|
148
|
+
| SBEnumType
|
|
149
|
+
| SBArrayType
|
|
150
|
+
| SBObjectType
|
|
151
|
+
| SBIntersectionType
|
|
152
|
+
| SBUnionType
|
|
153
|
+
| SBOtherType;
|
|
147
154
|
|
|
148
155
|
type StoryId = string;
|
|
149
156
|
type ComponentId = string;
|
|
@@ -151,233 +158,274 @@ type ComponentTitle = string;
|
|
|
151
158
|
type StoryName = string;
|
|
152
159
|
type Tag = string;
|
|
153
160
|
interface StoryIdentifier {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
componentId: ComponentId;
|
|
162
|
+
title: ComponentTitle;
|
|
163
|
+
/** @deprecated */
|
|
164
|
+
kind: ComponentTitle;
|
|
165
|
+
id: StoryId;
|
|
166
|
+
name: StoryName;
|
|
167
|
+
/** @deprecated */
|
|
168
|
+
story: StoryName;
|
|
169
|
+
tags: Tag[];
|
|
163
170
|
}
|
|
164
171
|
interface Parameters {
|
|
165
|
-
|
|
172
|
+
[name: string]: any;
|
|
166
173
|
}
|
|
167
|
-
type ControlType =
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
174
|
+
type ControlType =
|
|
175
|
+
| 'object'
|
|
176
|
+
| 'boolean'
|
|
177
|
+
| 'check'
|
|
178
|
+
| 'inline-check'
|
|
179
|
+
| 'radio'
|
|
180
|
+
| 'inline-radio'
|
|
181
|
+
| 'select'
|
|
182
|
+
| 'multi-select'
|
|
183
|
+
| 'number'
|
|
184
|
+
| 'range'
|
|
185
|
+
| 'file'
|
|
186
|
+
| 'color'
|
|
187
|
+
| 'date'
|
|
188
|
+
| 'text';
|
|
189
|
+
type ConditionalTest =
|
|
190
|
+
| {
|
|
191
|
+
truthy?: boolean;
|
|
192
|
+
}
|
|
193
|
+
| {
|
|
194
|
+
exists: boolean;
|
|
195
|
+
}
|
|
196
|
+
| {
|
|
197
|
+
eq: any;
|
|
198
|
+
}
|
|
199
|
+
| {
|
|
200
|
+
neq: any;
|
|
201
|
+
};
|
|
202
|
+
type ConditionalValue =
|
|
203
|
+
| {
|
|
204
|
+
arg: string;
|
|
205
|
+
}
|
|
206
|
+
| {
|
|
207
|
+
global: string;
|
|
208
|
+
};
|
|
182
209
|
type Conditional = ConditionalValue & ConditionalTest;
|
|
183
210
|
interface ControlBase {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
211
|
+
[key: string]: any;
|
|
212
|
+
/**
|
|
213
|
+
* @see https://storybook.js.org/docs/api/arg-types#controltype
|
|
214
|
+
*/
|
|
215
|
+
type?: ControlType;
|
|
216
|
+
disable?: boolean;
|
|
190
217
|
}
|
|
191
218
|
interface Report {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
219
|
+
type: string;
|
|
220
|
+
version?: number;
|
|
221
|
+
result: unknown;
|
|
222
|
+
status: 'failed' | 'passed' | 'warning';
|
|
196
223
|
}
|
|
197
224
|
interface ReportingAPI {
|
|
198
|
-
|
|
199
|
-
|
|
225
|
+
reports: Report[];
|
|
226
|
+
addReport: (report: Report) => void;
|
|
200
227
|
}
|
|
201
|
-
type Control =
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
228
|
+
type Control =
|
|
229
|
+
| ControlType
|
|
230
|
+
| false
|
|
231
|
+
| (ControlBase &
|
|
232
|
+
(
|
|
233
|
+
| ControlBase
|
|
234
|
+
| {
|
|
235
|
+
type: 'color';
|
|
236
|
+
/**
|
|
237
|
+
* @see https://storybook.js.org/docs/api/arg-types#controlpresetcolors
|
|
238
|
+
*/
|
|
239
|
+
presetColors?: string[];
|
|
240
|
+
}
|
|
241
|
+
| {
|
|
242
|
+
type: 'file';
|
|
243
|
+
/**
|
|
244
|
+
* @see https://storybook.js.org/docs/api/arg-types#controlaccept
|
|
245
|
+
*/
|
|
246
|
+
accept?: string;
|
|
247
|
+
}
|
|
248
|
+
| {
|
|
249
|
+
type: 'inline-check' | 'radio' | 'inline-radio' | 'select' | 'multi-select';
|
|
250
|
+
/**
|
|
251
|
+
* @see https://storybook.js.org/docs/api/arg-types#controllabels
|
|
252
|
+
*/
|
|
253
|
+
labels?: {
|
|
254
|
+
[options: string]: string;
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
| {
|
|
258
|
+
type: 'number' | 'range';
|
|
259
|
+
/**
|
|
260
|
+
* @see https://storybook.js.org/docs/api/arg-types#controlmax
|
|
261
|
+
*/
|
|
262
|
+
max?: number;
|
|
263
|
+
/**
|
|
264
|
+
* @see https://storybook.js.org/docs/api/arg-types#controlmin
|
|
265
|
+
*/
|
|
266
|
+
min?: number;
|
|
267
|
+
/**
|
|
268
|
+
* @see https://storybook.js.org/docs/api/arg-types#controlstep
|
|
269
|
+
*/
|
|
270
|
+
step?: number;
|
|
271
|
+
}
|
|
272
|
+
));
|
|
236
273
|
interface InputType {
|
|
274
|
+
/**
|
|
275
|
+
* @see https://storybook.js.org/docs/api/arg-types#control
|
|
276
|
+
*/
|
|
277
|
+
control?: Control;
|
|
278
|
+
/**
|
|
279
|
+
* @see https://storybook.js.org/docs/api/arg-types#description
|
|
280
|
+
*/
|
|
281
|
+
description?: string;
|
|
282
|
+
/**
|
|
283
|
+
* @see https://storybook.js.org/docs/api/arg-types#if
|
|
284
|
+
*/
|
|
285
|
+
if?: Conditional;
|
|
286
|
+
/**
|
|
287
|
+
* @see https://storybook.js.org/docs/api/arg-types#mapping
|
|
288
|
+
*/
|
|
289
|
+
mapping?: {
|
|
290
|
+
[key: string]: any;
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* @see https://storybook.js.org/docs/api/arg-types#name
|
|
294
|
+
*/
|
|
295
|
+
name?: string;
|
|
296
|
+
/**
|
|
297
|
+
* @see https://storybook.js.org/docs/api/arg-types#options
|
|
298
|
+
*/
|
|
299
|
+
options?: readonly any[];
|
|
300
|
+
/**
|
|
301
|
+
* @see https://storybook.js.org/docs/api/arg-types#table
|
|
302
|
+
*/
|
|
303
|
+
table?: {
|
|
304
|
+
[key: string]: unknown;
|
|
237
305
|
/**
|
|
238
|
-
* @see https://storybook.js.org/docs/api/arg-types#
|
|
239
|
-
*/
|
|
240
|
-
control?: Control;
|
|
241
|
-
/**
|
|
242
|
-
* @see https://storybook.js.org/docs/api/arg-types#description
|
|
243
|
-
*/
|
|
244
|
-
description?: string;
|
|
245
|
-
/**
|
|
246
|
-
* @see https://storybook.js.org/docs/api/arg-types#if
|
|
306
|
+
* @see https://storybook.js.org/docs/api/arg-types#tablecategory
|
|
247
307
|
*/
|
|
248
|
-
|
|
308
|
+
category?: string;
|
|
249
309
|
/**
|
|
250
|
-
* @see https://storybook.js.org/docs/api/arg-types#
|
|
310
|
+
* @see https://storybook.js.org/docs/api/arg-types#tabledefaultvalue
|
|
251
311
|
*/
|
|
252
|
-
|
|
253
|
-
|
|
312
|
+
defaultValue?: {
|
|
313
|
+
summary?: string;
|
|
314
|
+
detail?: string;
|
|
254
315
|
};
|
|
255
316
|
/**
|
|
256
|
-
* @see https://storybook.js.org/docs/api/arg-types#
|
|
317
|
+
* @see https://storybook.js.org/docs/api/arg-types#tabledisable
|
|
257
318
|
*/
|
|
258
|
-
|
|
319
|
+
disable?: boolean;
|
|
259
320
|
/**
|
|
260
|
-
* @see https://storybook.js.org/docs/api/arg-types#
|
|
321
|
+
* @see https://storybook.js.org/docs/api/arg-types#tablesubcategory
|
|
261
322
|
*/
|
|
262
|
-
|
|
323
|
+
subcategory?: string;
|
|
263
324
|
/**
|
|
264
|
-
* @see https://storybook.js.org/docs/api/arg-types#
|
|
325
|
+
* @see https://storybook.js.org/docs/api/arg-types#tabletype
|
|
265
326
|
*/
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
* @see https://storybook.js.org/docs/api/arg-types#tablecategory
|
|
270
|
-
*/
|
|
271
|
-
category?: string;
|
|
272
|
-
/**
|
|
273
|
-
* @see https://storybook.js.org/docs/api/arg-types#tabledefaultvalue
|
|
274
|
-
*/
|
|
275
|
-
defaultValue?: {
|
|
276
|
-
summary?: string;
|
|
277
|
-
detail?: string;
|
|
278
|
-
};
|
|
279
|
-
/**
|
|
280
|
-
* @see https://storybook.js.org/docs/api/arg-types#tabledisable
|
|
281
|
-
*/
|
|
282
|
-
disable?: boolean;
|
|
283
|
-
/**
|
|
284
|
-
* @see https://storybook.js.org/docs/api/arg-types#tablesubcategory
|
|
285
|
-
*/
|
|
286
|
-
subcategory?: string;
|
|
287
|
-
/**
|
|
288
|
-
* @see https://storybook.js.org/docs/api/arg-types#tabletype
|
|
289
|
-
*/
|
|
290
|
-
type?: {
|
|
291
|
-
summary?: string;
|
|
292
|
-
detail?: string;
|
|
293
|
-
};
|
|
327
|
+
type?: {
|
|
328
|
+
summary?: string;
|
|
329
|
+
detail?: string;
|
|
294
330
|
};
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
331
|
+
};
|
|
332
|
+
/**
|
|
333
|
+
* @see https://storybook.js.org/docs/api/arg-types#type
|
|
334
|
+
*/
|
|
335
|
+
type?: SBType | SBScalarType['name'];
|
|
336
|
+
/**
|
|
337
|
+
* @see https://storybook.js.org/docs/api/arg-types#defaultvalue
|
|
338
|
+
*
|
|
339
|
+
* @deprecated Use `table.defaultValue.summary` instead.
|
|
340
|
+
*/
|
|
341
|
+
defaultValue?: any;
|
|
342
|
+
[key: string]: any;
|
|
306
343
|
}
|
|
307
344
|
interface StrictInputType extends InputType {
|
|
308
|
-
|
|
309
|
-
|
|
345
|
+
name: string;
|
|
346
|
+
type?: SBType;
|
|
310
347
|
}
|
|
311
348
|
interface Args {
|
|
312
|
-
|
|
349
|
+
[name: string]: any;
|
|
313
350
|
}
|
|
314
351
|
type StrictArgTypes<TArgs = Args> = {
|
|
315
|
-
|
|
352
|
+
[name in keyof TArgs]: StrictInputType;
|
|
316
353
|
};
|
|
317
354
|
interface Globals {
|
|
318
|
-
|
|
355
|
+
[name: string]: any;
|
|
319
356
|
}
|
|
320
357
|
interface Renderer {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
358
|
+
/** What is the type of the `component` annotation in this renderer? */
|
|
359
|
+
component: unknown;
|
|
360
|
+
/** What does the story function return in this renderer? */
|
|
361
|
+
storyResult: unknown;
|
|
362
|
+
/** What type of element does this renderer render to? */
|
|
363
|
+
canvasElement: unknown;
|
|
364
|
+
mount(): Promise<Canvas>;
|
|
365
|
+
T?: unknown;
|
|
329
366
|
}
|
|
330
|
-
interface StoryContextForEnhancers<TRenderer extends Renderer = Renderer, TArgs = Args>
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
367
|
+
interface StoryContextForEnhancers<TRenderer extends Renderer = Renderer, TArgs = Args>
|
|
368
|
+
extends StoryIdentifier {
|
|
369
|
+
component?: (TRenderer & {
|
|
370
|
+
T: any;
|
|
371
|
+
})['component'];
|
|
372
|
+
subcomponents?: Record<
|
|
373
|
+
string,
|
|
374
|
+
(TRenderer & {
|
|
375
|
+
T: any;
|
|
376
|
+
})['component']
|
|
377
|
+
>;
|
|
378
|
+
parameters: Parameters;
|
|
379
|
+
initialArgs: TArgs;
|
|
380
|
+
argTypes: StrictArgTypes<TArgs>;
|
|
340
381
|
}
|
|
341
382
|
interface StoryContextUpdate<TArgs = Args> {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
383
|
+
args?: TArgs;
|
|
384
|
+
globals?: Globals;
|
|
385
|
+
[key: string]: any;
|
|
345
386
|
}
|
|
346
387
|
type ViewMode = 'story' | 'docs';
|
|
347
|
-
interface Canvas {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
388
|
+
interface Canvas {}
|
|
389
|
+
interface StoryContext<TRenderer extends Renderer = Renderer, TArgs = Args>
|
|
390
|
+
extends StoryContextForEnhancers<TRenderer, TArgs>,
|
|
391
|
+
Required<StoryContextUpdate<TArgs>> {
|
|
392
|
+
loaded: Record<string, any>;
|
|
393
|
+
abortSignal: AbortSignal;
|
|
394
|
+
canvasElement: TRenderer['canvasElement'];
|
|
395
|
+
hooks: unknown;
|
|
396
|
+
originalStoryFn: StoryFn<TRenderer>;
|
|
397
|
+
viewMode: ViewMode;
|
|
398
|
+
step: StepFunction<TRenderer, TArgs>;
|
|
399
|
+
context: this;
|
|
400
|
+
canvas: Canvas;
|
|
401
|
+
mount: TRenderer['mount'];
|
|
402
|
+
reporting: ReportingAPI;
|
|
361
403
|
}
|
|
362
404
|
/** @deprecated Use {@link StoryContext} instead. */
|
|
363
|
-
interface PlayFunctionContext<TRenderer extends Renderer = Renderer, TArgs = Args>
|
|
364
|
-
}
|
|
405
|
+
interface PlayFunctionContext<TRenderer extends Renderer = Renderer, TArgs = Args>
|
|
406
|
+
extends StoryContext<TRenderer, TArgs> {}
|
|
365
407
|
type StepLabel = string;
|
|
366
|
-
type StepFunction<TRenderer extends Renderer = Renderer, TArgs = Args> = (
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
408
|
+
type StepFunction<TRenderer extends Renderer = Renderer, TArgs = Args> = (
|
|
409
|
+
label: StepLabel,
|
|
410
|
+
play: PlayFunction<TRenderer, TArgs>
|
|
411
|
+
) => Promise<void> | void;
|
|
412
|
+
type PlayFunction<TRenderer extends Renderer = Renderer, TArgs = Args> = (
|
|
413
|
+
context: PlayFunctionContext<TRenderer, TArgs>
|
|
414
|
+
) => Promise<void> | void;
|
|
415
|
+
type LegacyStoryFn<TRenderer extends Renderer = Renderer, TArgs = Args> = (
|
|
416
|
+
context: StoryContext<TRenderer, TArgs>
|
|
417
|
+
) => TRenderer['storyResult'];
|
|
418
|
+
type ArgsStoryFn<TRenderer extends Renderer = Renderer, TArgs = Args> = (
|
|
419
|
+
args: TArgs,
|
|
420
|
+
context: StoryContext<TRenderer, TArgs>
|
|
421
|
+
) => (TRenderer & {
|
|
422
|
+
T: TArgs;
|
|
371
423
|
})['storyResult'];
|
|
372
|
-
type StoryFn<TRenderer extends Renderer = Renderer, TArgs = Args> =
|
|
424
|
+
type StoryFn<TRenderer extends Renderer = Renderer, TArgs = Args> =
|
|
425
|
+
| LegacyStoryFn<TRenderer, TArgs>
|
|
426
|
+
| ArgsStoryFn<TRenderer, TArgs>;
|
|
373
427
|
|
|
374
|
-
declare const LiteUI:
|
|
375
|
-
storage: Storage;
|
|
376
|
-
theme: Theme;
|
|
377
|
-
storyHash: API_IndexHash | undefined;
|
|
378
|
-
story?: StoryContext<ReactRenderer, Args>;
|
|
379
|
-
children: ReactNode | ReactNode[];
|
|
380
|
-
}) => ReactElement;
|
|
428
|
+
declare const LiteUI: SBUI;
|
|
381
429
|
declare const Layout: ({ storyHash, story, children, }: {
|
|
382
430
|
storyHash: API_IndexHash | undefined;
|
|
383
431
|
story?: StoryContext<ReactRenderer, Args>;
|
package/dist/index.js
CHANGED
|
@@ -662,6 +662,7 @@ var Tree = import_react4.default.memo(function Tree2({ isMain, refId, data, stat
|
|
|
662
662
|
}, [data]);
|
|
663
663
|
const collapsedItems = (0, import_react4.useMemo)(
|
|
664
664
|
() => Object.keys(data).filter((id) => !singleStoryComponentIds.includes(id)),
|
|
665
|
+
// eslint-disable-next-line react-compiler/react-compiler
|
|
665
666
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
666
667
|
[singleStoryComponentIds]
|
|
667
668
|
);
|
|
@@ -1372,6 +1373,55 @@ var MobileAddonsPanel = (0, import_react12.forwardRef)(
|
|
|
1372
1373
|
({ storyId }, ref) => {
|
|
1373
1374
|
const theme = (0, import_react_native_theming8.useTheme)();
|
|
1374
1375
|
const [mobileMenuOpen, setMobileMenuOpen] = (0, import_react12.useState)(false);
|
|
1376
|
+
const { height } = (0, import_react_native6.useWindowDimensions)();
|
|
1377
|
+
const panelHeight = (0, import_react_native6.useAnimatedValue)(height / 2);
|
|
1378
|
+
const positionBottomAnimation = (0, import_react_native6.useAnimatedValue)(0);
|
|
1379
|
+
(0, import_react12.useEffect)(() => {
|
|
1380
|
+
const handleKeyboardShow = ({ endCoordinates, duration, easing }) => {
|
|
1381
|
+
import_react_native6.Animated.parallel([
|
|
1382
|
+
import_react_native6.Animated.timing(positionBottomAnimation, {
|
|
1383
|
+
toValue: -endCoordinates.height,
|
|
1384
|
+
// Negative to move up
|
|
1385
|
+
duration,
|
|
1386
|
+
useNativeDriver: false,
|
|
1387
|
+
easing: import_react_native6.Easing[easing] || import_react_native6.Easing.out(import_react_native6.Easing.ease)
|
|
1388
|
+
}),
|
|
1389
|
+
import_react_native6.Animated.timing(panelHeight, {
|
|
1390
|
+
toValue: (height - endCoordinates.height) / 2,
|
|
1391
|
+
duration: duration + 250,
|
|
1392
|
+
useNativeDriver: false,
|
|
1393
|
+
easing: import_react_native6.Easing[easing] || import_react_native6.Easing.out(import_react_native6.Easing.ease)
|
|
1394
|
+
})
|
|
1395
|
+
]).start();
|
|
1396
|
+
};
|
|
1397
|
+
const handleKeyboardHide = ({ duration, easing }) => {
|
|
1398
|
+
import_react_native6.Animated.parallel([
|
|
1399
|
+
import_react_native6.Animated.timing(positionBottomAnimation, {
|
|
1400
|
+
toValue: 0,
|
|
1401
|
+
// Back to original position
|
|
1402
|
+
duration,
|
|
1403
|
+
useNativeDriver: false,
|
|
1404
|
+
easing: import_react_native6.Easing[easing] || import_react_native6.Easing.out(import_react_native6.Easing.ease)
|
|
1405
|
+
}),
|
|
1406
|
+
import_react_native6.Animated.timing(panelHeight, {
|
|
1407
|
+
toValue: height / 2,
|
|
1408
|
+
duration,
|
|
1409
|
+
useNativeDriver: false,
|
|
1410
|
+
easing: import_react_native6.Easing[easing] || import_react_native6.Easing.out(import_react_native6.Easing.ease)
|
|
1411
|
+
})
|
|
1412
|
+
]).start();
|
|
1413
|
+
};
|
|
1414
|
+
const showSubscription = import_react_native6.Keyboard.addListener("keyboardDidShow", handleKeyboardShow);
|
|
1415
|
+
const willShowSubscription = import_react_native6.Keyboard.addListener("keyboardWillShow", handleKeyboardShow);
|
|
1416
|
+
const hideSubscription = import_react_native6.Keyboard.addListener("keyboardWillHide", handleKeyboardHide);
|
|
1417
|
+
const didHideSubscription = import_react_native6.Keyboard.addListener("keyboardDidHide", handleKeyboardHide);
|
|
1418
|
+
return () => {
|
|
1419
|
+
showSubscription.remove();
|
|
1420
|
+
willShowSubscription.remove();
|
|
1421
|
+
hideSubscription.remove();
|
|
1422
|
+
didHideSubscription.remove();
|
|
1423
|
+
};
|
|
1424
|
+
}, [height, panelHeight, positionBottomAnimation]);
|
|
1375
1425
|
(0, import_react12.useImperativeHandle)(ref, () => ({
|
|
1376
1426
|
setAddonsPanelOpen: (open) => {
|
|
1377
1427
|
if (open) {
|
|
@@ -1381,34 +1431,50 @@ var MobileAddonsPanel = (0, import_react12.forwardRef)(
|
|
|
1381
1431
|
}
|
|
1382
1432
|
}
|
|
1383
1433
|
}));
|
|
1434
|
+
if (!mobileMenuOpen) {
|
|
1435
|
+
return null;
|
|
1436
|
+
}
|
|
1384
1437
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1385
|
-
import_react_native6.
|
|
1438
|
+
import_react_native6.Animated.View,
|
|
1386
1439
|
{
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1440
|
+
style: {
|
|
1441
|
+
position: "absolute",
|
|
1442
|
+
bottom: 0,
|
|
1443
|
+
left: 0,
|
|
1444
|
+
right: 0,
|
|
1445
|
+
height: panelHeight,
|
|
1446
|
+
transform: [{ translateY: positionBottomAnimation }]
|
|
1447
|
+
},
|
|
1448
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1449
|
+
import_react_native6.SafeAreaView,
|
|
1393
1450
|
{
|
|
1394
1451
|
style: {
|
|
1395
|
-
|
|
1396
|
-
backgroundColor: theme.background.content,
|
|
1397
|
-
paddingTop: 10,
|
|
1398
|
-
borderTopColor: theme.appBorderColor,
|
|
1399
|
-
borderTopWidth: 1
|
|
1452
|
+
justifyContent: "flex-end"
|
|
1400
1453
|
},
|
|
1401
1454
|
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1402
|
-
|
|
1455
|
+
import_react_native6.View,
|
|
1403
1456
|
{
|
|
1404
|
-
|
|
1405
|
-
|
|
1457
|
+
style: {
|
|
1458
|
+
height: "100%",
|
|
1459
|
+
backgroundColor: theme.background.content,
|
|
1460
|
+
paddingTop: 10,
|
|
1461
|
+
borderTopColor: theme.appBorderColor,
|
|
1462
|
+
borderTopWidth: 1,
|
|
1463
|
+
paddingBottom: import_react_native6.Platform.OS === "android" ? 16 : 0
|
|
1406
1464
|
},
|
|
1407
|
-
|
|
1465
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1466
|
+
AddonsTabs,
|
|
1467
|
+
{
|
|
1468
|
+
onClose: () => {
|
|
1469
|
+
setMobileMenuOpen(false);
|
|
1470
|
+
},
|
|
1471
|
+
storyId
|
|
1472
|
+
}
|
|
1473
|
+
)
|
|
1408
1474
|
}
|
|
1409
1475
|
)
|
|
1410
1476
|
}
|
|
1411
|
-
)
|
|
1477
|
+
)
|
|
1412
1478
|
}
|
|
1413
1479
|
);
|
|
1414
1480
|
}
|
|
@@ -1524,10 +1590,36 @@ var MobileMenuDrawer = (0, import_react13.memo)(
|
|
|
1524
1590
|
(0, import_react13.forwardRef)(({ children }, ref) => {
|
|
1525
1591
|
const [mobileMenuOpen, setMobileMenuOpen] = (0, import_react13.useState)(false);
|
|
1526
1592
|
const { scrollToSelectedNode, scrollRef } = useSelectedNode();
|
|
1527
|
-
const
|
|
1593
|
+
const theme = (0, import_react_native_theming9.useTheme)();
|
|
1594
|
+
const dragY = (0, import_react_native7.useAnimatedValue)(0);
|
|
1595
|
+
const panResponder = (0, import_react13.useRef)(
|
|
1596
|
+
import_react_native7.PanResponder.create({
|
|
1597
|
+
onStartShouldSetPanResponder: () => true,
|
|
1598
|
+
onMoveShouldSetPanResponder: (_, gestureState) => {
|
|
1599
|
+
return gestureState.dy > 0;
|
|
1600
|
+
},
|
|
1601
|
+
onPanResponderMove: (_, gestureState) => {
|
|
1602
|
+
if (gestureState.dy > 0) {
|
|
1603
|
+
dragY.setValue(gestureState.dy);
|
|
1604
|
+
}
|
|
1605
|
+
},
|
|
1606
|
+
onPanResponderRelease: (_, gestureState) => {
|
|
1607
|
+
if (gestureState.dy > 50) {
|
|
1608
|
+
import_react_native7.Keyboard.dismiss();
|
|
1609
|
+
setMobileMenuOpen(false);
|
|
1610
|
+
}
|
|
1611
|
+
import_react_native7.Animated.timing(dragY, {
|
|
1612
|
+
toValue: 0,
|
|
1613
|
+
duration: 300,
|
|
1614
|
+
useNativeDriver: true
|
|
1615
|
+
}).start();
|
|
1616
|
+
}
|
|
1617
|
+
})
|
|
1618
|
+
).current;
|
|
1528
1619
|
(0, import_react13.useImperativeHandle)(ref, () => ({
|
|
1529
1620
|
setMobileMenuOpen: (open) => {
|
|
1530
1621
|
if (open) {
|
|
1622
|
+
dragY.setValue(0);
|
|
1531
1623
|
scrollToSelectedNode();
|
|
1532
1624
|
setMobileMenuOpen(true);
|
|
1533
1625
|
} else {
|
|
@@ -1536,48 +1628,73 @@ var MobileMenuDrawer = (0, import_react13.memo)(
|
|
|
1536
1628
|
}
|
|
1537
1629
|
}
|
|
1538
1630
|
}));
|
|
1539
|
-
const
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
backgroundColor: theme.
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1631
|
+
const handleStyle = (0, import_react13.useMemo)(
|
|
1632
|
+
() => ({
|
|
1633
|
+
width: 40,
|
|
1634
|
+
height: 5,
|
|
1635
|
+
backgroundColor: theme.color.mediumdark,
|
|
1636
|
+
borderRadius: 2.5,
|
|
1637
|
+
alignSelf: "center",
|
|
1638
|
+
// TypeScript needs this to recognize 'center' as a valid FlexAlignType
|
|
1639
|
+
marginVertical: 8
|
|
1640
|
+
}),
|
|
1641
|
+
[theme.color.mediumdark]
|
|
1642
|
+
);
|
|
1549
1643
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1550
1644
|
import_react_native7.Modal,
|
|
1551
1645
|
{
|
|
1552
1646
|
visible: mobileMenuOpen,
|
|
1553
|
-
style: bgColorStyle,
|
|
1554
1647
|
animationType: "slide",
|
|
1555
1648
|
transparent: true,
|
|
1649
|
+
statusBarTranslucent: true,
|
|
1556
1650
|
onRequestClose: () => setMobileMenuOpen(false),
|
|
1557
1651
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native7.KeyboardAvoidingView, { behavior: "height", style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native7.SafeAreaView, { style: { justifyContent: "flex-end", flex: 1 }, children: [
|
|
1558
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1559
|
-
|
|
1652
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native7.View, { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native7.Pressable, { style: { flex: 1 }, onPress: () => setMobileMenuOpen(false) }) }),
|
|
1653
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1654
|
+
import_react_native7.Animated.View,
|
|
1560
1655
|
{
|
|
1561
|
-
style:
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1656
|
+
style: [
|
|
1657
|
+
{
|
|
1658
|
+
height: "65%",
|
|
1659
|
+
borderTopColor: theme.appBorderColor,
|
|
1660
|
+
borderTopWidth: 1,
|
|
1661
|
+
borderStyle: "solid",
|
|
1662
|
+
backgroundColor: theme.background.content,
|
|
1663
|
+
elevation: 8
|
|
1664
|
+
},
|
|
1665
|
+
{ transform: [{ translateY: dragY }] }
|
|
1666
|
+
],
|
|
1667
|
+
children: [
|
|
1668
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1669
|
+
import_react_native7.View,
|
|
1670
|
+
{
|
|
1671
|
+
...panResponder.panHandlers,
|
|
1672
|
+
style: {
|
|
1673
|
+
alignItems: "center",
|
|
1674
|
+
justifyContent: "center",
|
|
1675
|
+
backgroundColor: theme.background.content
|
|
1676
|
+
},
|
|
1677
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native7.View, { style: handleStyle })
|
|
1678
|
+
}
|
|
1679
|
+
),
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1681
|
+
import_react_native7.ScrollView,
|
|
1682
|
+
{
|
|
1683
|
+
ref: scrollRef,
|
|
1684
|
+
keyboardShouldPersistTaps: "handled",
|
|
1685
|
+
style: {
|
|
1686
|
+
flex: 1,
|
|
1687
|
+
paddingBottom: 150,
|
|
1688
|
+
alignSelf: "flex-end",
|
|
1689
|
+
width: "100%",
|
|
1690
|
+
backgroundColor: theme.background.content
|
|
1691
|
+
},
|
|
1692
|
+
children
|
|
1693
|
+
}
|
|
1694
|
+
)
|
|
1695
|
+
]
|
|
1579
1696
|
}
|
|
1580
|
-
)
|
|
1697
|
+
)
|
|
1581
1698
|
] }) })
|
|
1582
1699
|
}
|
|
1583
1700
|
);
|
|
@@ -1691,13 +1808,7 @@ var mobileMenuDrawerContentStyle = {
|
|
|
1691
1808
|
paddingTop: 4,
|
|
1692
1809
|
paddingBottom: 4
|
|
1693
1810
|
};
|
|
1694
|
-
var LiteUI = ({
|
|
1695
|
-
storage,
|
|
1696
|
-
theme,
|
|
1697
|
-
storyHash,
|
|
1698
|
-
story,
|
|
1699
|
-
children
|
|
1700
|
-
}) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_theming10.ThemeProvider, { theme, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_ui_common7.StorageProvider, { storage, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_ui_common7.LayoutProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Layout, { storyHash, story, children }) }) }) }) });
|
|
1811
|
+
var LiteUI = ({ storage, theme, storyHash, story, children }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_theming10.ThemeProvider, { theme, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_ui_common7.StorageProvider, { storage, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_ui_common7.LayoutProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Layout, { storyHash, story, children }) }) }) }) });
|
|
1701
1812
|
var Layout = ({
|
|
1702
1813
|
storyHash,
|
|
1703
1814
|
story,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/react-native-ui-lite",
|
|
3
|
-
"version": "9.0.0-
|
|
3
|
+
"version": "9.0.0-rc.5",
|
|
4
4
|
"description": "lightweight ui components for react native storybook",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
"typescript": "~5.8.3"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@storybook/react": "9
|
|
62
|
-
"@storybook/react-native-theming": "^9.0.0-
|
|
63
|
-
"@storybook/react-native-ui-common": "^9.0.0-
|
|
61
|
+
"@storybook/react": "^9",
|
|
62
|
+
"@storybook/react-native-theming": "^9.0.0-rc.5",
|
|
63
|
+
"@storybook/react-native-ui-common": "^9.0.0-rc.5",
|
|
64
64
|
"fuse.js": "^7.0.0",
|
|
65
65
|
"memoizerific": "^1.11.3",
|
|
66
66
|
"polished": "^4.3.1",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"react": "*",
|
|
71
71
|
"react-native": ">=0.57.0",
|
|
72
|
-
"storybook": "9
|
|
72
|
+
"storybook": "^9"
|
|
73
73
|
},
|
|
74
74
|
"engines": {
|
|
75
75
|
"node": ">=18.0.0"
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"publishConfig": {
|
|
78
78
|
"access": "public"
|
|
79
79
|
},
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "bed522706a1296d1550ff4446045b71d53e0902d"
|
|
81
81
|
}
|
package/src/Layout.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Args, StoryContext } from '@storybook/csf';
|
|
2
2
|
import type { ReactRenderer } from '@storybook/react';
|
|
3
|
-
import { styled,
|
|
3
|
+
import { styled, ThemeProvider, useTheme } from '@storybook/react-native-theming';
|
|
4
4
|
import {
|
|
5
5
|
IconButton,
|
|
6
6
|
LayoutProvider,
|
|
7
|
-
|
|
7
|
+
SBUI,
|
|
8
8
|
StorageProvider,
|
|
9
9
|
useLayout,
|
|
10
10
|
useStoreBooleanState,
|
|
@@ -64,19 +64,7 @@ const mobileMenuDrawerContentStyle = {
|
|
|
64
64
|
paddingBottom: 4,
|
|
65
65
|
} satisfies ViewStyle;
|
|
66
66
|
|
|
67
|
-
export const LiteUI = ({
|
|
68
|
-
storage,
|
|
69
|
-
theme,
|
|
70
|
-
storyHash,
|
|
71
|
-
story,
|
|
72
|
-
children,
|
|
73
|
-
}: {
|
|
74
|
-
storage: Storage;
|
|
75
|
-
theme: Theme;
|
|
76
|
-
storyHash: API_IndexHash | undefined;
|
|
77
|
-
story?: StoryContext<ReactRenderer, Args>;
|
|
78
|
-
children: ReactNode | ReactNode[];
|
|
79
|
-
}): ReactElement => (
|
|
67
|
+
export const LiteUI: SBUI = ({ storage, theme, storyHash, story, children }): ReactElement => (
|
|
80
68
|
<>
|
|
81
69
|
<ThemeProvider theme={theme}>
|
|
82
70
|
{/* @ts-ignore something weird with story type */}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { styled, useTheme } from '@storybook/react-native-theming';
|
|
2
|
-
import { forwardRef, useImperativeHandle, useMemo, useState } from 'react';
|
|
2
|
+
import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
Animated,
|
|
5
|
+
Easing,
|
|
6
|
+
Keyboard,
|
|
7
|
+
Platform,
|
|
6
8
|
SafeAreaView,
|
|
7
9
|
ScrollView,
|
|
8
10
|
StyleProp,
|
|
9
11
|
Text,
|
|
12
|
+
useAnimatedValue,
|
|
13
|
+
useWindowDimensions,
|
|
10
14
|
View,
|
|
11
15
|
ViewStyle,
|
|
12
16
|
} from 'react-native';
|
|
@@ -23,6 +27,63 @@ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: st
|
|
|
23
27
|
({ storyId }, ref) => {
|
|
24
28
|
const theme = useTheme();
|
|
25
29
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
30
|
+
const { height } = useWindowDimensions();
|
|
31
|
+
const panelHeight = useAnimatedValue(height / 2);
|
|
32
|
+
const positionBottomAnimation = useAnimatedValue(0);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
// Define keyboard show handler
|
|
36
|
+
const handleKeyboardShow = ({ endCoordinates, duration, easing }) => {
|
|
37
|
+
Animated.parallel([
|
|
38
|
+
Animated.timing(positionBottomAnimation, {
|
|
39
|
+
toValue: -endCoordinates.height, // Negative to move up
|
|
40
|
+
duration,
|
|
41
|
+
useNativeDriver: false,
|
|
42
|
+
easing: Easing[easing] || Easing.out(Easing.ease),
|
|
43
|
+
}),
|
|
44
|
+
|
|
45
|
+
Animated.timing(panelHeight, {
|
|
46
|
+
toValue: (height - endCoordinates.height) / 2,
|
|
47
|
+
duration: duration + 250,
|
|
48
|
+
useNativeDriver: false,
|
|
49
|
+
easing: Easing[easing] || Easing.out(Easing.ease),
|
|
50
|
+
}),
|
|
51
|
+
]).start();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Define keyboard hide handler
|
|
55
|
+
const handleKeyboardHide = ({ duration, easing }) => {
|
|
56
|
+
Animated.parallel([
|
|
57
|
+
Animated.timing(positionBottomAnimation, {
|
|
58
|
+
toValue: 0, // Back to original position
|
|
59
|
+
duration,
|
|
60
|
+
useNativeDriver: false,
|
|
61
|
+
easing: Easing[easing] || Easing.out(Easing.ease),
|
|
62
|
+
}),
|
|
63
|
+
|
|
64
|
+
Animated.timing(panelHeight, {
|
|
65
|
+
toValue: height / 2,
|
|
66
|
+
duration,
|
|
67
|
+
useNativeDriver: false,
|
|
68
|
+
easing: Easing[easing] || Easing.out(Easing.ease),
|
|
69
|
+
}),
|
|
70
|
+
]).start();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Add keyboard event listeners
|
|
74
|
+
const showSubscription = Keyboard.addListener('keyboardDidShow', handleKeyboardShow);
|
|
75
|
+
const willShowSubscription = Keyboard.addListener('keyboardWillShow', handleKeyboardShow);
|
|
76
|
+
const hideSubscription = Keyboard.addListener('keyboardWillHide', handleKeyboardHide);
|
|
77
|
+
const didHideSubscription = Keyboard.addListener('keyboardDidHide', handleKeyboardHide);
|
|
78
|
+
|
|
79
|
+
// Clean up subscriptions on unmount
|
|
80
|
+
return () => {
|
|
81
|
+
showSubscription.remove();
|
|
82
|
+
willShowSubscription.remove();
|
|
83
|
+
hideSubscription.remove();
|
|
84
|
+
didHideSubscription.remove();
|
|
85
|
+
};
|
|
86
|
+
}, [height, panelHeight, positionBottomAnimation]);
|
|
26
87
|
|
|
27
88
|
useImperativeHandle(ref, () => ({
|
|
28
89
|
setAddonsPanelOpen: (open: boolean) => {
|
|
@@ -34,34 +95,45 @@ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: st
|
|
|
34
95
|
},
|
|
35
96
|
}));
|
|
36
97
|
|
|
98
|
+
if (!mobileMenuOpen) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
37
102
|
return (
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
103
|
+
<Animated.View
|
|
104
|
+
style={{
|
|
105
|
+
position: 'absolute',
|
|
106
|
+
bottom: 0,
|
|
107
|
+
left: 0,
|
|
108
|
+
right: 0,
|
|
109
|
+
height: panelHeight,
|
|
110
|
+
transform: [{ translateY: positionBottomAnimation }],
|
|
111
|
+
}}
|
|
43
112
|
>
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
113
|
+
<SafeAreaView
|
|
114
|
+
style={{
|
|
115
|
+
justifyContent: 'flex-end',
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
<View
|
|
119
|
+
style={{
|
|
120
|
+
height: '100%',
|
|
121
|
+
backgroundColor: theme.background.content,
|
|
122
|
+
paddingTop: 10,
|
|
123
|
+
borderTopColor: theme.appBorderColor,
|
|
124
|
+
borderTopWidth: 1,
|
|
125
|
+
paddingBottom: Platform.OS === 'android' ? 16 : 0,
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
<AddonsTabs
|
|
129
|
+
onClose={() => {
|
|
130
|
+
setMobileMenuOpen(false);
|
|
53
131
|
}}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
storyId={storyId}
|
|
60
|
-
/>
|
|
61
|
-
</View>
|
|
62
|
-
</SafeAreaView>
|
|
63
|
-
</KeyboardAvoidingView>
|
|
64
|
-
</Modal>
|
|
132
|
+
storyId={storyId}
|
|
133
|
+
/>
|
|
134
|
+
</View>
|
|
135
|
+
</SafeAreaView>
|
|
136
|
+
</Animated.View>
|
|
65
137
|
);
|
|
66
138
|
}
|
|
67
139
|
);
|
package/src/MobileMenuDrawer.tsx
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { useTheme } from '@storybook/react-native-theming';
|
|
2
|
-
import { forwardRef, memo, ReactNode, useImperativeHandle, useMemo, useState } from 'react';
|
|
2
|
+
import { forwardRef, memo, ReactNode, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import {
|
|
4
|
+
Animated,
|
|
4
5
|
Keyboard,
|
|
5
6
|
KeyboardAvoidingView,
|
|
6
7
|
Modal,
|
|
8
|
+
PanResponder,
|
|
9
|
+
PanResponderInstance,
|
|
7
10
|
Pressable,
|
|
8
11
|
SafeAreaView,
|
|
9
12
|
ScrollView,
|
|
10
|
-
|
|
11
|
-
useWindowDimensions,
|
|
13
|
+
useAnimatedValue,
|
|
12
14
|
View,
|
|
13
|
-
ViewStyle,
|
|
14
15
|
} from 'react-native';
|
|
15
16
|
|
|
16
17
|
import { useSelectedNode } from './SelectedNodeProvider';
|
|
@@ -27,10 +28,45 @@ export const MobileMenuDrawer = memo(
|
|
|
27
28
|
forwardRef<MobileMenuDrawerRef, MobileMenuDrawerProps>(({ children }, ref) => {
|
|
28
29
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
29
30
|
const { scrollToSelectedNode, scrollRef } = useSelectedNode();
|
|
30
|
-
const
|
|
31
|
+
const theme = useTheme();
|
|
32
|
+
|
|
33
|
+
// Create a reference for the drag handle animation
|
|
34
|
+
const dragY = useAnimatedValue(0);
|
|
35
|
+
|
|
36
|
+
// Create the pan responder for handling drag gestures
|
|
37
|
+
const panResponder = useRef<PanResponderInstance>(
|
|
38
|
+
PanResponder.create({
|
|
39
|
+
onStartShouldSetPanResponder: () => true,
|
|
40
|
+
onMoveShouldSetPanResponder: (_, gestureState) => {
|
|
41
|
+
// Only capture downward dragging motions
|
|
42
|
+
return gestureState.dy > 0;
|
|
43
|
+
},
|
|
44
|
+
onPanResponderMove: (_, gestureState) => {
|
|
45
|
+
// Update dragY based on the gesture
|
|
46
|
+
if (gestureState.dy > 0) {
|
|
47
|
+
dragY.setValue(gestureState.dy);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
onPanResponderRelease: (_, gestureState) => {
|
|
51
|
+
// If dragged down enough, close the drawer
|
|
52
|
+
if (gestureState.dy > 50) {
|
|
53
|
+
Keyboard.dismiss();
|
|
54
|
+
setMobileMenuOpen(false);
|
|
55
|
+
}
|
|
56
|
+
// Reset the drag position
|
|
57
|
+
Animated.timing(dragY, {
|
|
58
|
+
toValue: 0,
|
|
59
|
+
duration: 300,
|
|
60
|
+
useNativeDriver: true,
|
|
61
|
+
}).start();
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
).current;
|
|
65
|
+
|
|
31
66
|
useImperativeHandle(ref, () => ({
|
|
32
67
|
setMobileMenuOpen: (open: boolean) => {
|
|
33
68
|
if (open) {
|
|
69
|
+
dragY.setValue(0);
|
|
34
70
|
scrollToSelectedNode();
|
|
35
71
|
setMobileMenuOpen(true);
|
|
36
72
|
} else {
|
|
@@ -39,41 +75,65 @@ export const MobileMenuDrawer = memo(
|
|
|
39
75
|
}
|
|
40
76
|
},
|
|
41
77
|
}));
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
height:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
78
|
+
|
|
79
|
+
// Create the styles for the drag handle
|
|
80
|
+
const handleStyle = useMemo(
|
|
81
|
+
() => ({
|
|
82
|
+
width: 40,
|
|
83
|
+
height: 5,
|
|
84
|
+
backgroundColor: theme.color.mediumdark,
|
|
85
|
+
borderRadius: 2.5,
|
|
86
|
+
alignSelf: 'center' as const, // TypeScript needs this to recognize 'center' as a valid FlexAlignType
|
|
87
|
+
marginVertical: 8,
|
|
88
|
+
}),
|
|
89
|
+
[theme.color.mediumdark]
|
|
90
|
+
);
|
|
52
91
|
|
|
53
92
|
return (
|
|
54
93
|
<Modal
|
|
55
94
|
visible={mobileMenuOpen}
|
|
56
|
-
style={bgColorStyle}
|
|
57
95
|
animationType="slide"
|
|
58
96
|
transparent
|
|
97
|
+
statusBarTranslucent
|
|
59
98
|
onRequestClose={() => setMobileMenuOpen(false)}
|
|
60
99
|
>
|
|
61
100
|
<KeyboardAvoidingView behavior="height" style={{ flex: 1 }}>
|
|
62
101
|
<SafeAreaView style={{ justifyContent: 'flex-end', flex: 1 }}>
|
|
63
|
-
<View
|
|
64
|
-
style={{ flex: 1, borderBottomColor: theme.appBorderColor, borderBottomWidth: 1 }}
|
|
65
|
-
>
|
|
102
|
+
<View style={{ flex: 1 }}>
|
|
66
103
|
<Pressable style={{ flex: 1 }} onPress={() => setMobileMenuOpen(false)}></Pressable>
|
|
67
104
|
</View>
|
|
68
105
|
|
|
69
|
-
<View
|
|
106
|
+
<Animated.View
|
|
107
|
+
style={[
|
|
108
|
+
{
|
|
109
|
+
height: '65%',
|
|
110
|
+
borderTopColor: theme.appBorderColor,
|
|
111
|
+
borderTopWidth: 1,
|
|
112
|
+
borderStyle: 'solid',
|
|
113
|
+
backgroundColor: theme.background.content,
|
|
114
|
+
elevation: 8,
|
|
115
|
+
},
|
|
116
|
+
{ transform: [{ translateY: dragY }] },
|
|
117
|
+
]}
|
|
118
|
+
>
|
|
119
|
+
{/* Drag handle */}
|
|
120
|
+
<View
|
|
121
|
+
{...panResponder.panHandlers}
|
|
122
|
+
style={{
|
|
123
|
+
alignItems: 'center',
|
|
124
|
+
justifyContent: 'center',
|
|
125
|
+
backgroundColor: theme.background.content,
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
<View style={handleStyle} />
|
|
129
|
+
</View>
|
|
130
|
+
|
|
70
131
|
<ScrollView
|
|
71
132
|
ref={scrollRef}
|
|
72
133
|
keyboardShouldPersistTaps="handled"
|
|
73
134
|
style={{
|
|
74
135
|
flex: 1,
|
|
75
136
|
paddingBottom: 150,
|
|
76
|
-
paddingTop: 24,
|
|
77
137
|
alignSelf: 'flex-end',
|
|
78
138
|
width: '100%',
|
|
79
139
|
backgroundColor: theme.background.content,
|
|
@@ -81,7 +141,7 @@ export const MobileMenuDrawer = memo(
|
|
|
81
141
|
>
|
|
82
142
|
{children}
|
|
83
143
|
</ScrollView>
|
|
84
|
-
</View>
|
|
144
|
+
</Animated.View>
|
|
85
145
|
</SafeAreaView>
|
|
86
146
|
</KeyboardAvoidingView>
|
|
87
147
|
</Modal>
|
package/src/Tree.tsx
CHANGED
|
@@ -256,6 +256,7 @@ export const Tree = React.memo<{
|
|
|
256
256
|
// Omit single-story components from the list of nodes.
|
|
257
257
|
const collapsedItems = useMemo(
|
|
258
258
|
() => Object.keys(data).filter((id) => !singleStoryComponentIds.includes(id)),
|
|
259
|
+
// eslint-disable-next-line react-compiler/react-compiler
|
|
259
260
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
260
261
|
[singleStoryComponentIds]
|
|
261
262
|
);
|
|
@@ -281,6 +282,7 @@ export const Tree = React.memo<{
|
|
|
281
282
|
},
|
|
282
283
|
{ ...data }
|
|
283
284
|
);
|
|
285
|
+
// eslint-disable-next-line react-compiler/react-compiler
|
|
284
286
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
285
287
|
}, [data]);
|
|
286
288
|
|