@ng-native/expo 0.17.1 → 0.18.1
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/android/src/main/java/dev/ngnative/expo/KeyboardModule.kt +10 -1
- package/dist/audio.d.ts +37 -0
- package/dist/audio.js +90 -6
- package/dist/audio.js.map +1 -1
- package/dist/brightness.js +50 -9
- package/dist/brightness.js.map +1 -1
- package/dist/expo-ui-components.d.ts +45 -2
- package/dist/expo-ui-components.js +96 -5
- package/dist/expo-ui-components.js.map +1 -1
- package/dist/foldable.d.ts +36 -3
- package/dist/foldable.js +66 -13
- package/dist/foldable.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keep-awake.js +2 -2
- package/dist/keep-awake.js.map +1 -1
- package/dist/keyboard.js +15 -0
- package/dist/keyboard.js.map +1 -1
- package/dist/orientation.js +4 -3
- package/dist/orientation.js.map +1 -1
- package/dist/screen-capture.js +2 -2
- package/dist/screen-capture.js.map +1 -1
- package/dist/search-field.js +1 -1
- package/dist/search-field.js.map +1 -1
- package/dist/symbol.d.ts +3 -1
- package/dist/symbol.js +26 -7
- package/dist/symbol.js.map +1 -1
- package/dist/ui-bottom-sheet-view.d.ts +10 -1
- package/dist/ui-bottom-sheet-view.js +10 -2
- package/dist/ui-bottom-sheet-view.js.map +1 -1
- package/expo-module.config.json +6 -1
- package/ios/SymbolImageSize.swift +53 -0
- package/package.json +42 -38
package/dist/search-field.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-field.js","sourceRoot":"","sources":["../src/search-field.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `<search-field>`: the platform's own search field, anywhere a view can go. `<native-search-bar>`\n * from `@ng-native/router` is the one in a navigation bar; this is the one for everywhere else, a\n * filter sheet, a page, a list's header:\n *\n * ```html\n * <ui-bottom-sheet [(open)]=\"filtering\">\n * <search-field placeholder=\"Search colours\" [(value)]=\"query\" />\n * ...\n * </ui-bottom-sheet>\n * ```\n *\n * It is `@ng-native/expo`'s own native view: UIKit's `UISearchBar` on iOS, with its Cancel button,\n * dictation and clear button, and AndroidX's `SearchView` on Android, which has no Cancel button.\n * The events are `<native-search-bar>`'s: `(search)` for the keyboard's search key with the text,\n * `(cancel)`, `(searchFocus)` and `(searchBlur)`, and `focus()`, `blur()` and `clear()` from code.\n * The text is a two-way `value` rather than the bar's `query`, because it is a Signal Forms control\n * as `<text-input>` is: `[formField]` binds `value`, `disabled`, and `touch` on blur.\n * Its type is the `font-family`, `font-size`, `font-weight` and `font-style` its CSS resolves to,\n * as a `<text>`'s is.\n *\n * Expo Go cannot load native code of its own, so there the element draws nothing, and in\n * development it says so once.\n */\nimport {\n Component,\n booleanAttribute,\n DestroyRef,\n ElementRef,\n InjectionToken,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport {\n Engine,\n type EngineNode,\n HostEngine,\n type NativeSyntheticEvent,\n nativePlatform,\n type PostScriptNames,\n registerViewName,\n} from '@ng-native/fabric';\nimport { optional } from './native.ts';\nimport { expoViewName } from './register-expo-view.ts';\nimport { optionalBoolean } from './transforms.ts';\n\n/** The functions the native module defines on the view, called with the view's tag as `this`. */\nexport interface SearchFieldFunctions {\n focus?(this: { nativeTag: number }): Promise<void>;\n blur?(this: { nativeTag: number }): Promise<void>;\n}\n\ndeclare const ngDevMode: unknown;\n\nconst MODULE = 'NgNativeSearchField';\n\nlet warned = false;\n\n/** Says once, in development, that the build has no native search field to draw. */\nfunction warnMissing(): void {\n if ((typeof ngDevMode !== 'undefined' && !ngDevMode) || warned) return;\n warned = true;\n console.warn(\n '[angular-native] <search-field> is native code of @ng-native/expo, which this build does not ' +\n 'have, so it draws nothing. Expo Go cannot load it: run a development build.',\n );\n}\n\n/**\n * The field's face by the PostScript name UIKit finds it by: expo-font registers it under the name\n * the app gives it, which `UIFont(name:)` does not know. Android's font manager finds that name.\n */\nfunction fieldFontName(props: Record<string, unknown>, postScriptName: PostScriptNames): void {\n const family = props['fontFamily'];\n if (typeof family === 'string') props['fontFamily'] = postScriptName(family) ?? family;\n}\n\n@Component({\n selector: 'search-field',\n template: '',\n styles: ':host { height: 56px; }',\n host: {\n '[text]': 'value()',\n '[enabled]': '!disabled()',\n '[mostRecentEventCount]': 'eventCount()',\n '[placeholder]': 'placeholder()',\n '[showsCancelButton]': 'showsCancelButton()',\n '[autoCapitalize]': 'autoCapitalize()',\n '[tintColor]': 'tintColor()',\n // Fabric draws a view the build does not have as a placeholder box naming it.\n '[style.display]': 'missing ? \"none\" : undefined',\n },\n})\nexport class SearchField {\n /**\n * The functions native defines on the view, or null where the build has no native search\n * field. Overridden in a test.\n */\n static readonly SOURCE = new InjectionToken<SearchFieldFunctions | null>(\n 'angular-native.searchFieldSource',\n {\n factory: () =>\n optional(() => {\n const core = require('expo-modules-core') as typeof import('expo-modules-core');\n const module = core.requireOptionalNativeModule<{\n ViewPrototypes?: Record<string, SearchFieldFunctions>;\n }>(MODULE);\n return module ? (module.ViewPrototypes?.[MODULE] ?? {}) : null;\n }),\n },\n );\n\n /**\n * The text in the field: typing writes it, and text set from code is put in the field. A\n * `model()`, which is all `FormValueControl<string>` asks, so `[formField]` binds it.\n */\n readonly value = model('');\n /** Refuse input and show the field dimmed. Signal Forms' `disabled()` rule sets it. */\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly placeholder = input<string>();\n /**\n * iOS: whether the Cancel button shows. Left unset it shows while the field has the keyboard,\n * as in a search bar under a navigation bar.\n */\n readonly showsCancelButton = input(undefined, { transform: optionalBoolean });\n readonly autoCapitalize = input<'none' | 'words' | 'sentences' | 'characters'>();\n /** The colour of the cursor and the Cancel button. */\n readonly tintColor = input<string>();\n\n /** The keyboard's search key was pressed, with the text in the field. */\n readonly search = output<string>();\n /** iOS: the Cancel button was pressed. The field is emptied and gives up the keyboard. */\n readonly cancel = output<void>();\n readonly searchFocus = output<void>();\n readonly searchBlur = output<void>();\n /** The field gave up the keyboard: what Signal Forms marks a field touched from. */\n readonly touch = output<void>();\n\n /**\n * The keystroke the text answers, as React Native's text input counts them: native skips a text\n * older than what has been typed since, which a fast typist's echo otherwise overwrites.\n */\n protected readonly eventCount = signal(0);\n\n private readonly functions = inject(SearchField.SOURCE);\n protected readonly missing = !this.functions;\n private readonly node = inject(ElementRef).nativeElement as EngineNode;\n private readonly engine = inject(Engine, { optional: true });\n\n constructor() {\n registerViewName('search-field', expoViewName(MODULE), undefined, {\n fontNames: nativePlatform() === 'ios' ? fieldFontName : undefined,\n });\n if (this.missing) warnMissing();\n const host =\n (this.node as { host?: Pick<Engine, 'setEventListener'> }).host ?? inject(HostEngine);\n const listen = (event: string, handle: (payload: Record<string, unknown>) => void) =>\n host.setEventListener(this.node, event, (raw) =>\n handle((raw as NativeSyntheticEvent<Record<string, unknown>>)?.nativeEvent ?? {}),\n );\n const stops = [\n listen('topChangeText', ({ text, eventCount }) => {\n if (typeof eventCount === 'number') this.eventCount.set(eventCount);\n this.value.set(String(text ?? ''));\n }),\n // Named apart from the outputs: a native event of an output's name reaches its listener too.\n listen('topSubmitSearch', ({ text }) => this.search.emit(String(text ?? this.value()))),\n listen('topPressCancel', () => this.cancel.emit()),\n listen('topBeginEditing', () => this.searchFocus.emit()),\n listen('topEndEditing', () => {\n this.searchBlur.emit();\n this.touch.emit();\n }),\n ];\n inject(DestroyRef).onDestroy(() => stops.forEach((stop) => stop()));\n }\n\n /** Give the field the keyboard. Does nothing before the view has reached the screen. */\n async focus(): Promise<void> {\n await this.call('focus');\n }\n\n /** Take the keyboard away from the field. */\n async blur(): Promise<void> {\n await this.call('blur');\n }\n\n /** Empty the field, and the value with it. */\n clear(): void {\n this.value.set('');\n }\n\n private async call(name: 'focus' | 'blur'): Promise<void> {\n const nativeTag = this.engine?.tagOf(this.node);\n if (nativeTag == null) return;\n await this.functions?.[name]?.call({ nativeTag });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search-field.js","sourceRoot":"","sources":["../src/search-field.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `<search-field>`: the platform's own search field, anywhere a view can go. `<native-search-bar>`\n * from `@ng-native/router` is the one in a navigation bar; this is the one for everywhere else, a\n * filter sheet, a page, a list's header:\n *\n * ```html\n * <ui-bottom-sheet [(open)]=\"filtering\">\n * <search-field placeholder=\"Search colours\" [(value)]=\"query\" />\n * ...\n * </ui-bottom-sheet>\n * ```\n *\n * It is `@ng-native/expo`'s own native view: UIKit's `UISearchBar` on iOS, with its Cancel button,\n * dictation and clear button, and AndroidX's `SearchView` on Android, which has no Cancel button.\n * The events are `<native-search-bar>`'s: `(search)` for the keyboard's search key with the text,\n * `(cancel)`, `(searchFocus)` and `(searchBlur)`, and `focus()`, `blur()` and `clear()` from code.\n * The text is a two-way `value` rather than the bar's `query`, because it is a Signal Forms control\n * as `<text-input>` is: `[formField]` binds `value`, `disabled`, and `touch` on blur.\n * Its type is the `font-family`, `font-size`, `font-weight` and `font-style` its CSS resolves to,\n * as a `<text>`'s is.\n *\n * Expo Go cannot load native code of its own, so there the element draws nothing, and in\n * development it says so once.\n */\nimport {\n Component,\n booleanAttribute,\n DestroyRef,\n ElementRef,\n InjectionToken,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport {\n Engine,\n type EngineNode,\n HostEngine,\n type NativeSyntheticEvent,\n nativePlatform,\n type PostScriptNames,\n registerViewName,\n} from '@ng-native/fabric';\nimport { optional } from './native.ts';\nimport { expoViewName } from './register-expo-view.ts';\nimport { optionalBoolean } from './transforms.ts';\n\n/** The functions the native module defines on the view, called with the view's tag as `this`. */\nexport interface SearchFieldFunctions {\n focus?(this: { nativeTag: number }): Promise<void>;\n blur?(this: { nativeTag: number }): Promise<void>;\n}\n\ndeclare const ngDevMode: unknown;\n\nconst MODULE = 'NgNativeSearchField';\n\nlet warned = false;\n\n/** Says once, in development, that the build has no native search field to draw. */\nfunction warnMissing(): void {\n if ((typeof ngDevMode !== 'undefined' && !ngDevMode) || warned) return;\n warned = true;\n console.warn(\n '[angular-native] <search-field> is native code of @ng-native/expo, which this build does not ' +\n 'have, so it draws nothing. Expo Go cannot load it: run a development build.',\n );\n}\n\n/**\n * The field's face by the PostScript name UIKit finds it by: expo-font registers it under the name\n * the app gives it, which `UIFont(name:)` does not know. Android's font manager finds that name.\n */\nfunction fieldFontName(props: Record<string, unknown>, postScriptName: PostScriptNames): void {\n const family = props['fontFamily'];\n if (typeof family === 'string') props['fontFamily'] = postScriptName(family) ?? family;\n}\n\n@Component({\n selector: 'search-field',\n template: '',\n styles: ':host { height: 56px; }',\n host: {\n '[text]': 'value()',\n '[enabled]': '!disabled()',\n '[mostRecentEventCount]': 'eventCount()',\n '[placeholder]': 'placeholder()',\n '[showsCancelButton]': 'showsCancelButton()',\n '[autoCapitalize]': 'autoCapitalize()',\n '[tintColor]': 'tintColor()',\n // Fabric draws a view the build does not have as a placeholder box naming it.\n '[style.display]': 'missing ? \"none\" : undefined',\n },\n})\nexport class SearchField {\n /**\n * The functions native defines on the view, or null where the build has no native search\n * field. Overridden in a test.\n */\n static readonly SOURCE = new InjectionToken<SearchFieldFunctions | null>(\n 'angular-native.searchFieldSource',\n {\n factory: () =>\n optional(() => {\n const core = require('expo-modules-core') as typeof import('expo-modules-core');\n const module = core.requireOptionalNativeModule<{\n ViewPrototypes?: Record<string, SearchFieldFunctions>;\n }>(MODULE);\n return module ? (module.ViewPrototypes?.[MODULE] ?? {}) : null;\n }),\n },\n );\n\n /**\n * The text in the field: typing writes it, and text set from code is put in the field. A\n * `model()`, which is all `FormValueControl<string>` asks, so `[formField]` binds it.\n */\n readonly value = model('');\n /** Refuse input and show the field dimmed. Signal Forms' `disabled()` rule sets it. */\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly placeholder = input<string>();\n /**\n * iOS: whether the Cancel button shows. Left unset it shows while the field has the keyboard,\n * as in a search bar under a navigation bar.\n */\n readonly showsCancelButton = input(undefined, { transform: optionalBoolean });\n readonly autoCapitalize = input<'none' | 'words' | 'sentences' | 'characters'>();\n /** The colour of the cursor and the Cancel button. */\n readonly tintColor = input<string>();\n\n /** The keyboard's search key was pressed, with the text in the field. */\n readonly search = output<string>();\n /** iOS: the Cancel button was pressed. The field is emptied and gives up the keyboard. */\n readonly cancel = output<void>();\n readonly searchFocus = output<void>();\n readonly searchBlur = output<void>();\n /** The field gave up the keyboard: what Signal Forms marks a field touched from. */\n readonly touch = output<void>();\n\n /**\n * The keystroke the text answers, as React Native's text input counts them: native skips a text\n * older than what has been typed since, which a fast typist's echo otherwise overwrites.\n */\n protected readonly eventCount = signal(0);\n\n private readonly functions = inject(SearchField.SOURCE);\n protected readonly missing = !this.functions;\n private readonly node = inject(ElementRef).nativeElement as EngineNode;\n private readonly engine = inject(Engine, { optional: true });\n\n constructor() {\n registerViewName('search-field', expoViewName(MODULE), undefined, {\n fontNames: nativePlatform() === 'ios' ? fieldFontName : undefined,\n });\n if (this.missing) warnMissing();\n const host =\n (this.node as { engine?: Pick<Engine, 'setEventListener'> }).engine ?? inject(HostEngine);\n const listen = (event: string, handle: (payload: Record<string, unknown>) => void) =>\n host.setEventListener(this.node, event, (raw) =>\n handle((raw as NativeSyntheticEvent<Record<string, unknown>>)?.nativeEvent ?? {}),\n );\n const stops = [\n listen('topChangeText', ({ text, eventCount }) => {\n if (typeof eventCount === 'number') this.eventCount.set(eventCount);\n this.value.set(String(text ?? ''));\n }),\n // Named apart from the outputs: a native event of an output's name reaches its listener too.\n listen('topSubmitSearch', ({ text }) => this.search.emit(String(text ?? this.value()))),\n listen('topPressCancel', () => this.cancel.emit()),\n listen('topBeginEditing', () => this.searchFocus.emit()),\n listen('topEndEditing', () => {\n this.searchBlur.emit();\n this.touch.emit();\n }),\n ];\n inject(DestroyRef).onDestroy(() => stops.forEach((stop) => stop()));\n }\n\n /** Give the field the keyboard. Does nothing before the view has reached the screen. */\n async focus(): Promise<void> {\n await this.call('focus');\n }\n\n /** Take the keyboard away from the field. */\n async blur(): Promise<void> {\n await this.call('blur');\n }\n\n /** Empty the field, and the value with it. */\n clear(): void {\n this.value.set('');\n }\n\n private async call(name: 'focus' | 'blur'): Promise<void> {\n const nativeTag = this.engine?.tagOf(this.node);\n if (nativeTag == null) return;\n await this.functions?.[name]?.call({ nativeTag });\n }\n}\n"]}
|
package/dist/symbol.d.ts
CHANGED
|
@@ -27,10 +27,12 @@ export declare class ExpoSymbol {
|
|
|
27
27
|
readonly colors: import("@angular/core").InputSignal<string | readonly string[] | undefined>;
|
|
28
28
|
readonly resizeMode: import("@angular/core").InputSignal<SymbolResizeMode | undefined>;
|
|
29
29
|
readonly animationSpec: import("@angular/core").InputSignal<SymbolAnimationSpec | undefined>;
|
|
30
|
-
/**
|
|
30
|
+
/** The point size the symbol is drawn at. */
|
|
31
31
|
readonly size: import("@angular/core").InputSignalWithTransform<number, unknown>;
|
|
32
32
|
protected readonly colourList: import("@angular/core").Signal<readonly string[] | undefined>;
|
|
33
33
|
protected readonly animated: import("@angular/core").Signal<boolean>;
|
|
34
|
+
/** Width and height: the symbol image's at the point size, or the square without native's. */
|
|
35
|
+
protected readonly box: import("@angular/core").Signal<number[] | readonly [number, number]>;
|
|
34
36
|
static ɵfac: i0.ɵɵFactoryDeclaration<ExpoSymbol, never>;
|
|
35
37
|
static ɵcmp: i0.ɵɵComponentDeclaration<ExpoSymbol, "expo-symbol", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "scale": { "alias": "scale"; "required": false; "isSignal": true; }; "weight": { "alias": "weight"; "required": false; "isSignal": true; }; "tintColor": { "alias": "tintColor"; "required": false; "isSignal": true; }; "colors": { "alias": "colors"; "required": false; "isSignal": true; }; "resizeMode": { "alias": "resizeMode"; "required": false; "isSignal": true; }; "animationSpec": { "alias": "animationSpec"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
36
38
|
}
|
package/dist/symbol.js
CHANGED
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
* `<expo-symbol>`: an SF Symbol, from `expo-symbols`, typed so a template is checked against the
|
|
3
3
|
* props. iOS only. Registered with `registerExpoViews('expo-symbol')`.
|
|
4
4
|
*
|
|
5
|
-
* It does what the module's React component does before native sees the props:
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* It does what the module's React component does before native sees the props: `type` is
|
|
6
|
+
* `monochrome` unless set, one colour or several become the list native takes, and an
|
|
7
|
+
* `animationSpec` is what turns animation on.
|
|
8
|
+
*
|
|
9
|
+
* `size` is a point size, as SwiftUI's `.font(.system(size:))` takes it (24 unless set): the view
|
|
10
|
+
* is the size of the symbol's image at that point size, weight and scale, which this package's
|
|
11
|
+
* native module reports, and the symbol fills it. Without that module, as in Expo Go, the view is
|
|
12
|
+
* `size` points square, as the React component makes it, and the symbol is fitted into it, which
|
|
13
|
+
* draws most symbols smaller than SwiftUI does.
|
|
8
14
|
*
|
|
9
15
|
* ```html
|
|
10
16
|
* <expo-symbol name="heart.fill" [size]="28" tintColor="#ff2d55" weight="semibold" />
|
|
@@ -34,7 +40,7 @@ export class ExpoSymbol {
|
|
|
34
40
|
...(ngDevMode ? [undefined, { debugName: "resizeMode" }] : /* istanbul ignore next */ []));
|
|
35
41
|
animationSpec = input(/* @ts-ignore */
|
|
36
42
|
...(ngDevMode ? [undefined, { debugName: "animationSpec" }] : /* istanbul ignore next */ []));
|
|
37
|
-
/**
|
|
43
|
+
/** The point size the symbol is drawn at. */
|
|
38
44
|
size = input(24, { ...(ngDevMode ? { debugName: "size" } : /* istanbul ignore next */ {}), transform: (value) => optionalNumber(value) ?? 24 });
|
|
39
45
|
colourList = computed(() => {
|
|
40
46
|
const colours = this.colors();
|
|
@@ -43,8 +49,14 @@ export class ExpoSymbol {
|
|
|
43
49
|
...(ngDevMode ? [{ debugName: "colourList" }] : /* istanbul ignore next */ []));
|
|
44
50
|
animated = computed(() => this.animationSpec() !== undefined, /* @ts-ignore */
|
|
45
51
|
...(ngDevMode ? [{ debugName: "animated" }] : /* istanbul ignore next */ []));
|
|
52
|
+
/** Width and height: the symbol image's at the point size, or the square without native's. */
|
|
53
|
+
box = computed(() => {
|
|
54
|
+
const size = this.size();
|
|
55
|
+
return symbolImageSize(this.name(), size, this.weight(), this.scale()) ?? [size, size];
|
|
56
|
+
}, /* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [{ debugName: "box" }] : /* istanbul ignore next */ []));
|
|
46
58
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: ExpoSymbol, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
47
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: ExpoSymbol, isStandalone: true, selector: "expo-symbol", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, weight: { classPropertyName: "weight", publicName: "weight", isSignal: true, isRequired: false, transformFunction: null }, tintColor: { classPropertyName: "tintColor", publicName: "tintColor", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null }, resizeMode: { classPropertyName: "resizeMode", publicName: "resizeMode", isSignal: true, isRequired: false, transformFunction: null }, animationSpec: { classPropertyName: "animationSpec", publicName: "animationSpec", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "name": "name()", "type": "type()", "scale": "scale()", "weight": "weight()", "tintColor": "tintColor()", "colors": "colourList()", "resizeMode": "resizeMode()", "animationSpec": "animationSpec()", "animated": "animated()", "style.width": "
|
|
59
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: ExpoSymbol, isStandalone: true, selector: "expo-symbol", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, weight: { classPropertyName: "weight", publicName: "weight", isSignal: true, isRequired: false, transformFunction: null }, tintColor: { classPropertyName: "tintColor", publicName: "tintColor", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null }, resizeMode: { classPropertyName: "resizeMode", publicName: "resizeMode", isSignal: true, isRequired: false, transformFunction: null }, animationSpec: { classPropertyName: "animationSpec", publicName: "animationSpec", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "name": "name()", "type": "type()", "scale": "scale()", "weight": "weight()", "tintColor": "tintColor()", "colors": "colourList()", "resizeMode": "resizeMode()", "animationSpec": "animationSpec()", "animated": "animated()", "style.width": "box()[0]", "style.height": "box()[1]" } }, ngImport: i0, template: '', isInline: true });
|
|
48
60
|
}
|
|
49
61
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: ExpoSymbol, decorators: [{
|
|
50
62
|
type: Component,
|
|
@@ -61,9 +73,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
61
73
|
'[resizeMode]': 'resizeMode()',
|
|
62
74
|
'[animationSpec]': 'animationSpec()',
|
|
63
75
|
'[animated]': 'animated()',
|
|
64
|
-
'[style.width]': '
|
|
65
|
-
'[style.height]': '
|
|
76
|
+
'[style.width]': 'box()[0]',
|
|
77
|
+
'[style.height]': 'box()[1]',
|
|
66
78
|
},
|
|
67
79
|
}]
|
|
68
80
|
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], scale: [{ type: i0.Input, args: [{ isSignal: true, alias: "scale", required: false }] }], weight: [{ type: i0.Input, args: [{ isSignal: true, alias: "weight", required: false }] }], tintColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "tintColor", required: false }] }], colors: [{ type: i0.Input, args: [{ isSignal: true, alias: "colors", required: false }] }], resizeMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizeMode", required: false }] }], animationSpec: [{ type: i0.Input, args: [{ isSignal: true, alias: "animationSpec", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
81
|
+
/** The size of the symbol's image in points, or null where native cannot say. */
|
|
82
|
+
function symbolImageSize(name, pointSize, weight, scale) {
|
|
83
|
+
const native = globalThis.expo
|
|
84
|
+
?.modules?.NgNativeSymbol;
|
|
85
|
+
const size = native?.imageSize?.(name, pointSize, weight, scale);
|
|
86
|
+
return size ? [size[0], size[1]] : null;
|
|
87
|
+
}
|
|
69
88
|
//# sourceMappingURL=symbol.js.map
|
package/dist/symbol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbol.js","sourceRoot":"","sources":["../src/symbol.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"symbol.js","sourceRoot":"","sources":["../src/symbol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;;AA4DjD,MAAM,OAAO,UAAU;IACrB,iFAAiF;IACxE,IAAI,GAAG,KAAK,CAAC,QAAQ;6EAAU,CAAC;IAChC,IAAI,GAAG,KAAK,CAAa,YAAY;6EAAC,CAAC;IACvC,KAAK,GAAG,KAAK;yFAAe,CAAC;IAC7B,MAAM,GAAG,KAAK;0FAAgB,CAAC;IACxC,6DAA6D;IACpD,SAAS,GAAG,KAAK;6FAAU,CAAC;IACrC,0CAA0C;IACjC,MAAM,GAAG,KAAK;0FAA8B,CAAC;IAC7C,UAAU,GAAG,KAAK;8FAAoB,CAAC;IACvC,aAAa,GAAG,KAAK;iGAAuB,CAAC;IACtD,6CAA6C;IACpC,IAAI,GAAG,KAAK,CAAC,EAAE,4EAAI,SAAS,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC;IAEvE,UAAU,GAAG,QAAQ,CAAC,GAAG,EAAE;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/F,CAAC;mFAAC,CAAC;IACgB,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,SAAS;iFAAC,CAAC;IACjF,8FAA8F;IAC3E,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzF,CAAC;4EAAC,CAAC;uGAxBQ,UAAU;2FAAV,UAAU,2+CAfX,EAAE;;2FAeD,UAAU;kBAjBtB,SAAS;mBAAC;oBACT,QAAQ,EAAE,aAAa;oBACvB,QAAQ,EAAE,EAAE;oBACZ,IAAI,EAAE;wBACJ,QAAQ,EAAE,QAAQ;wBAClB,QAAQ,EAAE,QAAQ;wBAClB,SAAS,EAAE,SAAS;wBACpB,UAAU,EAAE,UAAU;wBACtB,aAAa,EAAE,aAAa;wBAC5B,UAAU,EAAE,cAAc;wBAC1B,cAAc,EAAE,cAAc;wBAC9B,iBAAiB,EAAE,iBAAiB;wBACpC,YAAY,EAAE,YAAY;wBAC1B,eAAe,EAAE,UAAU;wBAC3B,gBAAgB,EAAE,UAAU;qBAC7B;iBACF;;AAsCD,iFAAiF;AACjF,SAAS,eAAe,CACtB,IAAY,EACZ,SAAiB,EACjB,MAAgC,EAChC,KAA8B;IAE9B,MAAM,MAAM,GAAI,UAAyE,CAAC,IAAI;QAC5F,EAAE,OAAO,EAAE,cAAc,CAAC;IAC5B,MAAM,IAAI,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC","sourcesContent":["/**\n * `<expo-symbol>`: an SF Symbol, from `expo-symbols`, typed so a template is checked against the\n * props. iOS only. Registered with `registerExpoViews('expo-symbol')`.\n *\n * It does what the module's React component does before native sees the props: `type` is\n * `monochrome` unless set, one colour or several become the list native takes, and an\n * `animationSpec` is what turns animation on.\n *\n * `size` is a point size, as SwiftUI's `.font(.system(size:))` takes it (24 unless set): the view\n * is the size of the symbol's image at that point size, weight and scale, which this package's\n * native module reports, and the symbol fills it. Without that module, as in Expo Go, the view is\n * `size` points square, as the React component makes it, and the symbol is fitted into it, which\n * draws most symbols smaller than SwiftUI does.\n *\n * ```html\n * <expo-symbol name=\"heart.fill\" [size]=\"28\" tintColor=\"#ff2d55\" weight=\"semibold\" />\n * <expo-symbol name=\"cloud.sun.fill\" type=\"palette\" [colors]=\"['#fff', '#ffcc00']\" />\n * ```\n */\nimport { Component, computed, input } from '@angular/core';\nimport { optionalNumber } from './transforms.ts';\n\nexport type SymbolType = 'monochrome' | 'hierarchical' | 'palette' | 'multicolor';\nexport type SymbolScale = 'default' | 'unspecified' | 'small' | 'medium' | 'large';\nexport type SymbolWeight =\n | 'unspecified'\n | 'ultraLight'\n | 'thin'\n | 'light'\n | 'regular'\n | 'medium'\n | 'semibold'\n | 'bold'\n | 'heavy'\n | 'black';\nexport type SymbolResizeMode =\n | 'scaleToFill'\n | 'scaleAspectFit'\n | 'scaleAspectFill'\n | 'redraw'\n | 'center'\n | 'top'\n | 'bottom'\n | 'left'\n | 'right'\n | 'topLeft'\n | 'topRight'\n | 'bottomLeft'\n | 'bottomRight';\n\n/** How a symbol animates, as `expo-symbols` describes it. */\nexport interface SymbolAnimationSpec {\n readonly effect?: {\n readonly type: 'bounce' | 'pulse' | 'scale';\n readonly wholeSymbol?: boolean;\n readonly direction?: 'up' | 'down';\n };\n readonly repeating?: boolean;\n readonly repeatCount?: number;\n readonly speed?: number;\n readonly variableAnimationSpec?: Readonly<Record<string, boolean>>;\n}\n\n@Component({\n selector: 'expo-symbol',\n template: '',\n host: {\n '[name]': 'name()',\n '[type]': 'type()',\n '[scale]': 'scale()',\n '[weight]': 'weight()',\n '[tintColor]': 'tintColor()',\n '[colors]': 'colourList()',\n '[resizeMode]': 'resizeMode()',\n '[animationSpec]': 'animationSpec()',\n '[animated]': 'animated()',\n '[style.width]': 'box()[0]',\n '[style.height]': 'box()[1]',\n },\n})\nexport class ExpoSymbol {\n /** The symbol's name, as SF Symbols lists it: `heart.fill`, `cloud.sun.rain`. */\n readonly name = input.required<string>();\n readonly type = input<SymbolType>('monochrome');\n readonly scale = input<SymbolScale>();\n readonly weight = input<SymbolWeight>();\n /** The colour of a `monochrome` or `hierarchical` symbol. */\n readonly tintColor = input<string>();\n /** The layers' colours, for `palette`. */\n readonly colors = input<string | readonly string[]>();\n readonly resizeMode = input<SymbolResizeMode>();\n readonly animationSpec = input<SymbolAnimationSpec>();\n /** The point size the symbol is drawn at. */\n readonly size = input(24, { transform: (value: unknown) => optionalNumber(value) ?? 24 });\n\n protected readonly colourList = computed(() => {\n const colours = this.colors();\n return colours === undefined ? undefined : typeof colours === 'string' ? [colours] : colours;\n });\n protected readonly animated = computed(() => this.animationSpec() !== undefined);\n /** Width and height: the symbol image's at the point size, or the square without native's. */\n protected readonly box = computed(() => {\n const size = this.size();\n return symbolImageSize(this.name(), size, this.weight(), this.scale()) ?? [size, size];\n });\n}\n\n/** This package's native symbol module, iOS only and absent from Expo Go. */\ninterface NativeSymbol {\n imageSize?(\n name: string,\n pointSize: number,\n weight?: SymbolWeight,\n scale?: SymbolScale,\n ): readonly number[] | null;\n}\n\n/** The size of the symbol's image in points, or null where native cannot say. */\nfunction symbolImageSize(\n name: string,\n pointSize: number,\n weight: SymbolWeight | undefined,\n scale: SymbolScale | undefined,\n): readonly [number, number] | null {\n const native = (globalThis as { expo?: { modules?: { NgNativeSymbol?: NativeSymbol } } }).expo\n ?.modules?.NgNativeSymbol;\n const size = native?.imageSize?.(name, pointSize, weight, scale);\n return size ? [size[0]!, size[1]!] : null;\n}\n"]}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { type NativeSyntheticEvent } from '@ng-native/fabric';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
|
+
/** How Compose's sheet may be dismissed other than by a swipe, as `@expo/ui` names it. */
|
|
4
|
+
export interface UiModalBottomSheetProperties {
|
|
5
|
+
readonly shouldDismissOnBackPress?: boolean;
|
|
6
|
+
readonly shouldDismissOnClickOutside?: boolean;
|
|
7
|
+
}
|
|
3
8
|
/** What SwiftUI's sheet sends when the user dismisses it: that it is no longer presented. */
|
|
4
9
|
export type UiBottomSheetPresentedEvent = NativeSyntheticEvent<{
|
|
5
10
|
readonly isPresented: boolean;
|
|
@@ -15,6 +20,10 @@ export declare class UiBottomSheetView {
|
|
|
15
20
|
readonly containerColor: import("@angular/core").InputSignal<unknown>;
|
|
16
21
|
/** Compose: the sheet opens at its full height rather than resting at half the screen's. */
|
|
17
22
|
readonly skipPartiallyExpanded: import("@angular/core").InputSignal<boolean | undefined>;
|
|
23
|
+
/** Compose: whether the sheet can be dragged, between its heights and down to dismiss it. */
|
|
24
|
+
readonly sheetGesturesEnabled: import("@angular/core").InputSignal<boolean | undefined>;
|
|
25
|
+
/** Compose: whether the back button and a tap outside the sheet dismiss it. */
|
|
26
|
+
readonly properties: import("@angular/core").InputSignal<UiModalBottomSheetProperties | undefined>;
|
|
18
27
|
/** SwiftUI: the user dismissed the sheet, or it was presented by something other than the prop. */
|
|
19
28
|
readonly isPresentedChange: import("@angular/core").OutputEmitterRef<UiBottomSheetPresentedEvent>;
|
|
20
29
|
/** SwiftUI: the sheet has finished dismissing, whoever dismissed it. */
|
|
@@ -23,5 +32,5 @@ export declare class UiBottomSheetView {
|
|
|
23
32
|
readonly dismissRequest: import("@angular/core").OutputEmitterRef<NativeSyntheticEvent<Record<string, never>>>;
|
|
24
33
|
constructor();
|
|
25
34
|
static ɵfac: i0.ɵɵFactoryDeclaration<UiBottomSheetView, never>;
|
|
26
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<UiBottomSheetView, "ui-bottom-sheet-view", never, { "isPresented": { "alias": "isPresented"; "required": false; "isSignal": true; }; "fitToContents": { "alias": "fitToContents"; "required": false; "isSignal": true; }; "showDragHandle": { "alias": "showDragHandle"; "required": false; "isSignal": true; }; "containerColor": { "alias": "containerColor"; "required": false; "isSignal": true; }; "skipPartiallyExpanded": { "alias": "skipPartiallyExpanded"; "required": false; "isSignal": true; }; }, { "isPresentedChange": "isPresentedChange"; "dismiss": "dismiss"; "dismissRequest": "dismissRequest"; }, never, ["*"], true, never>;
|
|
35
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<UiBottomSheetView, "ui-bottom-sheet-view", never, { "isPresented": { "alias": "isPresented"; "required": false; "isSignal": true; }; "fitToContents": { "alias": "fitToContents"; "required": false; "isSignal": true; }; "showDragHandle": { "alias": "showDragHandle"; "required": false; "isSignal": true; }; "containerColor": { "alias": "containerColor"; "required": false; "isSignal": true; }; "skipPartiallyExpanded": { "alias": "skipPartiallyExpanded"; "required": false; "isSignal": true; }; "sheetGesturesEnabled": { "alias": "sheetGesturesEnabled"; "required": false; "isSignal": true; }; "properties": { "alias": "properties"; "required": false; "isSignal": true; }; }, { "isPresentedChange": "isPresentedChange"; "dismiss": "dismiss"; "dismissRequest": "dismissRequest"; }, never, ["*"], true, never>;
|
|
27
36
|
}
|
|
@@ -29,6 +29,12 @@ export class UiBottomSheetView {
|
|
|
29
29
|
/** Compose: the sheet opens at its full height rather than resting at half the screen's. */
|
|
30
30
|
skipPartiallyExpanded = input(/* @ts-ignore */
|
|
31
31
|
...(ngDevMode ? [undefined, { debugName: "skipPartiallyExpanded" }] : /* istanbul ignore next */ []));
|
|
32
|
+
/** Compose: whether the sheet can be dragged, between its heights and down to dismiss it. */
|
|
33
|
+
sheetGesturesEnabled = input(/* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [undefined, { debugName: "sheetGesturesEnabled" }] : /* istanbul ignore next */ []));
|
|
35
|
+
/** Compose: whether the back button and a tap outside the sheet dismiss it. */
|
|
36
|
+
properties = input(/* @ts-ignore */
|
|
37
|
+
...(ngDevMode ? [undefined, { debugName: "properties" }] : /* istanbul ignore next */ []));
|
|
32
38
|
/** SwiftUI: the user dismissed the sheet, or it was presented by something other than the prop. */
|
|
33
39
|
isPresentedChange = output();
|
|
34
40
|
/** SwiftUI: the sheet has finished dismissing, whoever dismissed it. */
|
|
@@ -40,7 +46,7 @@ export class UiBottomSheetView {
|
|
|
40
46
|
keepNativeView(inject(ElementRef).nativeElement);
|
|
41
47
|
}
|
|
42
48
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiBottomSheetView, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
43
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: UiBottomSheetView, isStandalone: true, selector: "ui-bottom-sheet-view", inputs: { isPresented: { classPropertyName: "isPresented", publicName: "isPresented", isSignal: true, isRequired: false, transformFunction: null }, fitToContents: { classPropertyName: "fitToContents", publicName: "fitToContents", isSignal: true, isRequired: false, transformFunction: null }, showDragHandle: { classPropertyName: "showDragHandle", publicName: "showDragHandle", isSignal: true, isRequired: false, transformFunction: null }, containerColor: { classPropertyName: "containerColor", publicName: "containerColor", isSignal: true, isRequired: false, transformFunction: null }, skipPartiallyExpanded: { classPropertyName: "skipPartiallyExpanded", publicName: "skipPartiallyExpanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isPresentedChange: "isPresentedChange", dismiss: "dismiss", dismissRequest: "dismissRequest" }, host: { properties: { "isPresented": "isPresented()", "fitToContents": "fitToContents()", "showDragHandle": "showDragHandle()", "containerColor": "containerColor()", "skipPartiallyExpanded": "skipPartiallyExpanded()" } }, ngImport: i0, template: '<ng-content />', isInline: true });
|
|
49
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: UiBottomSheetView, isStandalone: true, selector: "ui-bottom-sheet-view", inputs: { isPresented: { classPropertyName: "isPresented", publicName: "isPresented", isSignal: true, isRequired: false, transformFunction: null }, fitToContents: { classPropertyName: "fitToContents", publicName: "fitToContents", isSignal: true, isRequired: false, transformFunction: null }, showDragHandle: { classPropertyName: "showDragHandle", publicName: "showDragHandle", isSignal: true, isRequired: false, transformFunction: null }, containerColor: { classPropertyName: "containerColor", publicName: "containerColor", isSignal: true, isRequired: false, transformFunction: null }, skipPartiallyExpanded: { classPropertyName: "skipPartiallyExpanded", publicName: "skipPartiallyExpanded", isSignal: true, isRequired: false, transformFunction: null }, sheetGesturesEnabled: { classPropertyName: "sheetGesturesEnabled", publicName: "sheetGesturesEnabled", isSignal: true, isRequired: false, transformFunction: null }, properties: { classPropertyName: "properties", publicName: "properties", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isPresentedChange: "isPresentedChange", dismiss: "dismiss", dismissRequest: "dismissRequest" }, host: { properties: { "isPresented": "isPresented()", "fitToContents": "fitToContents()", "showDragHandle": "showDragHandle()", "containerColor": "containerColor()", "skipPartiallyExpanded": "skipPartiallyExpanded()", "sheetGesturesEnabled": "sheetGesturesEnabled()", "properties": "properties()" } }, ngImport: i0, template: '<ng-content />', isInline: true });
|
|
44
50
|
}
|
|
45
51
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: UiBottomSheetView, decorators: [{
|
|
46
52
|
type: Component,
|
|
@@ -53,7 +59,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
53
59
|
'[showDragHandle]': 'showDragHandle()',
|
|
54
60
|
'[containerColor]': 'containerColor()',
|
|
55
61
|
'[skipPartiallyExpanded]': 'skipPartiallyExpanded()',
|
|
62
|
+
'[sheetGesturesEnabled]': 'sheetGesturesEnabled()',
|
|
63
|
+
'[properties]': 'properties()',
|
|
56
64
|
},
|
|
57
65
|
}]
|
|
58
|
-
}], ctorParameters: () => [], propDecorators: { isPresented: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPresented", required: false }] }], fitToContents: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitToContents", required: false }] }], showDragHandle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDragHandle", required: false }] }], containerColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerColor", required: false }] }], skipPartiallyExpanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipPartiallyExpanded", required: false }] }], isPresentedChange: [{ type: i0.Output, args: ["isPresentedChange"] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }], dismissRequest: [{ type: i0.Output, args: ["dismissRequest"] }] } });
|
|
66
|
+
}], ctorParameters: () => [], propDecorators: { isPresented: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPresented", required: false }] }], fitToContents: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitToContents", required: false }] }], showDragHandle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDragHandle", required: false }] }], containerColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerColor", required: false }] }], skipPartiallyExpanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipPartiallyExpanded", required: false }] }], sheetGesturesEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetGesturesEnabled", required: false }] }], properties: [{ type: i0.Input, args: [{ isSignal: true, alias: "properties", required: false }] }], isPresentedChange: [{ type: i0.Output, args: ["isPresentedChange"] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }], dismissRequest: [{ type: i0.Output, args: ["dismissRequest"] }] } });
|
|
59
67
|
//# sourceMappingURL=ui-bottom-sheet-view.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-bottom-sheet-view.js","sourceRoot":"","sources":["../src/ui-bottom-sheet-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAA6B,cAAc,EAAE,MAAM,mBAAmB,CAAC;;
|
|
1
|
+
{"version":3,"file":"ui-bottom-sheet-view.js","sourceRoot":"","sources":["../src/ui-bottom-sheet-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAA6B,cAAc,EAAE,MAAM,mBAAmB,CAAC;;AAwB9E,MAAM,OAAO,iBAAiB;IAC5B,sFAAsF;IAC7E,WAAW,GAAG,KAAK;+FAAW,CAAC;IACxC,oEAAoE;IAC3D,aAAa,GAAG,KAAK;iGAAW,CAAC;IAC1C,iDAAiD;IACxC,cAAc,GAAG,KAAK;kGAAW,CAAC;IAC3C,gGAAgG;IACvF,cAAc,GAAG,KAAK;kGAAW,CAAC;IAC3C,4FAA4F;IACnF,qBAAqB,GAAG,KAAK;yGAAW,CAAC;IAClD,6FAA6F;IACpF,oBAAoB,GAAG,KAAK;wGAAW,CAAC;IACjD,+EAA+E;IACtE,UAAU,GAAG,KAAK;8FAAgC,CAAC;IAC5D,mGAAmG;IAC1F,iBAAiB,GAAG,MAAM,EAA+B,CAAC;IACnE,wEAAwE;IAC/D,OAAO,GAAG,MAAM,EAA+C,CAAC;IACzE,mFAAmF;IAC1E,cAAc,GAAG,MAAM,EAA+C,CAAC;IAEhF;QACE,iFAAiF;QACjF,cAAc,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,aAAa,CAAC,CAAC;IACnD,CAAC;uGAzBU,iBAAiB;2FAAjB,iBAAiB,ygDAXlB,gBAAgB;;2FAWf,iBAAiB;kBAb7B,SAAS;mBAAC;oBACT,QAAQ,EAAE,sBAAsB;oBAChC,QAAQ,EAAE,gBAAgB;oBAC1B,IAAI,EAAE;wBACJ,eAAe,EAAE,eAAe;wBAChC,iBAAiB,EAAE,iBAAiB;wBACpC,kBAAkB,EAAE,kBAAkB;wBACtC,kBAAkB,EAAE,kBAAkB;wBACtC,yBAAyB,EAAE,yBAAyB;wBACpD,wBAAwB,EAAE,wBAAwB;wBAClD,cAAc,EAAE,cAAc;qBAC/B;iBACF","sourcesContent":["/**\n * `<ui-bottom-sheet-view>`: `@expo/ui`'s sheet itself, with each platform's props typed.\n *\n * `UiBottomSheet` in `expo-ui-components.ts` is the component an app uses, and this is the native\n * view inside it: SwiftUI's `BottomSheetView` on iOS, Compose's `ModalBottomSheetView` on Android.\n * It has an element name of its own because `ui-bottom-sheet` is that component's, and a\n * component's template takes its own selector to be the component again.\n *\n * The two views share no prop. An input left unset never reaches native, so the component sets\n * the ones the platform reads. The events are outputs for their type only, as with the other\n * `@expo/ui` components: the element's own event is what arrives.\n */\nimport { Component, ElementRef, inject, input, output } from '@angular/core';\nimport { type NativeSyntheticEvent, keepNativeView } from '@ng-native/fabric';\n\n/** How Compose's sheet may be dismissed other than by a swipe, as `@expo/ui` names it. */\nexport interface UiModalBottomSheetProperties {\n readonly shouldDismissOnBackPress?: boolean;\n readonly shouldDismissOnClickOutside?: boolean;\n}\n\n/** What SwiftUI's sheet sends when the user dismisses it: that it is no longer presented. */\nexport type UiBottomSheetPresentedEvent = NativeSyntheticEvent<{ readonly isPresented: boolean }>;\n\n@Component({\n selector: 'ui-bottom-sheet-view',\n template: '<ng-content />',\n host: {\n '[isPresented]': 'isPresented()',\n '[fitToContents]': 'fitToContents()',\n '[showDragHandle]': 'showDragHandle()',\n '[containerColor]': 'containerColor()',\n '[skipPartiallyExpanded]': 'skipPartiallyExpanded()',\n '[sheetGesturesEnabled]': 'sheetGesturesEnabled()',\n '[properties]': 'properties()',\n },\n})\nexport class UiBottomSheetView {\n /** SwiftUI: whether the sheet is presented. The view stays in the tree either way. */\n readonly isPresented = input<boolean>();\n /** SwiftUI: the sheet's one detent is the height of its content. */\n readonly fitToContents = input<boolean>();\n /** Compose: whether the drag handle is drawn. */\n readonly showDragHandle = input<boolean>();\n /** Compose: the sheet's colour behind its content. A colour prop, so the engine converts it. */\n readonly containerColor = input<unknown>();\n /** Compose: the sheet opens at its full height rather than resting at half the screen's. */\n readonly skipPartiallyExpanded = input<boolean>();\n /** Compose: whether the sheet can be dragged, between its heights and down to dismiss it. */\n readonly sheetGesturesEnabled = input<boolean>();\n /** Compose: whether the back button and a tap outside the sheet dismiss it. */\n readonly properties = input<UiModalBottomSheetProperties>();\n /** SwiftUI: the user dismissed the sheet, or it was presented by something other than the prop. */\n readonly isPresentedChange = output<UiBottomSheetPresentedEvent>();\n /** SwiftUI: the sheet has finished dismissing, whoever dismissed it. */\n readonly dismiss = output<NativeSyntheticEvent<Record<string, never>>>();\n /** Compose: the user dismissed the sheet, which stays until it leaves the tree. */\n readonly dismissRequest = output<NativeSyntheticEvent<Record<string, never>>>();\n\n constructor() {\n // The host is the registered native view, not a plain one: see `keepNativeView`.\n keepNativeView(inject(ElementRef).nativeElement);\n }\n}\n"]}
|
package/expo-module.config.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"platforms": ["apple", "android"],
|
|
3
3
|
"apple": {
|
|
4
|
-
"modules": [
|
|
4
|
+
"modules": [
|
|
5
|
+
"LiveActivityTapsModule",
|
|
6
|
+
"ExpoUIModifiersModule",
|
|
7
|
+
"SearchFieldModule",
|
|
8
|
+
"SymbolImageSizeModule"
|
|
9
|
+
],
|
|
5
10
|
"appDelegateSubscribers": ["LiveActivityTapsObserver"]
|
|
6
11
|
},
|
|
7
12
|
"android": {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
The size of an SF Symbol's image at a point size, weight and scale, which `<expo-symbol>` lays its
|
|
6
|
+
view out at. SwiftUI lays an `Image(systemName:)` out at this size, while `expo-symbols` builds the
|
|
7
|
+
symbol at the system font size and fits it into the view, so the view's size is what sets how
|
|
8
|
+
large the symbol draws.
|
|
9
|
+
*/
|
|
10
|
+
public final class SymbolImageSizeModule: Module {
|
|
11
|
+
public func definition() -> ModuleDefinition {
|
|
12
|
+
Name("NgNativeSymbol")
|
|
13
|
+
|
|
14
|
+
Function("imageSize") { (name: String, pointSize: Double, weight: String?, scale: String?) -> [Double]? in
|
|
15
|
+
let configuration = UIImage.SymbolConfiguration(
|
|
16
|
+
pointSize: CGFloat(pointSize),
|
|
17
|
+
weight: Self.weight(weight),
|
|
18
|
+
scale: Self.scale(scale)
|
|
19
|
+
)
|
|
20
|
+
guard let image = UIImage(systemName: name, withConfiguration: configuration) else {
|
|
21
|
+
return nil
|
|
22
|
+
}
|
|
23
|
+
return [Double(image.size.width), Double(image.size.height)]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// `expo-symbols`' weights, as UIKit's.
|
|
28
|
+
private static func weight(_ name: String?) -> UIImage.SymbolWeight {
|
|
29
|
+
switch name {
|
|
30
|
+
case "ultraLight": return .ultraLight
|
|
31
|
+
case "thin": return .thin
|
|
32
|
+
case "light": return .light
|
|
33
|
+
case "regular": return .regular
|
|
34
|
+
case "medium": return .medium
|
|
35
|
+
case "semibold": return .semibold
|
|
36
|
+
case "bold": return .bold
|
|
37
|
+
case "heavy": return .heavy
|
|
38
|
+
case "black": return .black
|
|
39
|
+
default: return .unspecified
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// `expo-symbols`' scales, as UIKit's.
|
|
44
|
+
private static func scale(_ name: String?) -> UIImage.SymbolScale {
|
|
45
|
+
switch name {
|
|
46
|
+
case "small": return .small
|
|
47
|
+
case "medium": return .medium
|
|
48
|
+
case "large": return .large
|
|
49
|
+
case "unspecified": return .unspecified
|
|
50
|
+
default: return .default
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-native/expo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.1",
|
|
4
4
|
"description": "Expo modules as Angular services for Angular Native, plus registerExpoView for a module's native view.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -221,8 +221,8 @@
|
|
|
221
221
|
"access": "public"
|
|
222
222
|
},
|
|
223
223
|
"dependencies": {
|
|
224
|
-
"@ng-native/device": "0.
|
|
225
|
-
"@ng-native/fabric": "0.
|
|
224
|
+
"@ng-native/device": "0.18.1",
|
|
225
|
+
"@ng-native/fabric": "0.18.1"
|
|
226
226
|
},
|
|
227
227
|
"nx": {
|
|
228
228
|
"tags": [
|
|
@@ -256,6 +256,7 @@
|
|
|
256
256
|
"expo-foldables": "^0.1.0",
|
|
257
257
|
"expo-font": "^57.0.0 || ^58.0.0",
|
|
258
258
|
"expo-haptics": "^57.0.0 || ^58.0.0",
|
|
259
|
+
"expo-hinge": "^58.0.0",
|
|
259
260
|
"expo-image-manipulator": "^57.0.0 || ^58.0.0",
|
|
260
261
|
"expo-image-picker": "^57.0.0 || ^58.0.0",
|
|
261
262
|
"expo-keep-awake": "^57.0.0 || ^58.0.0",
|
|
@@ -286,44 +287,44 @@
|
|
|
286
287
|
"devDependencies": {
|
|
287
288
|
"@angular/core": "22.2.0",
|
|
288
289
|
"@babel/core": "^7.29.7",
|
|
289
|
-
"@expo/ui": "^
|
|
290
|
+
"@expo/ui": "^58.0.21",
|
|
290
291
|
"@react-native-async-storage/async-storage": "^3.1.1",
|
|
291
|
-
"expo": "^
|
|
292
|
-
"expo-apple-authentication": "~
|
|
293
|
-
"expo-application": "^
|
|
294
|
-
"expo-asset": "^
|
|
295
|
-
"expo-audio": "^
|
|
296
|
-
"expo-background-task": "^
|
|
297
|
-
"expo-battery": "^
|
|
298
|
-
"expo-brightness": "^
|
|
299
|
-
"expo-camera": "^
|
|
300
|
-
"expo-crypto": "^
|
|
301
|
-
"expo-device": "^
|
|
302
|
-
"expo-document-picker": "^
|
|
292
|
+
"expo": "^58.0.16",
|
|
293
|
+
"expo-apple-authentication": "~58.0.2",
|
|
294
|
+
"expo-application": "^58.1.2",
|
|
295
|
+
"expo-asset": "^58.0.17",
|
|
296
|
+
"expo-audio": "^58.0.9",
|
|
297
|
+
"expo-background-task": "^58.0.11",
|
|
298
|
+
"expo-battery": "^58.0.3",
|
|
299
|
+
"expo-brightness": "^58.0.2",
|
|
300
|
+
"expo-camera": "^58.0.11",
|
|
301
|
+
"expo-crypto": "^58.0.7",
|
|
302
|
+
"expo-device": "^58.0.5",
|
|
303
|
+
"expo-document-picker": "^58.0.4",
|
|
303
304
|
"expo-foldables": "^0.1.0",
|
|
304
|
-
"expo-image-manipulator": "^
|
|
305
|
-
"expo-image-picker": "^
|
|
306
|
-
"expo-keep-awake": "^
|
|
307
|
-
"expo-local-authentication": "^
|
|
305
|
+
"expo-image-manipulator": "^58.0.15",
|
|
306
|
+
"expo-image-picker": "^58.0.10",
|
|
307
|
+
"expo-keep-awake": "^58.0.3",
|
|
308
|
+
"expo-local-authentication": "^58.0.2",
|
|
308
309
|
"expo-local-llm": "^0.8.1",
|
|
309
|
-
"expo-localization": "^
|
|
310
|
-
"expo-location": "^
|
|
311
|
-
"expo-maps": "^
|
|
312
|
-
"expo-media-library": "^
|
|
313
|
-
"expo-network": "^
|
|
314
|
-
"expo-notifications": "^
|
|
315
|
-
"expo-screen-capture": "^
|
|
316
|
-
"expo-screen-orientation": "^
|
|
317
|
-
"expo-secure-store": "^
|
|
318
|
-
"expo-sensors": "^
|
|
319
|
-
"expo-splash-screen": "^
|
|
320
|
-
"expo-sqlite": "^
|
|
321
|
-
"expo-store-review": "^
|
|
322
|
-
"expo-tracking-transparency": "^
|
|
323
|
-
"expo-updates": "^
|
|
324
|
-
"expo-video": "^
|
|
325
|
-
"expo-web-browser": "^
|
|
326
|
-
"expo-widgets": "^
|
|
310
|
+
"expo-localization": "^58.0.5",
|
|
311
|
+
"expo-location": "^58.0.18",
|
|
312
|
+
"expo-maps": "^58.0.10",
|
|
313
|
+
"expo-media-library": "^58.0.11",
|
|
314
|
+
"expo-network": "^58.0.3",
|
|
315
|
+
"expo-notifications": "^58.1.5",
|
|
316
|
+
"expo-screen-capture": "^58.0.5",
|
|
317
|
+
"expo-screen-orientation": "^58.0.3",
|
|
318
|
+
"expo-secure-store": "^58.0.2",
|
|
319
|
+
"expo-sensors": "^58.0.4",
|
|
320
|
+
"expo-splash-screen": "^58.0.10",
|
|
321
|
+
"expo-sqlite": "^58.0.13",
|
|
322
|
+
"expo-store-review": "^58.0.2",
|
|
323
|
+
"expo-tracking-transparency": "^58.0.2",
|
|
324
|
+
"expo-updates": "^58.0.17",
|
|
325
|
+
"expo-video": "^58.0.12",
|
|
326
|
+
"expo-web-browser": "^58.0.6",
|
|
327
|
+
"expo-widgets": "^58.0.21",
|
|
327
328
|
"react-native-watch-connectivity": "^2.0.0",
|
|
328
329
|
"typescript": "~6.0.3"
|
|
329
330
|
},
|
|
@@ -382,6 +383,9 @@
|
|
|
382
383
|
"expo-haptics": {
|
|
383
384
|
"optional": true
|
|
384
385
|
},
|
|
386
|
+
"expo-hinge": {
|
|
387
|
+
"optional": true
|
|
388
|
+
},
|
|
385
389
|
"expo-image-manipulator": {
|
|
386
390
|
"optional": true
|
|
387
391
|
},
|