@ng-native/expo 0.6.0 → 0.8.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 +82 -6
- package/dist/expo-ui-components.js +172 -16
- package/dist/expo-ui-components.js.map +1 -1
- package/dist/expo-ui.js +4 -0
- package/dist/expo-ui.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/permissions.d.ts +23 -3
- package/dist/permissions.js +63 -7
- package/dist/permissions.js.map +1 -1
- package/package.json +2 -2
|
@@ -103,7 +103,8 @@ export declare class UiContextMenu {
|
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
105
|
* A SwiftUI `Button`, as a menu item or on its own, or Compose's on Android, which draws `label` as
|
|
106
|
-
* text inside it. `systemImage` and `role` are SwiftUI's alone.
|
|
106
|
+
* text inside it. `systemImage` and `role` are SwiftUI's alone. A `close` button with no label and
|
|
107
|
+
* no content is the system's own close button, from iOS 26.
|
|
107
108
|
*/
|
|
108
109
|
export declare class UiButton {
|
|
109
110
|
protected readonly nativeView: true;
|
|
@@ -111,7 +112,7 @@ export declare class UiButton {
|
|
|
111
112
|
readonly label: import("@angular/core").InputSignal<string | undefined>;
|
|
112
113
|
/** An SF Symbol name. */
|
|
113
114
|
readonly systemImage: import("@angular/core").InputSignal<string | undefined>;
|
|
114
|
-
readonly role: import("@angular/core").InputSignal<"default" | "cancel" | "destructive" | undefined>;
|
|
115
|
+
readonly role: import("@angular/core").InputSignal<"default" | "cancel" | "destructive" | "close" | undefined>;
|
|
115
116
|
/**
|
|
116
117
|
* In a home-screen widget's layout, what a tap on it records for the app: see
|
|
117
118
|
* `@ng-native/expo/widget`.
|
|
@@ -642,6 +643,50 @@ export declare class UiGroup {
|
|
|
642
643
|
static ɵfac: i0.ɵɵFactoryDeclaration<UiGroup, never>;
|
|
643
644
|
static ɵcmp: i0.ɵɵComponentDeclaration<UiGroup, "ui-group", never, { "modifiers": { "alias": "modifiers"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
644
645
|
}
|
|
646
|
+
/**
|
|
647
|
+
* A SwiftUI `NavigationStack`, iOS only: the bar a `ui-toolbar` inside it puts its items in, and
|
|
648
|
+
* that a `navigationTitle` modifier on its content titles.
|
|
649
|
+
*/
|
|
650
|
+
export declare class UiNavigationStack {
|
|
651
|
+
protected readonly nativeView: true;
|
|
652
|
+
readonly modifiers: import("@angular/core").InputSignal<readonly UiModifier[] | undefined>;
|
|
653
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UiNavigationStack, never>;
|
|
654
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<UiNavigationStack, "ui-navigation-stack", never, { "modifiers": { "alias": "modifiers"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* SwiftUI's `toolbar`, iOS only. Its children are the view the toolbar belongs to, and its items go
|
|
658
|
+
* in `<ui-slot name="content">`, each a `ui-toolbar-item`. It shows in the bar of the
|
|
659
|
+
* `ui-navigation-stack` around it.
|
|
660
|
+
*/
|
|
661
|
+
export declare class UiToolbar {
|
|
662
|
+
protected readonly nativeView: true;
|
|
663
|
+
readonly modifiers: import("@angular/core").InputSignal<readonly UiModifier[] | undefined>;
|
|
664
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UiToolbar, never>;
|
|
665
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<UiToolbar, "ui-toolbar", never, { "modifiers": { "alias": "modifiers"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
666
|
+
}
|
|
667
|
+
/** Where a `ui-toolbar-item` sits, as SwiftUI's `ToolbarItemPlacement` names them. */
|
|
668
|
+
export type UiToolbarItemPlacement = 'automatic' | 'principal' | 'navigation' | 'primaryAction' | 'secondaryAction' | 'status' | 'confirmationAction' | 'cancellationAction' | 'destructiveAction' | 'keyboard' | 'topBarLeading' | 'topBarTrailing' | 'topBarPinnedTrailing' | 'largeTitle' | 'bottomBar';
|
|
669
|
+
/**
|
|
670
|
+
* One item of a `ui-toolbar`, SwiftUI's `ToolbarItem`: a `ui-button`, or a `ui-text` as a title
|
|
671
|
+
* with `placement="principal"`. Unplaced, SwiftUI places it. A placement the OS does not have is
|
|
672
|
+
* read as `automatic`.
|
|
673
|
+
*
|
|
674
|
+
* Written inside a `ui-bottom-sheet` it goes in the sheet's own toolbar, which is how a sheet
|
|
675
|
+
* shows the system's close button.
|
|
676
|
+
*/
|
|
677
|
+
export declare class UiToolbarItem {
|
|
678
|
+
protected readonly nativeView: true;
|
|
679
|
+
readonly placement: import("@angular/core").InputSignal<UiToolbarItemPlacement | undefined>;
|
|
680
|
+
/** How readily the item gives up its place when the bar runs out of room, from iOS 27. */
|
|
681
|
+
readonly visibilityPriority: import("@angular/core").InputSignal<"low" | "high" | "automatic" | undefined>;
|
|
682
|
+
/** What the slot tells the toolbar about itself: only what is set, so SwiftUI decides the rest. */
|
|
683
|
+
protected readonly extraProps: Signal<{
|
|
684
|
+
visibilityPriority?: "low" | "high" | "automatic" | undefined;
|
|
685
|
+
placement?: UiToolbarItemPlacement | undefined;
|
|
686
|
+
} | undefined>;
|
|
687
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UiToolbarItem, never>;
|
|
688
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<UiToolbarItem, "ui-toolbar-item", never, { "placement": { "alias": "placement"; "required": false; "isSignal": true; }; "visibilityPriority": { "alias": "visibilityPriority"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
689
|
+
}
|
|
645
690
|
/**
|
|
646
691
|
* A height a SwiftUI sheet rests at, as `@expo/ui`'s `PresentationDetent`: about half the screen,
|
|
647
692
|
* all of it, a fraction of it from 0 to 1, or a height in points.
|
|
@@ -671,6 +716,21 @@ export interface UiBottomSheetViewFunctions {
|
|
|
671
716
|
* `open` presents and dismisses it, and is written back when the user dismisses it. Its content is
|
|
672
717
|
* what is written inside it, the app's own components, in the tree while the sheet is on screen.
|
|
673
718
|
*
|
|
719
|
+
* A `ui-toolbar-item` written inside it is not content: on iOS it goes in a toolbar of the sheet's
|
|
720
|
+
* own, in a bar across its top, which is where the system's close button belongs.
|
|
721
|
+
*
|
|
722
|
+
* ```html
|
|
723
|
+
* <ui-bottom-sheet [(open)]="sorting">
|
|
724
|
+
* <ui-toolbar-item placement="cancellationAction">
|
|
725
|
+
* <ui-button role="close" (buttonPress)="sorting.set(false)" />
|
|
726
|
+
* </ui-toolbar-item>
|
|
727
|
+
* <app-sort-options />
|
|
728
|
+
* </ui-bottom-sheet>
|
|
729
|
+
* ```
|
|
730
|
+
*
|
|
731
|
+
* Compose's sheet has no toolbar, so Android draws no item. Nor does an iOS build whose `@expo/ui`
|
|
732
|
+
* is older than 57.0.20, which Expo Go's can be: it warns, and shows the sheet without one.
|
|
733
|
+
*
|
|
674
734
|
* The two platforms drive a sheet differently, and this is where that difference ends. SwiftUI's
|
|
675
735
|
* stays in the tree and is presented by `isPresented`, reporting `isPresentedChange` and
|
|
676
736
|
* `dismiss`. Compose's shows for as long as it is in the tree, and reports `dismissRequest`.
|
|
@@ -678,7 +738,8 @@ export interface UiBottomSheetViewFunctions {
|
|
|
678
738
|
* Unlike the other components here, the element this is mounted on is a plain view, which takes
|
|
679
739
|
* no room and needs no `ui-host` around it. The sheet is inside it, wrapped as `@expo/ui`'s own
|
|
680
740
|
* React component wraps one: a `ui-host`, the sheet, on iOS a `ui-group` that carries the
|
|
681
|
-
* presentation modifiers, and a `ui-view-host` holding the one view the content goes in.
|
|
741
|
+
* presentation modifiers, and a `ui-view-host` holding the one view the content goes in. With
|
|
742
|
+
* toolbar items, the view host is in a `ui-toolbar` in a `ui-navigation-stack`, under the group.
|
|
682
743
|
*/
|
|
683
744
|
export declare class UiBottomSheet {
|
|
684
745
|
/**
|
|
@@ -686,7 +747,14 @@ export declare class UiBottomSheet {
|
|
|
686
747
|
* build and there is no sheet. Overridden in a test to hide a sheet without a device.
|
|
687
748
|
*/
|
|
688
749
|
static readonly SOURCE: InjectionToken<UiBottomSheetViewFunctions | null>;
|
|
750
|
+
/**
|
|
751
|
+
* Whether the build has SwiftUI's toolbar. `@expo/ui` has had it since 57.0.20, and Expo Go has
|
|
752
|
+
* the version its SDK shipped with. A SwiftUI view under one the build lacks is a crash, so a
|
|
753
|
+
* sheet there leaves its toolbar out. Overridden in a test.
|
|
754
|
+
*/
|
|
755
|
+
static readonly TOOLBAR: InjectionToken<boolean>;
|
|
689
756
|
private readonly functions;
|
|
757
|
+
private readonly toolbarInBuild;
|
|
690
758
|
private readonly engine;
|
|
691
759
|
private readonly injector;
|
|
692
760
|
private readonly sheet;
|
|
@@ -694,7 +762,8 @@ export declare class UiBottomSheet {
|
|
|
694
762
|
readonly open: import("@angular/core").ModelSignal<boolean>;
|
|
695
763
|
/**
|
|
696
764
|
* The sheet is as tall as its content. Without it the sheet rests at half the screen's height
|
|
697
|
-
* and drags up to all of it. Read as the sheet opens.
|
|
765
|
+
* and drags up to all of it. Read as the sheet opens. A sheet with a toolbar on iOS is not
|
|
766
|
+
* sized to its content: it rests at its `detents`, or at half and full height.
|
|
698
767
|
*/
|
|
699
768
|
readonly fitToContents: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
700
769
|
/**
|
|
@@ -711,6 +780,10 @@ export declare class UiBottomSheet {
|
|
|
711
780
|
* moment another sheet or a dialog can be presented.
|
|
712
781
|
*/
|
|
713
782
|
readonly dismissed: import("@angular/core").OutputEmitterRef<void>;
|
|
783
|
+
/** The toolbar items written inside the sheet, which give it a bar to hold them. */
|
|
784
|
+
private readonly toolbarItems;
|
|
785
|
+
/** Whether the sheet has a toolbar: it has items for one, and the build has the views. */
|
|
786
|
+
protected readonly toolbar: Signal<boolean>;
|
|
714
787
|
/** SwiftUI's sheet stays in the tree; anywhere else it is there while it shows. */
|
|
715
788
|
protected readonly swiftUI: boolean;
|
|
716
789
|
protected readonly width: Signal<number | undefined>;
|
|
@@ -721,7 +794,10 @@ export declare class UiBottomSheet {
|
|
|
721
794
|
protected readonly mounted: import("@angular/core").WritableSignal<boolean>;
|
|
722
795
|
/**
|
|
723
796
|
* Whether the sheet is sized to its content, as it opened: a view host takes its sizing once,
|
|
724
|
-
* as it mounts. SwiftUI's sheet is not where it has detents to rest at
|
|
797
|
+
* as it mounts. SwiftUI's sheet is not where it has detents to rest at, nor where it has a
|
|
798
|
+
* toolbar: a navigation stack fills what it is given, and the bar is no part of the content.
|
|
799
|
+
* A toolbar that comes or goes while the sheet is open is followed, since the view host is made
|
|
800
|
+
* again around it.
|
|
725
801
|
*/
|
|
726
802
|
protected readonly fits: Signal<boolean>;
|
|
727
803
|
/**
|
|
@@ -770,6 +846,6 @@ export declare class UiBottomSheet {
|
|
|
770
846
|
/** The sheet has gone: its content leaves the tree. */
|
|
771
847
|
private finish;
|
|
772
848
|
static ɵfac: i0.ɵɵFactoryDeclaration<UiBottomSheet, never>;
|
|
773
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<UiBottomSheet, "ui-bottom-sheet", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "fitToContents": { "alias": "fitToContents"; "required": false; "isSignal": true; }; "detents": { "alias": "detents"; "required": false; "isSignal": true; }; "showDragIndicator": { "alias": "showDragIndicator"; "required": false; "isSignal": true; }; }, { "open": "openChange"; "dismissed": "dismissed"; },
|
|
849
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<UiBottomSheet, "ui-bottom-sheet", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "fitToContents": { "alias": "fitToContents"; "required": false; "isSignal": true; }; "detents": { "alias": "detents"; "required": false; "isSignal": true; }; "showDragIndicator": { "alias": "showDragIndicator"; "required": false; "isSignal": true; }; }, { "open": "openChange"; "dismissed": "dismissed"; }, ["toolbarItems"], ["*", "ui-toolbar-item"], true, never>;
|
|
774
850
|
}
|
|
775
851
|
export {};
|
|
@@ -23,7 +23,7 @@
|
|
|
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, InjectionToken, Injector, afterNextRender, booleanAttribute, computed, effect, inject, input, linkedSignal, model, output, signal, untracked, viewChild, } from '@angular/core';
|
|
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
27
|
import { Engine, HostEngine, keepNativeView, nativePlatform, } from '@ng-native/fabric';
|
|
28
28
|
import { optional } from "./native.js";
|
|
29
29
|
import { optionalBoolean, optionalNumber } from "./transforms.js";
|
|
@@ -168,7 +168,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
168
168
|
}], propDecorators: { modifiers: [{ type: i0.Input, args: [{ isSignal: true, alias: "modifiers", required: false }] }] } });
|
|
169
169
|
/**
|
|
170
170
|
* A SwiftUI `Button`, as a menu item or on its own, or Compose's on Android, which draws `label` as
|
|
171
|
-
* 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.
|
|
172
173
|
*/
|
|
173
174
|
export class UiButton {
|
|
174
175
|
nativeView = nativeView();
|
|
@@ -1217,6 +1218,80 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
1217
1218
|
host: { '[modifiers]': 'modifiers()' },
|
|
1218
1219
|
}]
|
|
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 }] }] } });
|
|
1220
1295
|
/** The detents of a sheet given none and not sized to its content. */
|
|
1221
1296
|
const HALF_AND_FULL = ['medium', 'large'];
|
|
1222
1297
|
/** The window's width as the engine knows it, or undefined before the platform has said. */
|
|
@@ -1244,6 +1319,21 @@ function windowWidth() {
|
|
|
1244
1319
|
* `open` presents and dismisses it, and is written back when the user dismisses it. Its content is
|
|
1245
1320
|
* what is written inside it, the app's own components, in the tree while the sheet is on screen.
|
|
1246
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
|
+
*
|
|
1247
1337
|
* The two platforms drive a sheet differently, and this is where that difference ends. SwiftUI's
|
|
1248
1338
|
* stays in the tree and is presented by `isPresented`, reporting `isPresentedChange` and
|
|
1249
1339
|
* `dismiss`. Compose's shows for as long as it is in the tree, and reports `dismissRequest`.
|
|
@@ -1251,7 +1341,8 @@ function windowWidth() {
|
|
|
1251
1341
|
* Unlike the other components here, the element this is mounted on is a plain view, which takes
|
|
1252
1342
|
* no room and needs no `ui-host` around it. The sheet is inside it, wrapped as `@expo/ui`'s own
|
|
1253
1343
|
* React component wraps one: a `ui-host`, the sheet, on iOS a `ui-group` that carries the
|
|
1254
|
-
* presentation modifiers, and a `ui-view-host` holding the one view the content goes in.
|
|
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.
|
|
1255
1346
|
*/
|
|
1256
1347
|
export class UiBottomSheet {
|
|
1257
1348
|
/**
|
|
@@ -1265,7 +1356,19 @@ export class UiBottomSheet {
|
|
|
1265
1356
|
return module ? (module.ViewPrototypes?.['ExpoUI_ModalBottomSheetView'] ?? {}) : null;
|
|
1266
1357
|
}),
|
|
1267
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
|
+
});
|
|
1268
1370
|
functions = inject(UiBottomSheet.SOURCE);
|
|
1371
|
+
toolbarInBuild = inject(UiBottomSheet.TOOLBAR);
|
|
1269
1372
|
engine = inject(Engine, { optional: true });
|
|
1270
1373
|
injector = inject(Injector);
|
|
1271
1374
|
sheet = viewChild('sheet', { ...(ngDevMode ? { debugName: "sheet" } : /* istanbul ignore next */ {}), read: ElementRef });
|
|
@@ -1274,7 +1377,8 @@ export class UiBottomSheet {
|
|
|
1274
1377
|
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
1275
1378
|
/**
|
|
1276
1379
|
* The sheet is as tall as its content. Without it the sheet rests at half the screen's height
|
|
1277
|
-
* and drags up to all of it. Read as the sheet opens.
|
|
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.
|
|
1278
1382
|
*/
|
|
1279
1383
|
fitToContents = input(false, { ...(ngDevMode ? { debugName: "fitToContents" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1280
1384
|
/**
|
|
@@ -1292,6 +1396,12 @@ export class UiBottomSheet {
|
|
|
1292
1396
|
* moment another sheet or a dialog can be presented.
|
|
1293
1397
|
*/
|
|
1294
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 */ []));
|
|
1295
1405
|
/** SwiftUI's sheet stays in the tree; anywhere else it is there while it shows. */
|
|
1296
1406
|
swiftUI = nativePlatform() === 'ios';
|
|
1297
1407
|
width = windowWidth();
|
|
@@ -1303,11 +1413,15 @@ export class UiBottomSheet {
|
|
|
1303
1413
|
computation: (open, previous) => open || (previous?.value ?? false) });
|
|
1304
1414
|
/**
|
|
1305
1415
|
* Whether the sheet is sized to its content, as it opened: a view host takes its sizing once,
|
|
1306
|
-
* as it mounts. SwiftUI's sheet is not where it has detents to rest at
|
|
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.
|
|
1307
1420
|
*/
|
|
1308
1421
|
fits = computed(() => {
|
|
1309
1422
|
this.mounted();
|
|
1310
|
-
|
|
1423
|
+
const toolbar = this.toolbar();
|
|
1424
|
+
return untracked(() => this.fitToContents() && !(this.swiftUI && (this.detents()?.length || toolbar)));
|
|
1311
1425
|
}, /* @ts-ignore */
|
|
1312
1426
|
...(ngDevMode ? [{ debugName: "fits" }] : /* istanbul ignore next */ []));
|
|
1313
1427
|
/**
|
|
@@ -1342,6 +1456,17 @@ export class UiBottomSheet {
|
|
|
1342
1456
|
if (!this.open())
|
|
1343
1457
|
untracked(() => this.close());
|
|
1344
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
|
+
}
|
|
1345
1470
|
}
|
|
1346
1471
|
presented(event) {
|
|
1347
1472
|
if (!this.own(event))
|
|
@@ -1422,7 +1547,7 @@ export class UiBottomSheet {
|
|
|
1422
1547
|
afterNextRender(() => this.mounted.set(this.open()), { injector: this.injector });
|
|
1423
1548
|
}
|
|
1424
1549
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiBottomSheet, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1425
|
-
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\"" } }, viewQueries: [{ propertyName: "sheet", first: true, predicate: ["sheet"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: `
|
|
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: `
|
|
1426
1551
|
<ng-template #content><ng-content /></ng-template>
|
|
1427
1552
|
@if (swiftUI) {
|
|
1428
1553
|
<ui-host style="position: absolute" pointerEvents="none" [style.width.px]="width()">
|
|
@@ -1435,9 +1560,20 @@ export class UiBottomSheet {
|
|
|
1435
1560
|
>
|
|
1436
1561
|
@if (mounted()) {
|
|
1437
1562
|
<ui-group [modifiers]="presentation()">
|
|
1438
|
-
|
|
1439
|
-
<ui-
|
|
1440
|
-
|
|
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
|
+
}
|
|
1441
1577
|
</ui-group>
|
|
1442
1578
|
}
|
|
1443
1579
|
</ui-bottom-sheet-view>
|
|
@@ -1456,13 +1592,22 @@ export class UiBottomSheet {
|
|
|
1456
1592
|
</ui-bottom-sheet-view>
|
|
1457
1593
|
</ui-host>
|
|
1458
1594
|
}
|
|
1459
|
-
`, 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: UiViewHost, selector: "ui-view-host", inputs: ["matchContents", "layoutRoot", "modifiers"] }] });
|
|
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"] }] });
|
|
1460
1596
|
}
|
|
1461
1597
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiBottomSheet, decorators: [{
|
|
1462
1598
|
type: Component,
|
|
1463
1599
|
args: [{
|
|
1464
1600
|
selector: 'ui-bottom-sheet',
|
|
1465
|
-
imports: [
|
|
1601
|
+
imports: [
|
|
1602
|
+
UiBottomSheetContent,
|
|
1603
|
+
UiBottomSheetView,
|
|
1604
|
+
UiGroup,
|
|
1605
|
+
UiHost,
|
|
1606
|
+
UiNavigationStack,
|
|
1607
|
+
UiSlot,
|
|
1608
|
+
UiToolbar,
|
|
1609
|
+
UiViewHost,
|
|
1610
|
+
],
|
|
1466
1611
|
template: `
|
|
1467
1612
|
<ng-template #content><ng-content /></ng-template>
|
|
1468
1613
|
@if (swiftUI) {
|
|
@@ -1476,9 +1621,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
1476
1621
|
>
|
|
1477
1622
|
@if (mounted()) {
|
|
1478
1623
|
<ui-group [modifiers]="presentation()">
|
|
1479
|
-
|
|
1480
|
-
<ui-
|
|
1481
|
-
|
|
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
|
+
}
|
|
1482
1638
|
</ui-group>
|
|
1483
1639
|
}
|
|
1484
1640
|
</ui-bottom-sheet-view>
|
|
@@ -1502,5 +1658,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
1502
1658
|
}]
|
|
1503
1659
|
}], ctorParameters: () => [], propDecorators: { sheet: [{ type: i0.ViewChild, args: ['sheet', { ...{
|
|
1504
1660
|
read: ElementRef,
|
|
1505
|
-
}, 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"] }] } });
|
|
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 }] }] } });
|
|
1506
1662
|
//# sourceMappingURL=expo-ui-components.js.map
|