@ng-native/expo 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +413 -1
  3. package/dist/app-info.d.ts +58 -0
  4. package/dist/app-info.js +71 -0
  5. package/dist/app-info.js.map +1 -0
  6. package/dist/apple-sign-in-button.d.ts +16 -0
  7. package/dist/apple-sign-in-button.js +55 -0
  8. package/dist/apple-sign-in-button.js.map +1 -0
  9. package/dist/apple-sign-in.d.ts +68 -0
  10. package/dist/apple-sign-in.js +120 -0
  11. package/dist/apple-sign-in.js.map +1 -0
  12. package/dist/assets.d.ts +24 -0
  13. package/dist/assets.js +47 -0
  14. package/dist/assets.js.map +1 -0
  15. package/dist/background-task.d.ts +66 -0
  16. package/dist/background-task.js +82 -0
  17. package/dist/background-task.js.map +1 -0
  18. package/dist/battery.d.ts +46 -0
  19. package/dist/battery.js +76 -0
  20. package/dist/battery.js.map +1 -0
  21. package/dist/biometrics.d.ts +45 -0
  22. package/dist/biometrics.js +53 -0
  23. package/dist/biometrics.js.map +1 -0
  24. package/dist/brightness.d.ts +38 -0
  25. package/dist/brightness.js +81 -0
  26. package/dist/brightness.js.map +1 -0
  27. package/dist/browser.d.ts +42 -0
  28. package/dist/browser.js +42 -0
  29. package/dist/browser.js.map +1 -0
  30. package/dist/camera.d.ts +48 -0
  31. package/dist/camera.js +59 -0
  32. package/dist/camera.js.map +1 -0
  33. package/dist/clipboard.d.ts +43 -0
  34. package/dist/clipboard.js +60 -0
  35. package/dist/clipboard.js.map +1 -0
  36. package/dist/community-views.d.ts +14 -0
  37. package/dist/community-views.js +76 -0
  38. package/dist/community-views.js.map +1 -0
  39. package/dist/crypto.d.ts +56 -0
  40. package/dist/crypto.js +84 -0
  41. package/dist/crypto.js.map +1 -0
  42. package/dist/database.d.ts +47 -0
  43. package/dist/database.js +108 -0
  44. package/dist/database.js.map +1 -0
  45. package/dist/document-picker.d.ts +34 -0
  46. package/dist/document-picker.js +40 -0
  47. package/dist/document-picker.js.map +1 -0
  48. package/dist/dom-component.d.ts +87 -0
  49. package/dist/dom-component.js +139 -0
  50. package/dist/dom-component.js.map +1 -0
  51. package/dist/expo-image.d.ts +33 -0
  52. package/dist/expo-image.js +57 -0
  53. package/dist/expo-image.js.map +1 -0
  54. package/dist/expo-ui-components.d.ts +327 -0
  55. package/dist/expo-ui-components.js +707 -0
  56. package/dist/expo-ui-components.js.map +1 -0
  57. package/dist/expo-ui.d.ts +46 -0
  58. package/dist/expo-ui.js +128 -0
  59. package/dist/expo-ui.js.map +1 -0
  60. package/dist/file-system.d.ts +63 -0
  61. package/dist/file-system.js +67 -0
  62. package/dist/file-system.js.map +1 -0
  63. package/dist/fonts.d.ts +90 -0
  64. package/dist/fonts.js +118 -0
  65. package/dist/fonts.js.map +1 -0
  66. package/dist/glass.d.ts +33 -0
  67. package/dist/glass.js +72 -0
  68. package/dist/glass.js.map +1 -0
  69. package/dist/haptics.d.ts +49 -0
  70. package/dist/haptics.js +64 -0
  71. package/dist/haptics.js.map +1 -0
  72. package/dist/image-editor.d.ts +62 -0
  73. package/dist/image-editor.js +101 -0
  74. package/dist/image-editor.js.map +1 -0
  75. package/dist/image-picker.d.ts +49 -0
  76. package/dist/image-picker.js +58 -0
  77. package/dist/image-picker.js.map +1 -0
  78. package/dist/index.d.ts +20 -0
  79. package/dist/index.js +21 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/keep-awake.d.ts +39 -0
  82. package/dist/keep-awake.js +80 -0
  83. package/dist/keep-awake.js.map +1 -0
  84. package/dist/language-model.d.ts +129 -0
  85. package/dist/language-model.js +225 -0
  86. package/dist/language-model.js.map +1 -0
  87. package/dist/locale.d.ts +51 -0
  88. package/dist/locale.js +78 -0
  89. package/dist/locale.js.map +1 -0
  90. package/dist/location.d.ts +68 -0
  91. package/dist/location.js +83 -0
  92. package/dist/location.js.map +1 -0
  93. package/dist/map-view.d.ts +203 -0
  94. package/dist/map-view.js +184 -0
  95. package/dist/map-view.js.map +1 -0
  96. package/dist/media-library.d.ts +103 -0
  97. package/dist/media-library.js +160 -0
  98. package/dist/media-library.js.map +1 -0
  99. package/dist/native-state.d.ts +22 -0
  100. package/dist/native-state.js +43 -0
  101. package/dist/native-state.js.map +1 -0
  102. package/dist/native.d.ts +42 -0
  103. package/dist/native.js +73 -0
  104. package/dist/native.js.map +1 -0
  105. package/dist/network.d.ts +35 -0
  106. package/dist/network.js +60 -0
  107. package/dist/network.js.map +1 -0
  108. package/dist/notifications.d.ts +175 -0
  109. package/dist/notifications.js +296 -0
  110. package/dist/notifications.js.map +1 -0
  111. package/dist/observed.d.ts +37 -0
  112. package/dist/observed.js +55 -0
  113. package/dist/observed.js.map +1 -0
  114. package/dist/orientation.d.ts +35 -0
  115. package/dist/orientation.js +78 -0
  116. package/dist/orientation.js.map +1 -0
  117. package/dist/permissions.d.ts +54 -0
  118. package/dist/permissions.js +72 -0
  119. package/dist/permissions.js.map +1 -0
  120. package/dist/player.d.ts +92 -0
  121. package/dist/player.js +141 -0
  122. package/dist/player.js.map +1 -0
  123. package/dist/register-expo-view.d.ts +55 -0
  124. package/dist/register-expo-view.js +110 -0
  125. package/dist/register-expo-view.js.map +1 -0
  126. package/dist/screen-capture.d.ts +58 -0
  127. package/dist/screen-capture.js +78 -0
  128. package/dist/screen-capture.js.map +1 -0
  129. package/dist/segmented-control.d.ts +32 -0
  130. package/dist/segmented-control.js +55 -0
  131. package/dist/segmented-control.js.map +1 -0
  132. package/dist/sensors.d.ts +85 -0
  133. package/dist/sensors.js +115 -0
  134. package/dist/sensors.js.map +1 -0
  135. package/dist/splash-screen.d.ts +73 -0
  136. package/dist/splash-screen.js +115 -0
  137. package/dist/splash-screen.js.map +1 -0
  138. package/dist/store-review.d.ts +43 -0
  139. package/dist/store-review.js +52 -0
  140. package/dist/store-review.js.map +1 -0
  141. package/dist/store.d.ts +108 -0
  142. package/dist/store.js +247 -0
  143. package/dist/store.js.map +1 -0
  144. package/dist/symbol.d.ts +36 -0
  145. package/dist/symbol.js +69 -0
  146. package/dist/symbol.js.map +1 -0
  147. package/dist/tracking.d.ts +45 -0
  148. package/dist/tracking.js +54 -0
  149. package/dist/tracking.js.map +1 -0
  150. package/dist/transforms.d.ts +2 -0
  151. package/dist/transforms.js +13 -0
  152. package/dist/transforms.js.map +1 -0
  153. package/dist/updates.d.ts +61 -0
  154. package/dist/updates.js +97 -0
  155. package/dist/updates.js.map +1 -0
  156. package/package.json +397 -3
@@ -0,0 +1,139 @@
1
+ /**
2
+ * `<dom-component>`: an Angular component rendered by a browser - DOM, CSS, anything a browser
3
+ * runs - in a web view inside a native screen, with its inputs and outputs bound from the app's
4
+ * template. Expo calls this a DOM component; it is not the Web Components standard.
5
+ *
6
+ * ```ts
7
+ * // web/note.ts: an ordinary Angular component for the browser, in the app's own source
8
+ * 'use dom';
9
+ * @Component({ selector: 'app-note', template: '<textarea ...></textarea>', styles: [...] })
10
+ * export class Note {
11
+ * readonly label = input('');
12
+ * readonly sent = output<string>();
13
+ * }
14
+ * export default mountInWebView(Note); // from '@ng-native/web/web-view'
15
+ *
16
+ * // a native screen
17
+ * import note from './web/note.ts';
18
+ * <dom-component [src]="note" class="flex-1"
19
+ * [inputs]="{ label: title() }" [outputs]="{ sent: save }" />
20
+ * ```
21
+ *
22
+ * The component runs in Expo's own web view (`@expo/dom-webview`, which `expo` already installs),
23
+ * so it is a separate JavaScript runtime from the app and only JSON crosses. It is shipped the way
24
+ * Expo ships its `'use dom'` components: the import is a reference to a page that Expo's dev server
25
+ * serves in development and `expo export:embed` bundles into the app for a release build (see
26
+ * `@ng-native/metro`'s `dom-component.cjs`), and the page is found where Expo finds its own.
27
+ *
28
+ * - **`inputs`** go into the page before it loads, and a changed value is sent to it afterwards
29
+ * without reloading. Anything sent before the page is ready is sent again once it is.
30
+ * - **`outputs`** map the component's outputs, by public name, to handlers. A name the component
31
+ * has no output for is an error naming the ones it does have, as `<ng-native-island>`'s is.
32
+ * - **Errors** the page throws reach the app's `ErrorHandler`.
33
+ */
34
+ import { Component, ElementRef, InjectionToken, computed, effect, inject, input, untracked, } from '@angular/core';
35
+ import { Engine } from '@ng-native/fabric';
36
+ import { optional } from "./native.js";
37
+ import { registerExpoView } from "./register-expo-view.js";
38
+ import * as i0 from "@angular/core";
39
+ /** The element is this package's, so it needs no `registerExpoViews` call of its own. */
40
+ registerExpoView('dom-component', 'ExpoDomWebViewModule');
41
+ export class DomComponent {
42
+ /** Overridden in a test to load pages without a dev server. */
43
+ static SOURCE = new InjectionToken('angular-native.domComponentSource', {
44
+ factory: () => {
45
+ // Expo's own resolution, so a page is found wherever Expo would look for a DOM
46
+ // component's: the dev server, the app's `www.bundle`, or a downloaded update.
47
+ const base = optional(() => require('expo/src/dom/base'));
48
+ const core = optional(() => require('expo-modules-core'));
49
+ const module = core?.requireOptionalNativeModule('ExpoDomWebViewModule');
50
+ return {
51
+ baseUrl: optional(() => base?.getBaseURL() ?? null),
52
+ functions: module?.ViewPrototypes?.['ExpoDomWebViewModule'] ?? null,
53
+ };
54
+ },
55
+ });
56
+ native = inject(DomComponent.SOURCE);
57
+ engine = inject(Engine);
58
+ node = inject(ElementRef).nativeElement;
59
+ ready = false;
60
+ /** The DOM component, as imported: `import note from './web/note.ts'`. */
61
+ src = input.required(/* @ts-ignore */
62
+ ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
63
+ /** Its inputs, by public name. JSON only: this crosses into another runtime. */
64
+ inputs = input({}, /* @ts-ignore */
65
+ ...(ngDevMode ? [{ debugName: "inputs" }] : /* istanbul ignore next */ []));
66
+ /** Handlers for its outputs, by public name. */
67
+ outputs = input({}, /* @ts-ignore */
68
+ ...(ngDevMode ? [{ debugName: "outputs" }] : /* istanbul ignore next */ []));
69
+ debuggable = typeof __DEV__ === 'undefined' || __DEV__;
70
+ source = computed(() => {
71
+ const { domComponent } = this.src();
72
+ return this.native.baseUrl === null ? null : { uri: `${this.native.baseUrl}/${domComponent}` };
73
+ }, /* @ts-ignore */
74
+ ...(ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []));
75
+ /** The file's name for an error message: the dev page names it, a release page is a hash. */
76
+ name = computed(() => this.src().domComponent.split('?')[0], /* @ts-ignore */
77
+ ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
78
+ /**
79
+ * What the page reads before it loads. The inputs are read untracked: a change to this prop
80
+ * reloads the page, so a changed input is sent to the running page instead.
81
+ */
82
+ page = computed(() => {
83
+ this.src();
84
+ return JSON.stringify({ inputs: untracked(this.inputs) });
85
+ }, /* @ts-ignore */
86
+ ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
87
+ constructor() {
88
+ effect(() => {
89
+ const inputs = this.inputs();
90
+ if (this.ready)
91
+ untracked(() => this.send(inputs));
92
+ });
93
+ }
94
+ receive(event) {
95
+ const message = JSON.parse(event.nativeEvent.data);
96
+ if (message.type === 'ready') {
97
+ this.checkOutputs(message.outputs);
98
+ this.ready = true;
99
+ this.send(this.inputs());
100
+ }
101
+ else if (message.type === 'output') {
102
+ this.outputs()[message.name]?.(message.value);
103
+ }
104
+ else if (message.type === 'error') {
105
+ throw new Error(`[angular-native] <dom-component> ${this.name()}: ${message.message}`);
106
+ }
107
+ }
108
+ checkOutputs(declared) {
109
+ for (const name of Object.keys(this.outputs())) {
110
+ if (!declared.includes(name)) {
111
+ throw new Error(`[angular-native] <dom-component>: ${this.name()} has no output '${name}' ` +
112
+ `(its outputs: ${declared.join(', ') || 'none'}).`);
113
+ }
114
+ }
115
+ }
116
+ send(inputs) {
117
+ const nativeTag = this.engine.tagOf(this.node);
118
+ if (!this.native.functions || nativeTag === null)
119
+ return;
120
+ const message = JSON.stringify({ type: 'inputs', inputs });
121
+ void this.native.functions.injectJavaScript.call({ nativeTag }, `window.__ngNative && window.__ngNative.receive(${message}); true;`);
122
+ }
123
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: DomComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
124
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: DomComponent, isStandalone: true, selector: "dom-component", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: true, transformFunction: null }, inputs: { classPropertyName: "inputs", publicName: "inputs", isSignal: true, isRequired: false, transformFunction: null }, outputs: { classPropertyName: "outputs", publicName: "outputs", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "message": "receive($event)" }, properties: { "source": "source()", "injectedJavaScriptObject": "page()", "webviewDebuggingEnabled": "debuggable" } }, ngImport: i0, template: '', isInline: true });
125
+ }
126
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: DomComponent, decorators: [{
127
+ type: Component,
128
+ args: [{
129
+ selector: 'dom-component',
130
+ template: '',
131
+ host: {
132
+ '[source]': 'source()',
133
+ '[injectedJavaScriptObject]': 'page()',
134
+ '[webviewDebuggingEnabled]': 'debuggable',
135
+ '(message)': 'receive($event)',
136
+ },
137
+ }]
138
+ }], ctorParameters: () => [], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: true }] }], inputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputs", required: false }] }], outputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputs", required: false }] }] } });
139
+ //# sourceMappingURL=dom-component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-component.js","sourceRoot":"","sources":["../src/dom-component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `<dom-component>`: an Angular component rendered by a browser - DOM, CSS, anything a browser\n * runs - in a web view inside a native screen, with its inputs and outputs bound from the app's\n * template. Expo calls this a DOM component; it is not the Web Components standard.\n *\n * ```ts\n * // web/note.ts: an ordinary Angular component for the browser, in the app's own source\n * 'use dom';\n * @Component({ selector: 'app-note', template: '<textarea ...></textarea>', styles: [...] })\n * export class Note {\n * readonly label = input('');\n * readonly sent = output<string>();\n * }\n * export default mountInWebView(Note); // from '@ng-native/web/web-view'\n *\n * // a native screen\n * import note from './web/note.ts';\n * <dom-component [src]=\"note\" class=\"flex-1\"\n * [inputs]=\"{ label: title() }\" [outputs]=\"{ sent: save }\" />\n * ```\n *\n * The component runs in Expo's own web view (`@expo/dom-webview`, which `expo` already installs),\n * so it is a separate JavaScript runtime from the app and only JSON crosses. It is shipped the way\n * Expo ships its `'use dom'` components: the import is a reference to a page that Expo's dev server\n * serves in development and `expo export:embed` bundles into the app for a release build (see\n * `@ng-native/metro`'s `dom-component.cjs`), and the page is found where Expo finds its own.\n *\n * - **`inputs`** go into the page before it loads, and a changed value is sent to it afterwards\n * without reloading. Anything sent before the page is ready is sent again once it is.\n * - **`outputs`** map the component's outputs, by public name, to handlers. A name the component\n * has no output for is an error naming the ones it does have, as `<ng-native-island>`'s is.\n * - **Errors** the page throws reach the app's `ErrorHandler`.\n */\nimport {\n Component,\n ElementRef,\n InjectionToken,\n computed,\n effect,\n inject,\n input,\n untracked,\n} from '@angular/core';\nimport { Engine, type EngineNode, type NativeSyntheticEvent } from '@ng-native/fabric';\nimport { optional } from './native.ts';\nimport { registerExpoView } from './register-expo-view.ts';\n\n/** The element is this package's, so it needs no `registerExpoViews` call of its own. */\nregisterExpoView('dom-component', 'ExpoDomWebViewModule');\n\n/** A handler for one of the DOM component's outputs. */\nexport type DomComponentOutputHandler = (value: never) => void;\n\n/** The functions Expo's web view defines on its view, called with the view's tag as `this`. */\nexport interface WebViewFunctions {\n injectJavaScript(this: { nativeTag: number }, script: string): Promise<void>;\n}\n\n/** Where the pages are, and how to reach the view once it is on screen. */\nexport interface DomComponentSource {\n /** Where Expo keeps DOM components' pages: the dev server, `www.bundle`, or an update. */\n readonly baseUrl: string | null;\n readonly functions: WebViewFunctions | null;\n}\n\n/** What native code gets for `import note from './web/note.ts'`. */\nexport interface DomComponentReference {\n readonly domComponent: string;\n}\n\ntype PageMessage =\n | { type: 'ready'; outputs: string[] }\n | { type: 'output'; name: string; value: unknown }\n | { type: 'error'; message: string };\n\n@Component({\n selector: 'dom-component',\n template: '',\n host: {\n '[source]': 'source()',\n '[injectedJavaScriptObject]': 'page()',\n '[webviewDebuggingEnabled]': 'debuggable',\n '(message)': 'receive($event)',\n },\n})\nexport class DomComponent {\n /** Overridden in a test to load pages without a dev server. */\n static readonly SOURCE = new InjectionToken<DomComponentSource>(\n 'angular-native.domComponentSource',\n {\n factory: () => {\n // Expo's own resolution, so a page is found wherever Expo would look for a DOM\n // component's: the dev server, the app's `www.bundle`, or a downloaded update.\n const base = optional(() => require('expo/src/dom/base') as { getBaseURL(): string });\n const core = optional(\n () => require('expo-modules-core') as typeof import('expo-modules-core'),\n );\n const module = core?.requireOptionalNativeModule<{\n ViewPrototypes?: Record<string, WebViewFunctions>;\n }>('ExpoDomWebViewModule');\n return {\n baseUrl: optional(() => base?.getBaseURL() ?? null),\n functions: module?.ViewPrototypes?.['ExpoDomWebViewModule'] ?? null,\n };\n },\n },\n );\n\n private readonly native = inject(DomComponent.SOURCE);\n private readonly engine = inject(Engine);\n private readonly node = inject<ElementRef<EngineNode>>(ElementRef).nativeElement;\n private ready = false;\n\n /** The DOM component, as imported: `import note from './web/note.ts'`. */\n readonly src = input.required<DomComponentReference>();\n /** Its inputs, by public name. JSON only: this crosses into another runtime. */\n readonly inputs = input<Readonly<Record<string, unknown>>>({});\n /** Handlers for its outputs, by public name. */\n readonly outputs = input<Readonly<Record<string, DomComponentOutputHandler>>>({});\n\n protected readonly debuggable = typeof __DEV__ === 'undefined' || __DEV__;\n\n protected readonly source = computed(() => {\n const { domComponent } = this.src();\n return this.native.baseUrl === null ? null : { uri: `${this.native.baseUrl}/${domComponent}` };\n });\n\n /** The file's name for an error message: the dev page names it, a release page is a hash. */\n private readonly name = computed(() => this.src().domComponent.split('?')[0]!);\n\n /**\n * What the page reads before it loads. The inputs are read untracked: a change to this prop\n * reloads the page, so a changed input is sent to the running page instead.\n */\n protected readonly page = computed(() => {\n this.src();\n return JSON.stringify({ inputs: untracked(this.inputs) });\n });\n\n constructor() {\n effect(() => {\n const inputs = this.inputs();\n if (this.ready) untracked(() => this.send(inputs));\n });\n }\n\n protected receive(event: NativeSyntheticEvent<{ data: string }>): void {\n const message = JSON.parse(event.nativeEvent.data) as PageMessage;\n if (message.type === 'ready') {\n this.checkOutputs(message.outputs);\n this.ready = true;\n this.send(this.inputs());\n } else if (message.type === 'output') {\n this.outputs()[message.name]?.(message.value as never);\n } else if (message.type === 'error') {\n throw new Error(`[angular-native] <dom-component> ${this.name()}: ${message.message}`);\n }\n }\n\n private checkOutputs(declared: readonly string[]): void {\n for (const name of Object.keys(this.outputs())) {\n if (!declared.includes(name)) {\n throw new Error(\n `[angular-native] <dom-component>: ${this.name()} has no output '${name}' ` +\n `(its outputs: ${declared.join(', ') || 'none'}).`,\n );\n }\n }\n }\n\n private send(inputs: Readonly<Record<string, unknown>>): void {\n const nativeTag = this.engine.tagOf(this.node);\n if (!this.native.functions || nativeTag === null) return;\n const message = JSON.stringify({ type: 'inputs', inputs });\n void this.native.functions.injectJavaScript.call(\n { nativeTag },\n `window.__ngNative && window.__ngNative.receive(${message}); true;`,\n );\n }\n}\n\ndeclare const __DEV__: boolean | undefined;\n"]}
@@ -0,0 +1,33 @@
1
+ import type { NativeSyntheticEvent } from '@ng-native/fabric';
2
+ import * as i0 from "@angular/core";
3
+ /** One image `source` entry, as `expo-image` passes them to its view. */
4
+ export interface ExpoImageSource {
5
+ readonly uri?: string;
6
+ readonly width?: number;
7
+ readonly height?: number;
8
+ readonly headers?: Readonly<Record<string, string>>;
9
+ readonly cacheKey?: string;
10
+ }
11
+ export type ExpoImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
12
+ export declare class ExpoImage {
13
+ readonly source: import("@angular/core").InputSignal<number | ExpoImageSource | readonly ExpoImageSource[] | undefined>;
14
+ readonly placeholder: import("@angular/core").InputSignal<number | ExpoImageSource | readonly ExpoImageSource[] | undefined>;
15
+ readonly contentFit: import("@angular/core").InputSignal<ExpoImageContentFit | undefined>;
16
+ readonly contentPosition: import("@angular/core").InputSignal<string | Readonly<Record<string, string | number>> | undefined>;
17
+ readonly transition: import("@angular/core").InputSignal<number | {
18
+ readonly duration?: number;
19
+ readonly effect?: string;
20
+ } | undefined>;
21
+ readonly blurRadius: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
22
+ readonly tintColor: import("@angular/core").InputSignal<string | undefined>;
23
+ readonly cachePolicy: import("@angular/core").InputSignal<"none" | "disk" | "memory" | "memory-disk" | undefined>;
24
+ readonly priority: import("@angular/core").InputSignal<"low" | "normal" | "high" | undefined>;
25
+ readonly recyclingKey: import("@angular/core").InputSignal<string | undefined>;
26
+ readonly accessibilityLabel: import("@angular/core").InputSignal<string | undefined>;
27
+ readonly load: import("@angular/core").OutputEmitterRef<NativeSyntheticEvent<Record<string, unknown>>>;
28
+ readonly error: import("@angular/core").OutputEmitterRef<NativeSyntheticEvent<{
29
+ readonly error: string;
30
+ }>>;
31
+ static ɵfac: i0.ɵɵFactoryDeclaration<ExpoImage, never>;
32
+ static ɵcmp: i0.ɵɵComponentDeclaration<ExpoImage, "expo-image", never, { "source": { "alias": "source"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "contentFit": { "alias": "contentFit"; "required": false; "isSignal": true; }; "contentPosition": { "alias": "contentPosition"; "required": false; "isSignal": true; }; "transition": { "alias": "transition"; "required": false; "isSignal": true; }; "blurRadius": { "alias": "blurRadius"; "required": false; "isSignal": true; }; "tintColor": { "alias": "tintColor"; "required": false; "isSignal": true; }; "cachePolicy": { "alias": "cachePolicy"; "required": false; "isSignal": true; }; "priority": { "alias": "priority"; "required": false; "isSignal": true; }; "recyclingKey": { "alias": "recyclingKey"; "required": false; "isSignal": true; }; "accessibilityLabel": { "alias": "accessibilityLabel"; "required": false; "isSignal": true; }; }, { "load": "load"; "error": "error"; }, never, never, true, never>;
33
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * `<expo-image>`, typed: `expo-image`'s view, registered by name with
3
+ * `registerExpoView('expo-image', 'ExpoImage')`, with its props as inputs so a template is
4
+ * checked against them. Each goes straight to the view; `source` is the array the React
5
+ * component would hand down.
6
+ */
7
+ import { Component, input, output } from '@angular/core';
8
+ import { optionalNumber } from "./transforms.js";
9
+ import * as i0 from "@angular/core";
10
+ export class ExpoImage {
11
+ source = input(/* @ts-ignore */
12
+ ...(ngDevMode ? [undefined, { debugName: "source" }] : /* istanbul ignore next */ []));
13
+ placeholder = input(/* @ts-ignore */
14
+ ...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
15
+ contentFit = input(/* @ts-ignore */
16
+ ...(ngDevMode ? [undefined, { debugName: "contentFit" }] : /* istanbul ignore next */ []));
17
+ contentPosition = input(/* @ts-ignore */
18
+ ...(ngDevMode ? [undefined, { debugName: "contentPosition" }] : /* istanbul ignore next */ []));
19
+ transition = input(/* @ts-ignore */
20
+ ...(ngDevMode ? [undefined, { debugName: "transition" }] : /* istanbul ignore next */ []));
21
+ blurRadius = input(undefined, { ...(ngDevMode ? { debugName: "blurRadius" } : /* istanbul ignore next */ {}), transform: optionalNumber });
22
+ tintColor = input(/* @ts-ignore */
23
+ ...(ngDevMode ? [undefined, { debugName: "tintColor" }] : /* istanbul ignore next */ []));
24
+ cachePolicy = input(/* @ts-ignore */
25
+ ...(ngDevMode ? [undefined, { debugName: "cachePolicy" }] : /* istanbul ignore next */ []));
26
+ priority = input(/* @ts-ignore */
27
+ ...(ngDevMode ? [undefined, { debugName: "priority" }] : /* istanbul ignore next */ []));
28
+ recyclingKey = input(/* @ts-ignore */
29
+ ...(ngDevMode ? [undefined, { debugName: "recyclingKey" }] : /* istanbul ignore next */ []));
30
+ accessibilityLabel = input(/* @ts-ignore */
31
+ ...(ngDevMode ? [undefined, { debugName: "accessibilityLabel" }] : /* istanbul ignore next */ []));
32
+ load = output();
33
+ error = output();
34
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: ExpoImage, deps: [], target: i0.ɵɵFactoryTarget.Component });
35
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: ExpoImage, isStandalone: true, selector: "expo-image", inputs: { source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, contentFit: { classPropertyName: "contentFit", publicName: "contentFit", isSignal: true, isRequired: false, transformFunction: null }, contentPosition: { classPropertyName: "contentPosition", publicName: "contentPosition", isSignal: true, isRequired: false, transformFunction: null }, transition: { classPropertyName: "transition", publicName: "transition", isSignal: true, isRequired: false, transformFunction: null }, blurRadius: { classPropertyName: "blurRadius", publicName: "blurRadius", isSignal: true, isRequired: false, transformFunction: null }, tintColor: { classPropertyName: "tintColor", publicName: "tintColor", isSignal: true, isRequired: false, transformFunction: null }, cachePolicy: { classPropertyName: "cachePolicy", publicName: "cachePolicy", isSignal: true, isRequired: false, transformFunction: null }, priority: { classPropertyName: "priority", publicName: "priority", isSignal: true, isRequired: false, transformFunction: null }, recyclingKey: { classPropertyName: "recyclingKey", publicName: "recyclingKey", isSignal: true, isRequired: false, transformFunction: null }, accessibilityLabel: { classPropertyName: "accessibilityLabel", publicName: "accessibilityLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { load: "load", error: "error" }, host: { properties: { "source": "source()", "placeholder": "placeholder()", "contentFit": "contentFit()", "contentPosition": "contentPosition()", "transition": "transition()", "blurRadius": "blurRadius()", "tintColor": "tintColor()", "cachePolicy": "cachePolicy()", "priority": "priority()", "recyclingKey": "recyclingKey()", "accessibilityLabel": "accessibilityLabel()" } }, ngImport: i0, template: '', isInline: true });
36
+ }
37
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: ExpoImage, decorators: [{
38
+ type: Component,
39
+ args: [{
40
+ selector: 'expo-image',
41
+ template: '',
42
+ host: {
43
+ '[source]': 'source()',
44
+ '[placeholder]': 'placeholder()',
45
+ '[contentFit]': 'contentFit()',
46
+ '[contentPosition]': 'contentPosition()',
47
+ '[transition]': 'transition()',
48
+ '[blurRadius]': 'blurRadius()',
49
+ '[tintColor]': 'tintColor()',
50
+ '[cachePolicy]': 'cachePolicy()',
51
+ '[priority]': 'priority()',
52
+ '[recyclingKey]': 'recyclingKey()',
53
+ '[accessibilityLabel]': 'accessibilityLabel()',
54
+ },
55
+ }]
56
+ }], propDecorators: { source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], contentFit: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentFit", required: false }] }], contentPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentPosition", required: false }] }], transition: [{ type: i0.Input, args: [{ isSignal: true, alias: "transition", required: false }] }], blurRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "blurRadius", required: false }] }], tintColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "tintColor", required: false }] }], cachePolicy: [{ type: i0.Input, args: [{ isSignal: true, alias: "cachePolicy", required: false }] }], priority: [{ type: i0.Input, args: [{ isSignal: true, alias: "priority", required: false }] }], recyclingKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "recyclingKey", required: false }] }], accessibilityLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "accessibilityLabel", required: false }] }], load: [{ type: i0.Output, args: ["load"] }], error: [{ type: i0.Output, args: ["error"] }] } });
57
+ //# sourceMappingURL=expo-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expo-image.js","sourceRoot":"","sources":["../src/expo-image.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;;AA8BjD,MAAM,OAAO,SAAS;IACX,MAAM,GAAG,KAAK;0FAAyD,CAAC;IACxE,WAAW,GAAG,KAAK;+FAAyD,CAAC;IAC7E,UAAU,GAAG,KAAK;8FAAuB,CAAC;IAC1C,eAAe,GAAG,KAAK;mGAAsD,CAAC;IAC9E,UAAU,GAAG,KAAK;8FAAqE,CAAC;IACxF,UAAU,GAAG,KAAK,CAAS,SAAS,kFAAI,SAAS,EAAE,cAAc,GAAG,CAAC;IACrE,SAAS,GAAG,KAAK;6FAAU,CAAC;IAC5B,WAAW,GAAG,KAAK;+FAA8C,CAAC;IAClE,QAAQ,GAAG,KAAK;4FAA6B,CAAC;IAC9C,YAAY,GAAG,KAAK;gGAAU,CAAC;IAC/B,kBAAkB,GAAG,KAAK;sGAAU,CAAC;IACrC,IAAI,GAAG,MAAM,EAAiD,CAAC;IAC/D,KAAK,GAAG,MAAM,EAAoD,CAAC;uGAbjE,SAAS;2FAAT,SAAS,g+DAfV,EAAE;;2FAeD,SAAS;kBAjBrB,SAAS;mBAAC;oBACT,QAAQ,EAAE,YAAY;oBACtB,QAAQ,EAAE,EAAE;oBACZ,IAAI,EAAE;wBACJ,UAAU,EAAE,UAAU;wBACtB,eAAe,EAAE,eAAe;wBAChC,cAAc,EAAE,cAAc;wBAC9B,mBAAmB,EAAE,mBAAmB;wBACxC,cAAc,EAAE,cAAc;wBAC9B,cAAc,EAAE,cAAc;wBAC9B,aAAa,EAAE,aAAa;wBAC5B,eAAe,EAAE,eAAe;wBAChC,YAAY,EAAE,YAAY;wBAC1B,gBAAgB,EAAE,gBAAgB;wBAClC,sBAAsB,EAAE,sBAAsB;qBAC/C;iBACF","sourcesContent":["/**\n * `<expo-image>`, typed: `expo-image`'s view, registered by name with\n * `registerExpoView('expo-image', 'ExpoImage')`, with its props as inputs so a template is\n * checked against them. Each goes straight to the view; `source` is the array the React\n * component would hand down.\n */\nimport { Component, input, output } from '@angular/core';\nimport type { NativeSyntheticEvent } from '@ng-native/fabric';\nimport { optionalNumber } from './transforms.ts';\n\n/** One image `source` entry, as `expo-image` passes them to its view. */\nexport interface ExpoImageSource {\n readonly uri?: string;\n readonly width?: number;\n readonly height?: number;\n readonly headers?: Readonly<Record<string, string>>;\n readonly cacheKey?: string;\n}\n\nexport type ExpoImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';\n\n@Component({\n selector: 'expo-image',\n template: '',\n host: {\n '[source]': 'source()',\n '[placeholder]': 'placeholder()',\n '[contentFit]': 'contentFit()',\n '[contentPosition]': 'contentPosition()',\n '[transition]': 'transition()',\n '[blurRadius]': 'blurRadius()',\n '[tintColor]': 'tintColor()',\n '[cachePolicy]': 'cachePolicy()',\n '[priority]': 'priority()',\n '[recyclingKey]': 'recyclingKey()',\n '[accessibilityLabel]': 'accessibilityLabel()',\n },\n})\nexport class ExpoImage {\n readonly source = input<readonly ExpoImageSource[] | ExpoImageSource | number>();\n readonly placeholder = input<readonly ExpoImageSource[] | ExpoImageSource | number>();\n readonly contentFit = input<ExpoImageContentFit>();\n readonly contentPosition = input<string | Readonly<Record<string, number | string>>>();\n readonly transition = input<number | { readonly duration?: number; readonly effect?: string }>();\n readonly blurRadius = input<number>(undefined, { transform: optionalNumber });\n readonly tintColor = input<string>();\n readonly cachePolicy = input<'none' | 'disk' | 'memory' | 'memory-disk'>();\n readonly priority = input<'low' | 'normal' | 'high'>();\n readonly recyclingKey = input<string>();\n readonly accessibilityLabel = input<string>();\n readonly load = output<NativeSyntheticEvent<Record<string, unknown>>>();\n readonly error = output<NativeSyntheticEvent<{ readonly error: string }>>();\n}\n"]}