@ng-native/expo 0.5.0 → 0.7.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/dist/expo-ui-components.d.ts +255 -11
- package/dist/expo-ui-components.js +468 -3
- package/dist/expo-ui-components.js.map +1 -1
- package/dist/expo-ui.js +9 -0
- package/dist/expo-ui.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ui-bottom-sheet-content.d.ts +18 -0
- package/dist/ui-bottom-sheet-content.js +29 -0
- package/dist/ui-bottom-sheet-content.js.map +1 -0
- package/dist/ui-bottom-sheet-view.d.ts +25 -0
- package/dist/ui-bottom-sheet-view.js +55 -0
- package/dist/ui-bottom-sheet-view.js.map +1 -0
- package/package.json +2 -2
|
@@ -23,9 +23,12 @@
|
|
|
23
23
|
* Still register the names with `registerExpoUiViews`: the component types the element, the
|
|
24
24
|
* registration is what makes it commit as the SwiftUI or Compose view.
|
|
25
25
|
*/
|
|
26
|
-
import { Component, DestroyRef, forwardRef, ElementRef, booleanAttribute, computed, inject, input, model, output, signal, } from '@angular/core';
|
|
27
|
-
import { HostEngine, keepNativeView, nativePlatform, } from '@ng-native/fabric';
|
|
26
|
+
import { Component, DestroyRef, forwardRef, ElementRef, InjectionToken, Injector, afterNextRender, booleanAttribute, computed, contentChildren, effect, inject, input, linkedSignal, model, output, signal, untracked, viewChild, } from '@angular/core';
|
|
27
|
+
import { Engine, HostEngine, keepNativeView, nativePlatform, } from '@ng-native/fabric';
|
|
28
|
+
import { optional } from "./native.js";
|
|
28
29
|
import { optionalBoolean, optionalNumber } from "./transforms.js";
|
|
30
|
+
import { UiBottomSheetContent } from "./ui-bottom-sheet-content.js";
|
|
31
|
+
import { UiBottomSheetView } from "./ui-bottom-sheet-view.js";
|
|
29
32
|
import * as i0 from "@angular/core";
|
|
30
33
|
/**
|
|
31
34
|
* Says the component's host is the `@expo/ui` view its selector is registered as. A component of
|
|
@@ -165,7 +168,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
165
168
|
}], propDecorators: { modifiers: [{ type: i0.Input, args: [{ isSignal: true, alias: "modifiers", required: false }] }] } });
|
|
166
169
|
/**
|
|
167
170
|
* A SwiftUI `Button`, as a menu item or on its own, or Compose's on Android, which draws `label` as
|
|
168
|
-
* text inside it. `systemImage` and `role` are SwiftUI's alone.
|
|
171
|
+
* text inside it. `systemImage` and `role` are SwiftUI's alone. A `close` button with no label and
|
|
172
|
+
* no content is the system's own close button, from iOS 26.
|
|
169
173
|
*/
|
|
170
174
|
export class UiButton {
|
|
171
175
|
nativeView = nativeView();
|
|
@@ -1194,4 +1198,465 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
1194
1198
|
host: { '[title]': 'title()', '[modifiers]': 'modifiers()' },
|
|
1195
1199
|
}]
|
|
1196
1200
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], modifiers: [{ type: i0.Input, args: [{ isSignal: true, alias: "modifiers", required: false }] }] } });
|
|
1201
|
+
/**
|
|
1202
|
+
* A SwiftUI `Group`, iOS only: its children as they are, with no layout of its own. What it is for
|
|
1203
|
+
* is `modifiers` that belong to several views at once, or to content that takes none itself, as a
|
|
1204
|
+
* sheet's presentation modifiers go on a group around a `ui-view-host`.
|
|
1205
|
+
*/
|
|
1206
|
+
export class UiGroup {
|
|
1207
|
+
nativeView = nativeView();
|
|
1208
|
+
modifiers = input(/* @ts-ignore */
|
|
1209
|
+
...(ngDevMode ? [undefined, { debugName: "modifiers" }] : /* istanbul ignore next */ []));
|
|
1210
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1211
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: UiGroup, isStandalone: true, selector: "ui-group", inputs: { modifiers: { classPropertyName: "modifiers", publicName: "modifiers", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "modifiers": "modifiers()" } }, ngImport: i0, template: '<ng-content />', isInline: true });
|
|
1212
|
+
}
|
|
1213
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiGroup, decorators: [{
|
|
1214
|
+
type: Component,
|
|
1215
|
+
args: [{
|
|
1216
|
+
selector: 'ui-group',
|
|
1217
|
+
template: '<ng-content />',
|
|
1218
|
+
host: { '[modifiers]': 'modifiers()' },
|
|
1219
|
+
}]
|
|
1220
|
+
}], propDecorators: { modifiers: [{ type: i0.Input, args: [{ isSignal: true, alias: "modifiers", required: false }] }] } });
|
|
1221
|
+
/**
|
|
1222
|
+
* A SwiftUI `NavigationStack`, iOS only: the bar a `ui-toolbar` inside it puts its items in, and
|
|
1223
|
+
* that a `navigationTitle` modifier on its content titles.
|
|
1224
|
+
*/
|
|
1225
|
+
export class UiNavigationStack {
|
|
1226
|
+
nativeView = nativeView();
|
|
1227
|
+
modifiers = input(/* @ts-ignore */
|
|
1228
|
+
...(ngDevMode ? [undefined, { debugName: "modifiers" }] : /* istanbul ignore next */ []));
|
|
1229
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiNavigationStack, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1230
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: UiNavigationStack, isStandalone: true, selector: "ui-navigation-stack", inputs: { modifiers: { classPropertyName: "modifiers", publicName: "modifiers", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "modifiers": "modifiers()" } }, ngImport: i0, template: '<ng-content />', isInline: true });
|
|
1231
|
+
}
|
|
1232
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiNavigationStack, decorators: [{
|
|
1233
|
+
type: Component,
|
|
1234
|
+
args: [{
|
|
1235
|
+
selector: 'ui-navigation-stack',
|
|
1236
|
+
template: '<ng-content />',
|
|
1237
|
+
host: { '[modifiers]': 'modifiers()' },
|
|
1238
|
+
}]
|
|
1239
|
+
}], propDecorators: { modifiers: [{ type: i0.Input, args: [{ isSignal: true, alias: "modifiers", required: false }] }] } });
|
|
1240
|
+
/**
|
|
1241
|
+
* SwiftUI's `toolbar`, iOS only. Its children are the view the toolbar belongs to, and its items go
|
|
1242
|
+
* in `<ui-slot name="content">`, each a `ui-toolbar-item`. It shows in the bar of the
|
|
1243
|
+
* `ui-navigation-stack` around it.
|
|
1244
|
+
*/
|
|
1245
|
+
export class UiToolbar {
|
|
1246
|
+
nativeView = nativeView();
|
|
1247
|
+
modifiers = input(/* @ts-ignore */
|
|
1248
|
+
...(ngDevMode ? [undefined, { debugName: "modifiers" }] : /* istanbul ignore next */ []));
|
|
1249
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiToolbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1250
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: UiToolbar, isStandalone: true, selector: "ui-toolbar", inputs: { modifiers: { classPropertyName: "modifiers", publicName: "modifiers", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "modifiers": "modifiers()" } }, ngImport: i0, template: '<ng-content />', isInline: true });
|
|
1251
|
+
}
|
|
1252
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiToolbar, decorators: [{
|
|
1253
|
+
type: Component,
|
|
1254
|
+
args: [{
|
|
1255
|
+
selector: 'ui-toolbar',
|
|
1256
|
+
template: '<ng-content />',
|
|
1257
|
+
host: { '[modifiers]': 'modifiers()' },
|
|
1258
|
+
}]
|
|
1259
|
+
}], propDecorators: { modifiers: [{ type: i0.Input, args: [{ isSignal: true, alias: "modifiers", required: false }] }] } });
|
|
1260
|
+
/**
|
|
1261
|
+
* One item of a `ui-toolbar`, SwiftUI's `ToolbarItem`: a `ui-button`, or a `ui-text` as a title
|
|
1262
|
+
* with `placement="principal"`. Unplaced, SwiftUI places it. A placement the OS does not have is
|
|
1263
|
+
* read as `automatic`.
|
|
1264
|
+
*
|
|
1265
|
+
* Written inside a `ui-bottom-sheet` it goes in the sheet's own toolbar, which is how a sheet
|
|
1266
|
+
* shows the system's close button.
|
|
1267
|
+
*/
|
|
1268
|
+
export class UiToolbarItem {
|
|
1269
|
+
nativeView = nativeView();
|
|
1270
|
+
placement = input(/* @ts-ignore */
|
|
1271
|
+
...(ngDevMode ? [undefined, { debugName: "placement" }] : /* istanbul ignore next */ []));
|
|
1272
|
+
/** How readily the item gives up its place when the bar runs out of room, from iOS 27. */
|
|
1273
|
+
visibilityPriority = input(/* @ts-ignore */
|
|
1274
|
+
...(ngDevMode ? [undefined, { debugName: "visibilityPriority" }] : /* istanbul ignore next */ []));
|
|
1275
|
+
/** What the slot tells the toolbar about itself: only what is set, so SwiftUI decides the rest. */
|
|
1276
|
+
extraProps = computed(() => {
|
|
1277
|
+
const placement = this.placement();
|
|
1278
|
+
const visibilityPriority = this.visibilityPriority();
|
|
1279
|
+
if (!placement && !visibilityPriority)
|
|
1280
|
+
return undefined;
|
|
1281
|
+
return { ...(placement && { placement }), ...(visibilityPriority && { visibilityPriority }) };
|
|
1282
|
+
}, /* @ts-ignore */
|
|
1283
|
+
...(ngDevMode ? [{ debugName: "extraProps" }] : /* istanbul ignore next */ []));
|
|
1284
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiToolbarItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1285
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: UiToolbarItem, isStandalone: true, selector: "ui-toolbar-item", inputs: { placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, visibilityPriority: { classPropertyName: "visibilityPriority", publicName: "visibilityPriority", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "name": "\"item\"", "extraProps": "extraProps()" } }, ngImport: i0, template: '<ng-content />', isInline: true });
|
|
1286
|
+
}
|
|
1287
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiToolbarItem, decorators: [{
|
|
1288
|
+
type: Component,
|
|
1289
|
+
args: [{
|
|
1290
|
+
selector: 'ui-toolbar-item',
|
|
1291
|
+
template: '<ng-content />',
|
|
1292
|
+
host: { '[name]': '"item"', '[extraProps]': 'extraProps()' },
|
|
1293
|
+
}]
|
|
1294
|
+
}], propDecorators: { placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], visibilityPriority: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibilityPriority", required: false }] }] } });
|
|
1295
|
+
/** The detents of a sheet given none and not sized to its content. */
|
|
1296
|
+
const HALF_AND_FULL = ['medium', 'large'];
|
|
1297
|
+
/** The window's width as the engine knows it, or undefined before the platform has said. */
|
|
1298
|
+
function windowWidth() {
|
|
1299
|
+
const node = inject(ElementRef).nativeElement;
|
|
1300
|
+
const engine = (node.host ?? inject(HostEngine));
|
|
1301
|
+
const read = () => engine.viewport?.width || undefined;
|
|
1302
|
+
const width = signal(read(), /* @ts-ignore */
|
|
1303
|
+
...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
|
|
1304
|
+
const stop = engine.watchViewport?.(() => width.set(read()));
|
|
1305
|
+
if (stop)
|
|
1306
|
+
inject(DestroyRef).onDestroy(stop);
|
|
1307
|
+
return width;
|
|
1308
|
+
}
|
|
1309
|
+
/**
|
|
1310
|
+
* A sheet that slides up from the bottom of the screen, opened from any component: SwiftUI's on
|
|
1311
|
+
* iOS, Material's on Android.
|
|
1312
|
+
*
|
|
1313
|
+
* ```html
|
|
1314
|
+
* <ui-bottom-sheet [(open)]="sorting" fitToContents>
|
|
1315
|
+
* <app-sort-options (done)="sorting.set(false)" />
|
|
1316
|
+
* </ui-bottom-sheet>
|
|
1317
|
+
* ```
|
|
1318
|
+
*
|
|
1319
|
+
* `open` presents and dismisses it, and is written back when the user dismisses it. Its content is
|
|
1320
|
+
* what is written inside it, the app's own components, in the tree while the sheet is on screen.
|
|
1321
|
+
*
|
|
1322
|
+
* A `ui-toolbar-item` written inside it is not content: on iOS it goes in a toolbar of the sheet's
|
|
1323
|
+
* own, in a bar across its top, which is where the system's close button belongs.
|
|
1324
|
+
*
|
|
1325
|
+
* ```html
|
|
1326
|
+
* <ui-bottom-sheet [(open)]="sorting">
|
|
1327
|
+
* <ui-toolbar-item placement="cancellationAction">
|
|
1328
|
+
* <ui-button role="close" (buttonPress)="sorting.set(false)" />
|
|
1329
|
+
* </ui-toolbar-item>
|
|
1330
|
+
* <app-sort-options />
|
|
1331
|
+
* </ui-bottom-sheet>
|
|
1332
|
+
* ```
|
|
1333
|
+
*
|
|
1334
|
+
* Compose's sheet has no toolbar, so Android draws no item. Nor does an iOS build whose `@expo/ui`
|
|
1335
|
+
* is older than 57.0.20, which Expo Go's can be: it warns, and shows the sheet without one.
|
|
1336
|
+
*
|
|
1337
|
+
* The two platforms drive a sheet differently, and this is where that difference ends. SwiftUI's
|
|
1338
|
+
* stays in the tree and is presented by `isPresented`, reporting `isPresentedChange` and
|
|
1339
|
+
* `dismiss`. Compose's shows for as long as it is in the tree, and reports `dismissRequest`.
|
|
1340
|
+
*
|
|
1341
|
+
* Unlike the other components here, the element this is mounted on is a plain view, which takes
|
|
1342
|
+
* no room and needs no `ui-host` around it. The sheet is inside it, wrapped as `@expo/ui`'s own
|
|
1343
|
+
* React component wraps one: a `ui-host`, the sheet, on iOS a `ui-group` that carries the
|
|
1344
|
+
* presentation modifiers, and a `ui-view-host` holding the one view the content goes in. With
|
|
1345
|
+
* toolbar items, the view host is in a `ui-toolbar` in a `ui-navigation-stack`, under the group.
|
|
1346
|
+
*/
|
|
1347
|
+
export class UiBottomSheet {
|
|
1348
|
+
/**
|
|
1349
|
+
* The functions of Compose's sheet, none of them on iOS, or null where `@expo/ui` is not in the
|
|
1350
|
+
* build and there is no sheet. Overridden in a test to hide a sheet without a device.
|
|
1351
|
+
*/
|
|
1352
|
+
static SOURCE = new InjectionToken('angular-native.bottomSheetSource', {
|
|
1353
|
+
factory: () => optional(() => {
|
|
1354
|
+
const core = require('expo-modules-core');
|
|
1355
|
+
const module = core.requireOptionalNativeModule('ExpoUI');
|
|
1356
|
+
return module ? (module.ViewPrototypes?.['ExpoUI_ModalBottomSheetView'] ?? {}) : null;
|
|
1357
|
+
}),
|
|
1358
|
+
});
|
|
1359
|
+
/**
|
|
1360
|
+
* Whether the build has SwiftUI's toolbar. `@expo/ui` has had it since 57.0.20, and Expo Go has
|
|
1361
|
+
* the version its SDK shipped with. A SwiftUI view under one the build lacks is a crash, so a
|
|
1362
|
+
* sheet there leaves its toolbar out. Overridden in a test.
|
|
1363
|
+
*/
|
|
1364
|
+
static TOOLBAR = new InjectionToken('angular-native.bottomSheetToolbar', {
|
|
1365
|
+
factory: () => {
|
|
1366
|
+
const expo = globalThis.expo;
|
|
1367
|
+
return ['NavigationStackView', 'ToolbarView'].every((view) => optional(() => expo?.getViewConfig?.('ExpoUI', view)) != null);
|
|
1368
|
+
},
|
|
1369
|
+
});
|
|
1370
|
+
functions = inject(UiBottomSheet.SOURCE);
|
|
1371
|
+
toolbarInBuild = inject(UiBottomSheet.TOOLBAR);
|
|
1372
|
+
engine = inject(Engine, { optional: true });
|
|
1373
|
+
injector = inject(Injector);
|
|
1374
|
+
sheet = viewChild('sheet', { ...(ngDevMode ? { debugName: "sheet" } : /* istanbul ignore next */ {}), read: ElementRef });
|
|
1375
|
+
/** Whether the sheet is on screen. Written back as false when the user dismisses it. */
|
|
1376
|
+
open = model(false, /* @ts-ignore */
|
|
1377
|
+
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
1378
|
+
/**
|
|
1379
|
+
* The sheet is as tall as its content. Without it the sheet rests at half the screen's height
|
|
1380
|
+
* and drags up to all of it. Read as the sheet opens. A sheet with a toolbar on iOS is not
|
|
1381
|
+
* sized to its content: it rests at its `detents`, or at half and full height.
|
|
1382
|
+
*/
|
|
1383
|
+
fitToContents = input(false, { ...(ngDevMode ? { debugName: "fitToContents" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1384
|
+
/**
|
|
1385
|
+
* The heights the sheet rests at, iOS only: SwiftUI's `presentationDetents`. Compose's sheet has
|
|
1386
|
+
* a half and a full height and no others, so Android takes no notice of this. On iOS a sheet
|
|
1387
|
+
* given detents rests at them rather than at the height of its content, whatever `fitToContents`
|
|
1388
|
+
* says, as `@expo/ui`'s own sheets do. None, or an empty list, is the sheet without them.
|
|
1389
|
+
*/
|
|
1390
|
+
detents = input(/* @ts-ignore */
|
|
1391
|
+
...(ngDevMode ? [undefined, { debugName: "detents" }] : /* istanbul ignore next */ []));
|
|
1392
|
+
/** Whether the grabber shows at the top of the sheet. */
|
|
1393
|
+
showDragIndicator = input(true, { ...(ngDevMode ? { debugName: "showDragIndicator" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1394
|
+
/**
|
|
1395
|
+
* The sheet has finished closing, whether the user dismissed it or `open` was set false: the
|
|
1396
|
+
* moment another sheet or a dialog can be presented.
|
|
1397
|
+
*/
|
|
1398
|
+
dismissed = output();
|
|
1399
|
+
/** The toolbar items written inside the sheet, which give it a bar to hold them. */
|
|
1400
|
+
toolbarItems = contentChildren(UiToolbarItem, /* @ts-ignore */
|
|
1401
|
+
...(ngDevMode ? [{ debugName: "toolbarItems" }] : /* istanbul ignore next */ []));
|
|
1402
|
+
/** Whether the sheet has a toolbar: it has items for one, and the build has the views. */
|
|
1403
|
+
toolbar = computed(() => this.toolbarInBuild && this.toolbarItems().length > 0, /* @ts-ignore */
|
|
1404
|
+
...(ngDevMode ? [{ debugName: "toolbar" }] : /* istanbul ignore next */ []));
|
|
1405
|
+
/** SwiftUI's sheet stays in the tree; anywhere else it is there while it shows. */
|
|
1406
|
+
swiftUI = nativePlatform() === 'ios';
|
|
1407
|
+
width = windowWidth();
|
|
1408
|
+
/**
|
|
1409
|
+
* Whether the content is in the tree: from when the sheet opens until it has gone, which is
|
|
1410
|
+
* after `open` turns false, so that it slides away with its content still in it.
|
|
1411
|
+
*/
|
|
1412
|
+
mounted = linkedSignal({ ...(ngDevMode ? { debugName: "mounted" } : /* istanbul ignore next */ {}), source: this.open,
|
|
1413
|
+
computation: (open, previous) => open || (previous?.value ?? false) });
|
|
1414
|
+
/**
|
|
1415
|
+
* Whether the sheet is sized to its content, as it opened: a view host takes its sizing once,
|
|
1416
|
+
* as it mounts. SwiftUI's sheet is not where it has detents to rest at, nor where it has a
|
|
1417
|
+
* toolbar: a navigation stack fills what it is given, and the bar is no part of the content.
|
|
1418
|
+
* A toolbar that comes or goes while the sheet is open is followed, since the view host is made
|
|
1419
|
+
* again around it.
|
|
1420
|
+
*/
|
|
1421
|
+
fits = computed(() => {
|
|
1422
|
+
this.mounted();
|
|
1423
|
+
const toolbar = this.toolbar();
|
|
1424
|
+
return untracked(() => this.fitToContents() && !(this.swiftUI && (this.detents()?.length || toolbar)));
|
|
1425
|
+
}, /* @ts-ignore */
|
|
1426
|
+
...(ngDevMode ? [{ debugName: "fits" }] : /* istanbul ignore next */ []));
|
|
1427
|
+
/**
|
|
1428
|
+
* SwiftUI reads how a sheet is presented from modifiers on its content, not from props. The
|
|
1429
|
+
* detents of a sheet not sized to its content are followed while it is open.
|
|
1430
|
+
*/
|
|
1431
|
+
presentation = computed(() => [
|
|
1432
|
+
this.fits()
|
|
1433
|
+
? { $type: 'presentationSizing', sizing: 'fitted' }
|
|
1434
|
+
: {
|
|
1435
|
+
$type: 'presentationDetents',
|
|
1436
|
+
detents: this.detents()?.length ? this.detents() : HALF_AND_FULL,
|
|
1437
|
+
},
|
|
1438
|
+
{
|
|
1439
|
+
$type: 'presentationDragIndicator',
|
|
1440
|
+
visibility: this.showDragIndicator() ? 'visible' : 'hidden',
|
|
1441
|
+
},
|
|
1442
|
+
], /* @ts-ignore */
|
|
1443
|
+
...(ngDevMode ? [{ debugName: "presentation" }] : /* istanbul ignore next */ []));
|
|
1444
|
+
/**
|
|
1445
|
+
* The one view a view host holds. Sized to its content it needs a width of its own, the
|
|
1446
|
+
* window's; otherwise it fills the height the sheet gives it.
|
|
1447
|
+
*/
|
|
1448
|
+
body = computed(() => this.fits() ? { width: this.width() } : { flexGrow: 1, height: 0 }, /* @ts-ignore */
|
|
1449
|
+
...(ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []));
|
|
1450
|
+
/** Whether `open` has turned false on a sheet that has yet to go. */
|
|
1451
|
+
closing = false;
|
|
1452
|
+
/** Whether Compose is sliding the sheet away. */
|
|
1453
|
+
hiding = false;
|
|
1454
|
+
constructor() {
|
|
1455
|
+
effect(() => {
|
|
1456
|
+
if (!this.open())
|
|
1457
|
+
untracked(() => this.close());
|
|
1458
|
+
});
|
|
1459
|
+
if (this.swiftUI && !this.toolbarInBuild) {
|
|
1460
|
+
const warned = effect(() => {
|
|
1461
|
+
if (!this.toolbarItems().length)
|
|
1462
|
+
return;
|
|
1463
|
+
console.warn('[angular-native] A ui-toolbar-item in a ui-bottom-sheet needs @expo/ui 57.0.20 or ' +
|
|
1464
|
+
'later in the native build. This build has no SwiftUI toolbar, as Expo Go may not, ' +
|
|
1465
|
+
'so the sheet is shown without the item.');
|
|
1466
|
+
warned.destroy();
|
|
1467
|
+
}, /* @ts-ignore */
|
|
1468
|
+
...(ngDevMode ? [{ debugName: "warned" }] : /* istanbul ignore next */ []));
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
presented(event) {
|
|
1472
|
+
if (!this.own(event))
|
|
1473
|
+
return;
|
|
1474
|
+
const isPresented = event.nativeEvent?.isPresented;
|
|
1475
|
+
if (typeof isPresented === 'boolean')
|
|
1476
|
+
this.open.set(isPresented);
|
|
1477
|
+
}
|
|
1478
|
+
dismissRequested(event) {
|
|
1479
|
+
if (this.own(event))
|
|
1480
|
+
this.open.set(false);
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* SwiftUI has finished dismissing the sheet. After a swipe it says so before it reports that the
|
|
1484
|
+
* sheet is no longer presented, so a sheet that has gone while `open`, and was not closing, is
|
|
1485
|
+
* one the user dismissed.
|
|
1486
|
+
*/
|
|
1487
|
+
gone(event) {
|
|
1488
|
+
if (!this.own(event))
|
|
1489
|
+
return;
|
|
1490
|
+
if (!this.closing)
|
|
1491
|
+
this.open.set(false);
|
|
1492
|
+
this.finish();
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Whether an event is this sheet's own, which it then stops. Events bubble, so a `dismiss` from
|
|
1496
|
+
* a modal in the content arrives here too, and the sheet's own would go on to a listener around
|
|
1497
|
+
* it.
|
|
1498
|
+
*/
|
|
1499
|
+
own(event) {
|
|
1500
|
+
const target = event.target;
|
|
1501
|
+
if (target != null && target !== this.sheet()?.nativeElement)
|
|
1502
|
+
return false;
|
|
1503
|
+
event.stopPropagation();
|
|
1504
|
+
return true;
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* `open` turned false. SwiftUI dismisses its sheet on the prop, and says when it has gone.
|
|
1508
|
+
* Compose shows a sheet for as long as it is in the tree, so one taken out is gone at once:
|
|
1509
|
+
* its `hide` slides it away first, as `@expo/ui`'s own component calls it before unmounting.
|
|
1510
|
+
*/
|
|
1511
|
+
close() {
|
|
1512
|
+
if (!this.mounted())
|
|
1513
|
+
return;
|
|
1514
|
+
// No `@expo/ui` in the build: no sheet is there to slide away, or to say that it has.
|
|
1515
|
+
if (!this.functions)
|
|
1516
|
+
return this.finish();
|
|
1517
|
+
this.closing = true;
|
|
1518
|
+
if (this.swiftUI || this.hiding)
|
|
1519
|
+
return;
|
|
1520
|
+
const node = this.sheet()?.nativeElement;
|
|
1521
|
+
const nativeTag = node ? (this.engine?.tagOf(node) ?? null) : null;
|
|
1522
|
+
const hidden = nativeTag === null ? undefined : optional(() => this.functions?.hide?.call({ nativeTag }));
|
|
1523
|
+
if (!hidden)
|
|
1524
|
+
return this.finish();
|
|
1525
|
+
this.hiding = true;
|
|
1526
|
+
const done = () => {
|
|
1527
|
+
this.hiding = false;
|
|
1528
|
+
this.finish();
|
|
1529
|
+
};
|
|
1530
|
+
hidden.then(done, done);
|
|
1531
|
+
}
|
|
1532
|
+
/** The sheet has gone: its content leaves the tree. */
|
|
1533
|
+
finish() {
|
|
1534
|
+
this.closing = false;
|
|
1535
|
+
if (!this.mounted())
|
|
1536
|
+
return;
|
|
1537
|
+
if (!this.open()) {
|
|
1538
|
+
this.mounted.set(false);
|
|
1539
|
+
this.dismissed.emit();
|
|
1540
|
+
return;
|
|
1541
|
+
}
|
|
1542
|
+
// Opened again before it had gone. SwiftUI presents the sheet it still has; Compose hid the
|
|
1543
|
+
// one it was asked to, and shows a sheet only as it enters the tree.
|
|
1544
|
+
if (this.swiftUI)
|
|
1545
|
+
return;
|
|
1546
|
+
this.mounted.set(false);
|
|
1547
|
+
afterNextRender(() => this.mounted.set(this.open()), { injector: this.injector });
|
|
1548
|
+
}
|
|
1549
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiBottomSheet, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1550
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.2.0", type: UiBottomSheet, isStandalone: true, selector: "ui-bottom-sheet", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, fitToContents: { classPropertyName: "fitToContents", publicName: "fitToContents", isSignal: true, isRequired: false, transformFunction: null }, detents: { classPropertyName: "detents", publicName: "detents", isSignal: true, isRequired: false, transformFunction: null }, showDragIndicator: { classPropertyName: "showDragIndicator", publicName: "showDragIndicator", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", dismissed: "dismissed" }, host: { properties: { "style.position": "\"absolute\"" } }, queries: [{ propertyName: "toolbarItems", predicate: UiToolbarItem, isSignal: true }], viewQueries: [{ propertyName: "sheet", first: true, predicate: ["sheet"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: `
|
|
1551
|
+
<ng-template #content><ng-content /></ng-template>
|
|
1552
|
+
@if (swiftUI) {
|
|
1553
|
+
<ui-host style="position: absolute" pointerEvents="none" [style.width.px]="width()">
|
|
1554
|
+
<ui-bottom-sheet-view
|
|
1555
|
+
#sheet
|
|
1556
|
+
[isPresented]="open()"
|
|
1557
|
+
[fitToContents]="fits()"
|
|
1558
|
+
(isPresentedChange)="presented($event)"
|
|
1559
|
+
(dismiss)="gone($event)"
|
|
1560
|
+
>
|
|
1561
|
+
@if (mounted()) {
|
|
1562
|
+
<ui-group [modifiers]="presentation()">
|
|
1563
|
+
@if (toolbar()) {
|
|
1564
|
+
<ui-navigation-stack>
|
|
1565
|
+
<ui-toolbar>
|
|
1566
|
+
<ui-view-host layoutRoot [matchContents]="fits() || undefined">
|
|
1567
|
+
<ui-bottom-sheet-content [style]="body()" [content]="content" />
|
|
1568
|
+
</ui-view-host>
|
|
1569
|
+
<ui-slot name="content"><ng-content select="ui-toolbar-item" /></ui-slot>
|
|
1570
|
+
</ui-toolbar>
|
|
1571
|
+
</ui-navigation-stack>
|
|
1572
|
+
} @else {
|
|
1573
|
+
<ui-view-host layoutRoot [matchContents]="fits() || undefined">
|
|
1574
|
+
<ui-bottom-sheet-content [style]="body()" [content]="content" />
|
|
1575
|
+
</ui-view-host>
|
|
1576
|
+
}
|
|
1577
|
+
</ui-group>
|
|
1578
|
+
}
|
|
1579
|
+
</ui-bottom-sheet-view>
|
|
1580
|
+
</ui-host>
|
|
1581
|
+
} @else if (mounted()) {
|
|
1582
|
+
<ui-host style="position: absolute" pointerEvents="none" [style.width.px]="width()">
|
|
1583
|
+
<ui-bottom-sheet-view
|
|
1584
|
+
#sheet
|
|
1585
|
+
[showDragHandle]="showDragIndicator()"
|
|
1586
|
+
[skipPartiallyExpanded]="fits()"
|
|
1587
|
+
(dismissRequest)="dismissRequested($event)"
|
|
1588
|
+
>
|
|
1589
|
+
<ui-view-host layoutRoot [matchContents]="fits() || undefined">
|
|
1590
|
+
<ui-bottom-sheet-content [style]="body()" [content]="content" />
|
|
1591
|
+
</ui-view-host>
|
|
1592
|
+
</ui-bottom-sheet-view>
|
|
1593
|
+
</ui-host>
|
|
1594
|
+
}
|
|
1595
|
+
`, isInline: true, dependencies: [{ kind: "component", type: UiBottomSheetContent, selector: "ui-bottom-sheet-content", inputs: ["content"] }, { kind: "component", type: UiBottomSheetView, selector: "ui-bottom-sheet-view", inputs: ["isPresented", "fitToContents", "showDragHandle", "skipPartiallyExpanded"], outputs: ["isPresentedChange", "dismiss", "dismissRequest"] }, { kind: "component", type: UiGroup, selector: "ui-group", inputs: ["modifiers"] }, { kind: "component", type: UiHost, selector: "ui-host", inputs: ["matchContents", "ignoreSafeArea", "useViewportSizeMeasurement"] }, { kind: "component", type: UiNavigationStack, selector: "ui-navigation-stack", inputs: ["modifiers"] }, { kind: "component", type: UiSlot, selector: "ui-slot", inputs: ["name", "extraProps"] }, { kind: "component", type: UiToolbar, selector: "ui-toolbar", inputs: ["modifiers"] }, { kind: "component", type: UiViewHost, selector: "ui-view-host", inputs: ["matchContents", "layoutRoot", "modifiers"] }] });
|
|
1596
|
+
}
|
|
1597
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiBottomSheet, decorators: [{
|
|
1598
|
+
type: Component,
|
|
1599
|
+
args: [{
|
|
1600
|
+
selector: 'ui-bottom-sheet',
|
|
1601
|
+
imports: [
|
|
1602
|
+
UiBottomSheetContent,
|
|
1603
|
+
UiBottomSheetView,
|
|
1604
|
+
UiGroup,
|
|
1605
|
+
UiHost,
|
|
1606
|
+
UiNavigationStack,
|
|
1607
|
+
UiSlot,
|
|
1608
|
+
UiToolbar,
|
|
1609
|
+
UiViewHost,
|
|
1610
|
+
],
|
|
1611
|
+
template: `
|
|
1612
|
+
<ng-template #content><ng-content /></ng-template>
|
|
1613
|
+
@if (swiftUI) {
|
|
1614
|
+
<ui-host style="position: absolute" pointerEvents="none" [style.width.px]="width()">
|
|
1615
|
+
<ui-bottom-sheet-view
|
|
1616
|
+
#sheet
|
|
1617
|
+
[isPresented]="open()"
|
|
1618
|
+
[fitToContents]="fits()"
|
|
1619
|
+
(isPresentedChange)="presented($event)"
|
|
1620
|
+
(dismiss)="gone($event)"
|
|
1621
|
+
>
|
|
1622
|
+
@if (mounted()) {
|
|
1623
|
+
<ui-group [modifiers]="presentation()">
|
|
1624
|
+
@if (toolbar()) {
|
|
1625
|
+
<ui-navigation-stack>
|
|
1626
|
+
<ui-toolbar>
|
|
1627
|
+
<ui-view-host layoutRoot [matchContents]="fits() || undefined">
|
|
1628
|
+
<ui-bottom-sheet-content [style]="body()" [content]="content" />
|
|
1629
|
+
</ui-view-host>
|
|
1630
|
+
<ui-slot name="content"><ng-content select="ui-toolbar-item" /></ui-slot>
|
|
1631
|
+
</ui-toolbar>
|
|
1632
|
+
</ui-navigation-stack>
|
|
1633
|
+
} @else {
|
|
1634
|
+
<ui-view-host layoutRoot [matchContents]="fits() || undefined">
|
|
1635
|
+
<ui-bottom-sheet-content [style]="body()" [content]="content" />
|
|
1636
|
+
</ui-view-host>
|
|
1637
|
+
}
|
|
1638
|
+
</ui-group>
|
|
1639
|
+
}
|
|
1640
|
+
</ui-bottom-sheet-view>
|
|
1641
|
+
</ui-host>
|
|
1642
|
+
} @else if (mounted()) {
|
|
1643
|
+
<ui-host style="position: absolute" pointerEvents="none" [style.width.px]="width()">
|
|
1644
|
+
<ui-bottom-sheet-view
|
|
1645
|
+
#sheet
|
|
1646
|
+
[showDragHandle]="showDragIndicator()"
|
|
1647
|
+
[skipPartiallyExpanded]="fits()"
|
|
1648
|
+
(dismissRequest)="dismissRequested($event)"
|
|
1649
|
+
>
|
|
1650
|
+
<ui-view-host layoutRoot [matchContents]="fits() || undefined">
|
|
1651
|
+
<ui-bottom-sheet-content [style]="body()" [content]="content" />
|
|
1652
|
+
</ui-view-host>
|
|
1653
|
+
</ui-bottom-sheet-view>
|
|
1654
|
+
</ui-host>
|
|
1655
|
+
}
|
|
1656
|
+
`,
|
|
1657
|
+
host: { '[style.position]': '"absolute"' },
|
|
1658
|
+
}]
|
|
1659
|
+
}], ctorParameters: () => [], propDecorators: { sheet: [{ type: i0.ViewChild, args: ['sheet', { ...{
|
|
1660
|
+
read: ElementRef,
|
|
1661
|
+
}, isSignal: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], fitToContents: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitToContents", required: false }] }], detents: [{ type: i0.Input, args: [{ isSignal: true, alias: "detents", required: false }] }], showDragIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDragIndicator", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], toolbarItems: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => UiToolbarItem), { isSignal: true }] }] } });
|
|
1197
1662
|
//# sourceMappingURL=expo-ui-components.js.map
|