voltra 1.0.0-rc.1 → 1.0.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.
@@ -0,0 +1,132 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ - Demonstrating empathy and kindness toward other people
21
+ - Being respectful of differing opinions, viewpoints, and experiences
22
+ - Giving and gracefully accepting constructive feedback
23
+ - Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ - Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ - The use of sexualized language or imagery, and sexual attention or advances of
31
+ any kind
32
+ - Trolling, insulting or derogatory comments, and personal or political attacks
33
+ - Public or private harassment
34
+ - Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ - Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ [INSERT CONTACT METHOD].
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series of
86
+ actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or permanent
93
+ ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within the
113
+ community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.1, available at
119
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120
+
121
+ Community Impact Guidelines were inspired by
122
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
+
124
+ For answers to common questions about this code of conduct, see the FAQ at
125
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126
+ [https://www.contributor-covenant.org/translations][translations].
127
+
128
+ [homepage]: https://www.contributor-covenant.org
129
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130
+ [Mozilla CoC]: https://github.com/mozilla/diversity
131
+ [FAQ]: https://www.contributor-covenant.org/faq
132
+ [translations]: https://www.contributor-covenant.org/translations
@@ -0,0 +1,235 @@
1
+ # Contributing to Voltra
2
+
3
+ ## Before you start any work
4
+
5
+ Please open an issue before starting to work on a new feature or a fix to a bug you encountered. This will prevent you from wasting your time on a feature that's not going to be merged, because for instance it's out of scope. If there is an existing issue present for the matter you want to work on, make sure to post a comment saying you are going to work on it. This will make sure there will be only one person working on a given issue.
6
+
7
+ ## Development process
8
+
9
+ All work on Voltra happens directly on GitHub. Contributors send pull requests which go through the review process.
10
+
11
+ > **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
12
+
13
+ 1. Fork the repo and create your branch from `main` (a guide on [how to fork a repository](https://help.github.com/articles/fork-a-repo/)).
14
+ 2. Run `npm install` to install all required dependencies.
15
+ 3. Build the plugin: `npx tsc -p plugin/tsconfig.json`.
16
+ 4. Now you are ready to make changes.
17
+
18
+ ## Architecture overview
19
+
20
+ ### JS/TS code structure
21
+
22
+ The JavaScript/TypeScript code has **two separate entry points** that must be maintained as independent boundaries:
23
+
24
+ - **Client entry (`src/index.ts`)**: React Native code that runs in the app. Exports JSX components, hooks, and the imperative API for managing Live Activities.
25
+ - **Server entry (`src/server.ts`)**: Node.js code for rendering Voltra components to string payloads. Used for server-side rendering and push notification payloads.
26
+
27
+ ⚠️ **Important**: These two entry points must remain separate. Client code should not import server-only dependencies, and server code should not import React Native-specific modules.
28
+
29
+ ### Expo config plugin (`plugin/`)
30
+
31
+ The Expo plugin in `plugin/src/` handles all Xcode project setup during `expo prebuild`:
32
+
33
+ 1. **Creates the widget extension target** with proper build settings
34
+ 2. **Copies template files** from `ios-files/` (widget bundle, assets, Info.plist) into the extension target
35
+ 3. **Configures CocoaPods** to include the `VoltraWidget` subspec in the extension target
36
+ 4. **Sets up entitlements** for App Groups (optional, for event forwarding)
37
+ 5. **Configures push notifications** (optional)
38
+
39
+ ### Swift code distribution (`ios/`)
40
+
41
+ Voltra's Swift code lives in `ios/` and is distributed as a **CocoaPods package** with multiple subspecs:
42
+
43
+ ```ruby
44
+ # From ios/Voltra.podspec
45
+ s.subspec 'Core' do |ss|
46
+ # React Native bridge module (auto-linked by Expo)
47
+ ss.source_files = ["app/**/*.swift", "shared/**/*.swift", "ui/**/*.swift"]
48
+ end
49
+
50
+ s.subspec 'Widget' do |ss|
51
+ # Widget extension code (used by Live Activity target)
52
+ ss.source_files = ["shared/**/*.swift", "ui/**/*.swift", "target/**/*.swift"]
53
+ end
54
+ ```
55
+
56
+ - **`Core` subspec**: Contains the React Native module (`app/`), shared code (`shared/`), and UI components (`ui/`). Auto-linked by Expo in the main app.
57
+ - **`Widget` subspec**: Contains shared code, UI components, and widget-specific files (`target/`). Used by the Live Activity extension target.
58
+
59
+ This separation ensures the widget extension doesn't include unnecessary React Native dependencies.
60
+
61
+ ### Template files (`ios-files/`)
62
+
63
+ Files in `ios-files/` are copied by the config plugin into the generated widget extension:
64
+
65
+ - `VoltraWidgetBundle.swift` — Widget bundle entry point
66
+ - `Assets.xcassets/` — Asset catalog for the extension
67
+ - `Info.plist` — Extension configuration
68
+
69
+ ## Props synchronization
70
+
71
+ Component props are kept in sync between TypeScript and Swift via a **custom code generator**. The single source of truth is:
72
+
73
+ ```
74
+ data/components.json
75
+ ```
76
+
77
+ This file defines all components, their parameters, types, and short names used for payload compression.
78
+
79
+ ### Running the generator
80
+
81
+ ```sh
82
+ npm run generate
83
+ ```
84
+
85
+ This generates:
86
+
87
+ - **TypeScript prop types**: `src/jsx/props/*.ts`
88
+ - **Swift parameter structs**: `ios/ui/Generated/Parameters/*.swift`
89
+ - **Component ID mappings**: `src/payload/component-ids.ts` and `ios/shared/ComponentTypeID.swift`
90
+ - **Short name mappings**: `src/payload/short-names.ts` and `ios/shared/ShortNames.swift`
91
+
92
+ ⚠️ **Important**: When adding new components or modifying props, always update `data/components.json` first, then run the generator. Do not manually edit generated files (marked with `.generated`).
93
+
94
+ ## Payload size budget
95
+
96
+ Live Activity payloads have strict size limits imposed by iOS. Voltra includes tests that track payload sizes for real-world examples.
97
+
98
+ ### How it works
99
+
100
+ The test in `src/__tests__/payload-size.node.test.tsx` renders example components and snapshots their compressed payload size:
101
+
102
+ ```typescript
103
+ it('BasicLiveActivityUI', async () => {
104
+ const size = await getPayloadSize({
105
+ lockScreen: <BasicLiveActivityUI />,
106
+ })
107
+ expect(size).toMatchSnapshot()
108
+ })
109
+ ```
110
+
111
+ ### When payload size changes
112
+
113
+ If your changes affect payload size, the tests will fail. This is intentional:
114
+
115
+ - **Size decreased?** Great! Run `npm test -- -u` to update snapshots and lock in the improvement.
116
+ - **Size increased?** Investigate carefully. Is the increase justified? Can it be optimized? Only update snapshots after confirming the increase is necessary.
117
+
118
+ ⚠️ **CI will block merging** if payload size snapshots are out of date. This ensures we don't accidentally regress payload efficiency.
119
+
120
+ ## Payload schema versioning
121
+
122
+ The payload schema has a version number to support forward compatibility. When the Swift code receives a payload with a newer version than it understands, it renders empty instead of crashing.
123
+
124
+ ### Version constants
125
+
126
+ The version is defined in two places that must stay in sync:
127
+
128
+ - **TypeScript**: `src/renderer/renderer.ts` → `VOLTRA_PAYLOAD_VERSION`
129
+ - **Swift**: `ios/shared/VoltraPayloadMigrator.swift` → `currentVersion`
130
+
131
+ ### When to increment the version
132
+
133
+ Increment the version when making **breaking changes** to the payload schema:
134
+
135
+ - Adding required fields that old Swift code wouldn't understand
136
+ - Changing the structure of existing fields
137
+ - Renaming keys in a way that breaks parsing
138
+
139
+ You do **not** need to increment for:
140
+
141
+ - Adding optional fields (old Swift code will ignore them)
142
+ - Bug fixes that don't change the schema
143
+ - Adding new component types (they render as `EmptyView` if unknown)
144
+
145
+ ### Adding migrations
146
+
147
+ When you increment the version, add a migration in Swift to upgrade old payloads:
148
+
149
+ 1. Increment `currentVersion` in both TypeScript and Swift
150
+ 2. Create a migration struct implementing `VoltraPayloadMigration`
151
+ 3. Register it in the `migrations` dictionary
152
+
153
+ ```swift
154
+ // Example: V1ToV2Migration.swift
155
+ struct V1ToV2Migration: VoltraPayloadMigration {
156
+ static let fromVersion = 1
157
+ static let toVersion = 2
158
+
159
+ static func migrate(_ json: JSONValue) throws -> JSONValue {
160
+ // Transform v1 payload to v2 format
161
+ // Update the version field
162
+ var result = json
163
+ result["v"] = .int(2)
164
+ return result
165
+ }
166
+ }
167
+
168
+ // In VoltraPayloadMigrator.swift:
169
+ private static let migrations: [Int: any VoltraPayloadMigration.Type] = [
170
+ 1: V1ToV2Migration.self,
171
+ ]
172
+ ```
173
+
174
+ This ensures users with older apps can still receive updates from newer servers.
175
+
176
+ ## Testing your changes
177
+
178
+ The `example/` directory contains an Expo app for testing changes.
179
+
180
+ ### Running the example app
181
+
182
+ ```sh
183
+ # 1) Build the plugin
184
+ npx tsc -p plugin/tsconfig.json
185
+
186
+ # 2) Install example dependencies
187
+ (cd example && npm install)
188
+
189
+ # 3) Prebuild for iOS
190
+ (cd example && npx expo prebuild -p ios)
191
+
192
+ # 4) Run on iOS
193
+ (cd example && npx expo run:ios)
194
+ ```
195
+
196
+ If iterating on the plugin, rebuild after each change in `plugin/src/`.
197
+
198
+ ### Running tests
199
+
200
+ Run the following checks before opening a pull request:
201
+
202
+ ```sh
203
+ # Linting
204
+ npm run lint:libOnly
205
+
206
+ # Type checking
207
+ npm run build
208
+
209
+ # Unit tests
210
+ npm test
211
+
212
+ # Format check
213
+ npm run format:check
214
+ ```
215
+
216
+ If formatting fails, run `npx prettier --write .` to fix it.
217
+
218
+ ## Creating a pull request
219
+
220
+ When you are ready to have your changes incorporated into the main codebase, open a pull request.
221
+
222
+ This repository follows [the Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/#summary). Please follow this pattern in your pull request titles. Keep in mind your commits will be squashed before merging and the title will be used as a commit title.
223
+
224
+ ### Pull request checklist
225
+
226
+ - [ ] Tests pass (`npm test`)
227
+ - [ ] Linting passes (`npm run lint:libOnly`)
228
+ - [ ] Formatting is correct (`npm run format:check`)
229
+ - [ ] If props changed, generator was run (`npm run generate`)
230
+ - [ ] If payload size changed, snapshots were intentionally updated
231
+ - [ ] Documentation updated if needed
232
+
233
+ ## License
234
+
235
+ By contributing to Voltra, you agree that your contributions will be licensed under its MIT license.
package/README.md CHANGED
@@ -84,13 +84,15 @@ export function OrderTracker({ orderId }: { orderId: string }) {
84
84
 
85
85
  **Note:** This module is intended for use on **iOS devices only**.
86
86
 
87
- ## Made with ❤️ at Callstack
87
+ ## Authors
88
88
 
89
- `voltra` is an open source project and will always remain free to use. If you think it's cool, please star it 🌟.
89
+ `voltra` is an open source collaboration between [Saúl Sharma](https://github.com/saul-sharma) and [Szymon Chmal](https://github.com/szymonchmal) at [Callstack][callstack-readme-with-love].
90
+
91
+ If you think it's cool, please star it 🌟. This project will always remain free to use.
90
92
 
91
93
  [Callstack][callstack-readme-with-love] is a group of React and React Native geeks, contact us at [hello@callstack.com](mailto:hello@callstack.com) if you need any help with these or just want to say hi!
92
94
 
93
- Like the project? ⚛️ [Join the team](https://callstack.com/careers/?utm_campaign=Senior_RN&utm_source=github&utm_medium=readme) who does amazing stuff for clients and drives React Native Open Source! 🔥
95
+ Like the project? ⚛️ [Join the Callstack team](https://callstack.com/careers/?utm_campaign=Senior_RN&utm_source=github&utm_medium=readme) who does amazing stuff for clients and drives React Native Open Source! 🔥
94
96
 
95
97
  [callstack-readme-with-love]: https://callstack.com/?utm_source=github.com&utm_medium=referral&utm_campaign=voltra&utm_term=readme-with-love
96
98
  [license-badge]: https://img.shields.io/npm/l/voltra?style=for-the-badge
@@ -1,3 +1,121 @@
1
- declare const _default: any;
2
- export default _default;
1
+ import type { EventSubscription, PreloadImageOptions, PreloadImagesResult, UpdateWidgetOptions } from './types.js';
2
+ /**
3
+ * Options for starting a Live Activity
4
+ */
5
+ export type StartVoltraOptions = {
6
+ /**
7
+ * Target type for the activity (used internally)
8
+ */
9
+ target?: string;
10
+ /**
11
+ * URL to open when the Live Activity is tapped.
12
+ */
13
+ deepLinkUrl?: string;
14
+ /**
15
+ * The ID/name of the Live Activity.
16
+ * Allows you to rebind to the same activity on app restart.
17
+ */
18
+ activityId?: string;
19
+ /**
20
+ * Unix timestamp in milliseconds
21
+ */
22
+ staleDate?: number;
23
+ /**
24
+ * Double value between 0.0 and 1.0, defaults to 0.0
25
+ */
26
+ relevanceScore?: number;
27
+ };
28
+ /**
29
+ * Options for updating a Live Activity
30
+ */
31
+ export type UpdateVoltraOptions = {
32
+ /**
33
+ * Unix timestamp in milliseconds
34
+ */
35
+ staleDate?: number;
36
+ /**
37
+ * Double value between 0.0 and 1.0, defaults to 0.0
38
+ */
39
+ relevanceScore?: number;
40
+ };
41
+ /**
42
+ * Options for ending a Live Activity
43
+ */
44
+ export type EndVoltraOptions = {
45
+ dismissalPolicy?: {
46
+ type: 'immediate' | 'after';
47
+ date?: number;
48
+ };
49
+ };
50
+ /**
51
+ * VoltraModule native module interface
52
+ */
53
+ export interface VoltraModuleSpec {
54
+ /**
55
+ * Start a new Live Activity
56
+ */
57
+ startLiveActivity(jsonString: string, options?: StartVoltraOptions): Promise<string>;
58
+ /**
59
+ * Update an existing Live Activity
60
+ */
61
+ updateLiveActivity(activityId: string, jsonString: string, options?: UpdateVoltraOptions): Promise<void>;
62
+ /**
63
+ * End a Live Activity
64
+ */
65
+ endLiveActivity(activityId: string, options?: EndVoltraOptions): Promise<void>;
66
+ /**
67
+ * End all active Live Activities
68
+ */
69
+ endAllLiveActivities(): Promise<void>;
70
+ /**
71
+ * Get the latest (most recently created) Voltra Live Activity ID, if any
72
+ */
73
+ getLatestVoltraActivityId(): Promise<string | null>;
74
+ /**
75
+ * List all running Voltra Live Activity IDs
76
+ */
77
+ listVoltraActivityIds(): Promise<string[]>;
78
+ /**
79
+ * Check if a Live Activity with the given name is currently active
80
+ */
81
+ isLiveActivityActive(activityName: string): boolean;
82
+ /**
83
+ * Check if the app was launched in the background (headless)
84
+ */
85
+ isHeadless(): boolean;
86
+ /**
87
+ * Preload images to App Group storage for use in Live Activities
88
+ */
89
+ preloadImages(images: PreloadImageOptions[]): Promise<PreloadImagesResult>;
90
+ /**
91
+ * Reload Live Activities to pick up preloaded images
92
+ */
93
+ reloadLiveActivities(activityNames?: string[] | null): Promise<void>;
94
+ /**
95
+ * Clear preloaded images from App Group storage
96
+ */
97
+ clearPreloadedImages(keys?: string[] | null): Promise<void>;
98
+ /**
99
+ * Update a home screen widget with new content
100
+ */
101
+ updateWidget(widgetId: string, jsonString: string, options?: UpdateWidgetOptions): Promise<void>;
102
+ /**
103
+ * Reload widget timelines to refresh their content
104
+ */
105
+ reloadWidgets(widgetIds?: string[] | null): Promise<void>;
106
+ /**
107
+ * Clear a widget's stored data
108
+ */
109
+ clearWidget(widgetId: string): Promise<void>;
110
+ /**
111
+ * Clear all widgets' stored data
112
+ */
113
+ clearAllWidgets(): Promise<void>;
114
+ /**
115
+ * Add an event listener
116
+ */
117
+ addListener(event: string, listener: (event: any) => void): EventSubscription;
118
+ }
119
+ declare const VoltraModule: VoltraModuleSpec;
120
+ export default VoltraModule;
3
121
  //# sourceMappingURL=VoltraModule.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VoltraModule.d.ts","sourceRoot":"","sources":["../src/VoltraModule.ts"],"names":[],"mappings":";AAEA,wBAAkD"}
1
+ {"version":3,"file":"VoltraModule.d.ts","sourceRoot":"","sources":["../src/VoltraModule.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  import { requireNativeModule } from 'expo';
2
- export default requireNativeModule('VoltraModule');
2
+ const VoltraModule = requireNativeModule('VoltraModule');
3
+ export default VoltraModule;
3
4
  //# sourceMappingURL=VoltraModule.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VoltraModule.js","sourceRoot":"","sources":["../src/VoltraModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAA;AAE1C,eAAe,mBAAmB,CAAC,cAAc,CAAC,CAAA","sourcesContent":["import { requireNativeModule } from 'expo'\n\nexport default requireNativeModule('VoltraModule')\n"]}
1
+ {"version":3,"file":"VoltraModule.js","sourceRoot":"","sources":["../src/VoltraModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAA;AA4I1C,MAAM,YAAY,GAAG,mBAAmB,CAAmB,cAAc,CAAC,CAAA;AAE1E,eAAe,YAAY,CAAA","sourcesContent":["import { requireNativeModule } from 'expo'\n\nimport type { EventSubscription, PreloadImageOptions, PreloadImagesResult, UpdateWidgetOptions } from './types.js'\n\n/**\n * Options for starting a Live Activity\n */\nexport type StartVoltraOptions = {\n /**\n * Target type for the activity (used internally)\n */\n target?: string\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n /**\n * The ID/name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityId?: string\n /**\n * Unix timestamp in milliseconds\n */\n staleDate?: number\n /**\n * Double value between 0.0 and 1.0, defaults to 0.0\n */\n relevanceScore?: number\n}\n\n/**\n * Options for updating a Live Activity\n */\nexport type UpdateVoltraOptions = {\n /**\n * Unix timestamp in milliseconds\n */\n staleDate?: number\n /**\n * Double value between 0.0 and 1.0, defaults to 0.0\n */\n relevanceScore?: number\n}\n\n/**\n * Options for ending a Live Activity\n */\nexport type EndVoltraOptions = {\n dismissalPolicy?: {\n type: 'immediate' | 'after'\n date?: number\n }\n}\n\n/**\n * VoltraModule native module interface\n */\nexport interface VoltraModuleSpec {\n /**\n * Start a new Live Activity\n */\n startLiveActivity(jsonString: string, options?: StartVoltraOptions): Promise<string>\n\n /**\n * Update an existing Live Activity\n */\n updateLiveActivity(activityId: string, jsonString: string, options?: UpdateVoltraOptions): Promise<void>\n\n /**\n * End a Live Activity\n */\n endLiveActivity(activityId: string, options?: EndVoltraOptions): Promise<void>\n\n /**\n * End all active Live Activities\n */\n endAllLiveActivities(): Promise<void>\n\n /**\n * Get the latest (most recently created) Voltra Live Activity ID, if any\n */\n getLatestVoltraActivityId(): Promise<string | null>\n\n /**\n * List all running Voltra Live Activity IDs\n */\n listVoltraActivityIds(): Promise<string[]>\n\n /**\n * Check if a Live Activity with the given name is currently active\n */\n isLiveActivityActive(activityName: string): boolean\n\n /**\n * Check if the app was launched in the background (headless)\n */\n isHeadless(): boolean\n\n /**\n * Preload images to App Group storage for use in Live Activities\n */\n preloadImages(images: PreloadImageOptions[]): Promise<PreloadImagesResult>\n\n /**\n * Reload Live Activities to pick up preloaded images\n */\n reloadLiveActivities(activityNames?: string[] | null): Promise<void>\n\n /**\n * Clear preloaded images from App Group storage\n */\n clearPreloadedImages(keys?: string[] | null): Promise<void>\n\n /**\n * Update a home screen widget with new content\n */\n updateWidget(widgetId: string, jsonString: string, options?: UpdateWidgetOptions): Promise<void>\n\n /**\n * Reload widget timelines to refresh their content\n */\n reloadWidgets(widgetIds?: string[] | null): Promise<void>\n\n /**\n * Clear a widget's stored data\n */\n clearWidget(widgetId: string): Promise<void>\n\n /**\n * Clear all widgets' stored data\n */\n clearAllWidgets(): Promise<void>\n\n /**\n * Add an event listener\n */\n addListener(event: string, listener: (event: any) => void): EventSubscription\n}\n\nconst VoltraModule = requireNativeModule<VoltraModuleSpec>('VoltraModule')\n\nexport default VoltraModule\n"]}
package/build/events.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- export type EventSubscription = {
2
- remove: () => void;
3
- };
1
+ import type { EventSubscription } from './types.js';
4
2
  export type BasicVoltraEvent = {
5
3
  source: string;
6
4
  timestamp: number;
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;AACjG,MAAM,MAAM,gCAAgC,GAAG,gBAAgB,GAAG;IAChE,IAAI,EAAE,uBAAuB,CAAA;IAC7B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AACD,MAAM,MAAM,2CAA2C,GAAG,gBAAgB,GAAG;IAC3E,IAAI,EAAE,kCAAkC,CAAA;IACxC,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AACD,MAAM,MAAM,yBAAyB,GAAG,gBAAgB,GAAG;IACzD,IAAI,EAAE,aAAa,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,mBAAmB,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG;IACtD,IAAI,EAAE,aAAa,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAMD,MAAM,MAAM,cAAc,GAAG;IAC3B,qBAAqB,EAAE,gCAAgC,CAAA;IACvD,gCAAgC,EAAE,2CAA2C,CAAA;IAC7E,WAAW,EAAE,yBAAyB,CAAA;IACtC,WAAW,EAAE,sBAAsB,CAAA;CACpC,CAAA;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,cAAc,EAC9D,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3C,iBAAiB,CAMnB"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAInD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;AACjG,MAAM,MAAM,gCAAgC,GAAG,gBAAgB,GAAG;IAChE,IAAI,EAAE,uBAAuB,CAAA;IAC7B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AACD,MAAM,MAAM,2CAA2C,GAAG,gBAAgB,GAAG;IAC3E,IAAI,EAAE,kCAAkC,CAAA;IACxC,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AACD,MAAM,MAAM,yBAAyB,GAAG,gBAAgB,GAAG;IACzD,IAAI,EAAE,aAAa,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,mBAAmB,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG;IACtD,IAAI,EAAE,aAAa,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAMD,MAAM,MAAM,cAAc,GAAG;IAC3B,qBAAqB,EAAE,gCAAgC,CAAA;IACvD,gCAAgC,EAAE,2CAA2C,CAAA;IAC7E,WAAW,EAAE,yBAAyB,CAAA;IACtC,WAAW,EAAE,sBAAsB,CAAA;CACpC,CAAA;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,cAAc,EAC9D,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3C,iBAAiB,CAMnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,YAAY,MAAM,mBAAmB,CAAA;AAiC5C,MAAM,gBAAgB,GAAsB;IAC1C,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;CACjB,CAAA;AASD,MAAM,UAAU,iBAAiB,CAC/B,KAAQ,EACR,QAA4C;IAE5C,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;QAC5B,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,OAAO,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AAClD,CAAC","sourcesContent":["import { assertRunningOnApple } from './utils/index.js'\nimport VoltraModule from './VoltraModule.js'\n\nexport type EventSubscription = {\n remove: () => void\n}\n\nexport type BasicVoltraEvent = {\n source: string\n timestamp: number\n}\n\nexport type VoltraActivityState = 'active' | 'dismissed' | 'pending' | 'stale' | 'ended' | string\nexport type VoltraActivityTokenReceivedEvent = BasicVoltraEvent & {\n type: 'activityTokenReceived'\n activityName: string\n pushToken: string\n}\nexport type VoltraActivityPushToStartTokenReceivedEvent = BasicVoltraEvent & {\n type: 'activityPushToStartTokenReceived'\n pushToStartToken: string\n}\nexport type VoltraActivityUpdateEvent = BasicVoltraEvent & {\n type: 'stateChange'\n activityName: string\n activityState: VoltraActivityState\n}\n\nexport type VoltraInteractionEvent = BasicVoltraEvent & {\n type: 'interaction'\n identifier: string\n payload: string\n}\n\nconst noopSubscription: EventSubscription = {\n remove: () => {},\n}\n\nexport type VoltraEventMap = {\n activityTokenReceived: VoltraActivityTokenReceivedEvent\n activityPushToStartTokenReceived: VoltraActivityPushToStartTokenReceivedEvent\n stateChange: VoltraActivityUpdateEvent\n interaction: VoltraInteractionEvent\n}\n\nexport function addVoltraListener<K extends keyof VoltraEventMap>(\n event: K,\n listener: (event: VoltraEventMap[K]) => void\n): EventSubscription {\n if (!assertRunningOnApple()) {\n return noopSubscription\n }\n\n return VoltraModule.addListener(event, listener)\n}\n"]}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,YAAY,MAAM,mBAAmB,CAAA;AA6B5C,MAAM,gBAAgB,GAAsB;IAC1C,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;CACjB,CAAA;AASD,MAAM,UAAU,iBAAiB,CAC/B,KAAQ,EACR,QAA4C;IAE5C,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;QAC5B,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,OAAO,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AAClD,CAAC","sourcesContent":["import type { EventSubscription } from './types.js'\nimport { assertRunningOnApple } from './utils/index.js'\nimport VoltraModule from './VoltraModule.js'\n\nexport type BasicVoltraEvent = {\n source: string\n timestamp: number\n}\n\nexport type VoltraActivityState = 'active' | 'dismissed' | 'pending' | 'stale' | 'ended' | string\nexport type VoltraActivityTokenReceivedEvent = BasicVoltraEvent & {\n type: 'activityTokenReceived'\n activityName: string\n pushToken: string\n}\nexport type VoltraActivityPushToStartTokenReceivedEvent = BasicVoltraEvent & {\n type: 'activityPushToStartTokenReceived'\n pushToStartToken: string\n}\nexport type VoltraActivityUpdateEvent = BasicVoltraEvent & {\n type: 'stateChange'\n activityName: string\n activityState: VoltraActivityState\n}\n\nexport type VoltraInteractionEvent = BasicVoltraEvent & {\n type: 'interaction'\n identifier: string\n payload: string\n}\n\nconst noopSubscription: EventSubscription = {\n remove: () => {},\n}\n\nexport type VoltraEventMap = {\n activityTokenReceived: VoltraActivityTokenReceivedEvent\n activityPushToStartTokenReceived: VoltraActivityPushToStartTokenReceivedEvent\n stateChange: VoltraActivityUpdateEvent\n interaction: VoltraInteractionEvent\n}\n\nexport function addVoltraListener<K extends keyof VoltraEventMap>(\n event: K,\n listener: (event: VoltraEventMap[K]) => void\n): EventSubscription {\n if (!assertRunningOnApple()) {\n return noopSubscription\n }\n\n return VoltraModule.addListener(event, listener)\n}\n"]}
@@ -140,7 +140,7 @@ export declare const updateLiveActivity: (targetId: string, variants: LiveActivi
140
140
  * ```tsx
141
141
  * import { stopLiveActivity } from 'voltra'
142
142
  *
143
- * await stopLiveActivity('activity-123', { dismissalPolicy: 'afterDate' })
143
+ * await stopLiveActivity('activity-123', { dismissalPolicy: 'immediate' })
144
144
  * ```
145
145
  */
146
146
  export declare const stopLiveActivity: (targetId: string, options?: EndLiveActivityOptions) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/live-activity/api.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEvE,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,yBAAyB,CAAA;AAE7B,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAA;AAEjE,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5D,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxD,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AA6BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,oBAAoB,EAC9B,UAAU,sBAAsB,KAC/B,qBAwFF,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,oBAAoB,EAC9B,UAAU,wBAAwB,KACjC,OAAO,CAAC,MAAM,CAahB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,UAAU,oBAAoB,EAC9B,UAAU,yBAAyB,KAClC,OAAO,CAAC,IAAI,CAOd,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAAU,UAAU,MAAM,EAAE,UAAU,sBAAsB,KAAG,OAAO,CAAC,IAAI,CAIvG,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAAI,cAAc,MAAM,KAAG,OAI3D,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1D"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/live-activity/api.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEvE,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,yBAAyB,CAAA;AAE7B,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAA;AAEjE,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5D,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxD,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,oBAAoB,EAC9B,UAAU,sBAAsB,KAC/B,qBAwFF,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,oBAAoB,EAC9B,UAAU,wBAAwB,KACjC,OAAO,CAAC,MAAM,CAahB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,UAAU,oBAAoB,EAC9B,UAAU,yBAAyB,KAClC,OAAO,CAAC,IAAI,CAOd,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAAU,UAAU,MAAM,EAAE,UAAU,sBAAsB,KAAG,OAAO,CAAC,IAAI,CAKvG,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAAI,cAAc,MAAM,KAAG,OAI3D,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1D"}
@@ -27,6 +27,20 @@ const normalizeSharedLiveActivityOptions = (options) => {
27
27
  }
28
28
  return Object.keys(normalizedOptions).length > 0 ? normalizedOptions : undefined;
29
29
  };
30
+ const normalizeEndLiveActivityOptions = (options) => {
31
+ if (!options?.dismissalPolicy)
32
+ return undefined;
33
+ if (typeof options.dismissalPolicy === 'string') {
34
+ if (options.dismissalPolicy === 'immediate') {
35
+ return { dismissalPolicy: { type: 'immediate' } };
36
+ }
37
+ }
38
+ else if (typeof options.dismissalPolicy === 'object' && 'after' in options.dismissalPolicy) {
39
+ return { dismissalPolicy: { type: 'after', date: options.dismissalPolicy.after } };
40
+ }
41
+ // Default to immediate if unrecognized
42
+ return { dismissalPolicy: { type: 'immediate' } };
43
+ };
30
44
  /**
31
45
  * React hook for managing Live Activities with automatic lifecycle handling.
32
46
  *
@@ -198,13 +212,14 @@ export const updateLiveActivity = async (targetId, variants, options) => {
198
212
  * ```tsx
199
213
  * import { stopLiveActivity } from 'voltra'
200
214
  *
201
- * await stopLiveActivity('activity-123', { dismissalPolicy: 'afterDate' })
215
+ * await stopLiveActivity('activity-123', { dismissalPolicy: 'immediate' })
202
216
  * ```
203
217
  */
204
218
  export const stopLiveActivity = async (targetId, options) => {
205
219
  if (!assertRunningOnApple())
206
220
  return Promise.resolve();
207
- return VoltraModule.endLiveActivity(targetId, options);
221
+ const normalizedOptions = normalizeEndLiveActivityOptions(options);
222
+ return VoltraModule.endLiveActivity(targetId, normalizedOptions);
208
223
  };
209
224
  /**
210
225
  * Check if a Live Activity with the given name is currently active.
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/live-activity/api.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { addVoltraListener } from '../events.js'\nimport { logger } from '../logger.js'\nimport { assertRunningOnApple, useUpdateOnHMR } from '../utils/index.js'\nimport VoltraModule from '../VoltraModule.js'\nimport { renderLiveActivityToString } from './renderer.js'\nimport type { DismissalPolicy, LiveActivityVariants } from './types.js'\n\nexport type SharedLiveActivityOptions = {\n /**\n * Unix timestamp in milliseconds\n */\n staleDate?: number\n /**\n * Double value between 0.0 and 1.0\n * @default 0.0\n */\n relevanceScore?: number\n /**\n * How the Live Activity should be dismissed after ending\n * @default 'immediate'\n */\n dismissalPolicy?: DismissalPolicy\n}\n\nexport type StartLiveActivityOptions = {\n /**\n * The name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityName?: string\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n} & SharedLiveActivityOptions\n\nexport type UpdateLiveActivityOptions = SharedLiveActivityOptions\n\nexport type EndLiveActivityOptions = {\n dismissalPolicy?: DismissalPolicy\n}\n\nexport type UseLiveActivityOptions = {\n /**\n * The name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityName?: string\n /**\n * Automatically start the Live Activity when the component mounts.\n */\n autoStart?: boolean\n /**\n * Automatically update the Live Activity when the component updates.\n */\n autoUpdate?: boolean\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n}\n\nexport type UseLiveActivityResult = {\n start: (options?: StartLiveActivityOptions) => Promise<void>\n update: (options?: UpdateLiveActivityOptions) => Promise<void>\n end: (options?: EndLiveActivityOptions) => Promise<void>\n isActive: boolean\n}\n\nconst normalizeSharedLiveActivityOptions = (\n options?: SharedLiveActivityOptions\n): SharedLiveActivityOptions | undefined => {\n if (!options) return undefined\n\n const normalizedOptions: SharedLiveActivityOptions = {}\n\n if (options.staleDate !== undefined) {\n if (options.staleDate < Date.now()) {\n logger.warn('Ignoring staleDate because it is in the past, the Live Activity would be dismissed immediately.')\n } else {\n normalizedOptions.staleDate = options.staleDate\n }\n }\n\n // Always include relevanceScore, defaulting to 0.0 if not provided\n const relevanceScore = options.relevanceScore ?? 0.0\n if (relevanceScore < 0 || relevanceScore > 1) {\n logger.warn('Ignoring relevanceScore because it is out of range [0.0, 1.0], using default 0.0')\n normalizedOptions.relevanceScore = 0.0\n } else {\n normalizedOptions.relevanceScore = relevanceScore\n }\n\n return Object.keys(normalizedOptions).length > 0 ? normalizedOptions : undefined\n}\n\n/**\n * React hook for managing Live Activities with automatic lifecycle handling.\n *\n * @param variants - The Live Activity content variants to display\n * @param options - Configuration options for the hook\n * @returns Object with start, update, end methods and isActive state\n *\n * @example\n * ```tsx\n * import { useLiveActivity, Voltra } from 'voltra'\n *\n * const MyLiveActivity = () => {\n * const { start, update, end, isActive } = useLiveActivity({\n * minimal: <Voltra.Text>Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * activityName: 'my-activity',\n * autoStart: true,\n * autoUpdate: true\n * })\n *\n * return (\n * <View>\n * <Button title={isActive ? \"Stop\" : \"Start\"} onPress={isActive ? end : start} />\n * </View>\n * )\n * }\n * ```\n */\nexport const useLiveActivity = (\n variants: LiveActivityVariants,\n options?: UseLiveActivityOptions\n): UseLiveActivityResult => {\n const [targetId, setTargetId] = useState<string | null>(() => {\n if (options?.activityName) {\n return isLiveActivityActive(options.activityName) ? options.activityName : null\n }\n\n return null\n })\n const isActive = targetId !== null\n const optionsRef = useRef(options)\n const variantsRef = useRef(variants)\n const lastUpdateOptionsRef = useRef<UpdateLiveActivityOptions | undefined>(undefined)\n\n // Update refs when values change\n useEffect(() => {\n optionsRef.current = options\n }, [options])\n\n useEffect(() => {\n variantsRef.current = variants\n }, [variants])\n\n useUpdateOnHMR()\n\n const start = useCallback(async (options?: StartLiveActivityOptions) => {\n const id = await startLiveActivity(variantsRef.current, { ...optionsRef.current, ...options })\n setTargetId(id)\n }, [])\n\n const update = useCallback(\n async (options?: UpdateLiveActivityOptions) => {\n if (!targetId) {\n return\n }\n\n const updateOptions = { ...optionsRef.current, ...options }\n lastUpdateOptionsRef.current = updateOptions\n await updateLiveActivity(targetId, variantsRef.current, updateOptions)\n },\n [targetId]\n )\n\n const end = useCallback(\n async (options?: EndLiveActivityOptions) => {\n if (!targetId) {\n return\n }\n\n await stopLiveActivity(targetId, options)\n setTargetId(null)\n },\n [targetId]\n )\n\n useEffect(() => {\n if (!options?.autoStart) {\n return\n }\n\n start()\n }, [options?.autoStart, start])\n\n useEffect(() => {\n if (!options?.autoUpdate) return\n update(lastUpdateOptionsRef.current)\n }, [options?.autoUpdate, update, variants])\n\n useEffect(() => {\n if (!targetId) return\n\n const subscription = addVoltraListener('stateChange', (event) => {\n if (event.activityName !== targetId) return\n\n if (event.activityState === 'dismissed' || event.activityState === 'ended') {\n // Live Activity is no longer active.\n setTargetId(null)\n }\n })\n\n return () => subscription.remove()\n }, [targetId])\n\n return {\n start,\n update,\n end,\n isActive,\n }\n}\n\n/**\n * Start a new Live Activity with the provided content variants.\n *\n * @param variants - The Live Activity content variants to display\n * @param options - Configuration options for the Live Activity\n * @returns Promise resolving to the activity ID\n *\n * @example\n * ```tsx\n * import { startLiveActivity, Voltra } from 'voltra'\n *\n * const activityId = await startLiveActivity({\n * minimal: <Voltra.Text>Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * activityName: 'my-activity',\n * deepLinkUrl: '/details',\n * relevanceScore: 0.8\n * })\n * ```\n */\nexport const startLiveActivity = async (\n variants: LiveActivityVariants,\n options?: StartLiveActivityOptions\n): Promise<string> => {\n if (!assertRunningOnApple()) return Promise.resolve('')\n\n const payload = renderLiveActivityToString(variants)\n\n const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)\n const targetId = await VoltraModule.startLiveActivity(payload, {\n target: 'liveActivity',\n deepLinkUrl: options?.deepLinkUrl,\n activityId: options?.activityName,\n ...normalizedSharedOptions,\n })\n return targetId\n}\n\n/**\n * Update an existing Live Activity with new content.\n *\n * @param targetId - The ID of the Live Activity to update\n * @param variants - The new Live Activity content variants\n * @param options - Update options like relevance score\n *\n * @example\n * ```tsx\n * import { updateLiveActivity, Voltra } from 'voltra'\n *\n * await updateLiveActivity('activity-123', {\n * minimal: <Voltra.Text>Updated: Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * relevanceScore: 0.9\n * })\n * ```\n */\nexport const updateLiveActivity = async (\n targetId: string,\n variants: LiveActivityVariants,\n options?: UpdateLiveActivityOptions\n): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const payload = renderLiveActivityToString(variants)\n\n const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)\n return VoltraModule.updateLiveActivity(targetId, payload, normalizedSharedOptions)\n}\n\n/**\n * Stop a Live Activity.\n *\n * @param targetId - The ID of the Live Activity to stop\n * @param options - Options for how to end the activity\n *\n * @example\n * ```tsx\n * import { stopLiveActivity } from 'voltra'\n *\n * await stopLiveActivity('activity-123', { dismissalPolicy: 'afterDate' })\n * ```\n */\nexport const stopLiveActivity = async (targetId: string, options?: EndLiveActivityOptions): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.endLiveActivity(targetId, options)\n}\n\n/**\n * Check if a Live Activity with the given name is currently active.\n *\n * @param activityName - The name of the Live Activity to check\n * @returns true if the activity is active, false otherwise\n *\n * @example\n * ```tsx\n * import { isLiveActivityActive } from 'voltra'\n *\n * if (isLiveActivityActive('my-activity')) {\n * console.log('Activity is running')\n * }\n * ```\n */\nexport const isLiveActivityActive = (activityName: string): boolean => {\n if (!assertRunningOnApple()) return false\n\n return VoltraModule.isLiveActivityActive(activityName)\n}\n\n/**\n * End all active Live Activities.\n *\n * This function stops and dismisses all currently running Live Activities in the app.\n * It's useful for cleanup operations, such as when the app is being closed or\n * when you want to reset all Live Activity states.\n *\n * @example\n * ```typescript\n * import { endAllLiveActivities } from 'voltra'\n *\n * // End all active Live Activities\n * await endAllLiveActivities()\n * ```\n */\nexport async function endAllLiveActivities(): Promise<void> {\n if (!assertRunningOnApple()) return Promise.resolve()\n return VoltraModule.endAllLiveActivities()\n}\n"]}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/live-activity/api.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { addVoltraListener } from '../events.js'\nimport { logger } from '../logger.js'\nimport { assertRunningOnApple, useUpdateOnHMR } from '../utils/index.js'\nimport VoltraModule from '../VoltraModule.js'\nimport { renderLiveActivityToString } from './renderer.js'\nimport type { DismissalPolicy, LiveActivityVariants } from './types.js'\n\nexport type SharedLiveActivityOptions = {\n /**\n * Unix timestamp in milliseconds\n */\n staleDate?: number\n /**\n * Double value between 0.0 and 1.0\n * @default 0.0\n */\n relevanceScore?: number\n /**\n * How the Live Activity should be dismissed after ending\n * @default 'immediate'\n */\n dismissalPolicy?: DismissalPolicy\n}\n\nexport type StartLiveActivityOptions = {\n /**\n * The name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityName?: string\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n} & SharedLiveActivityOptions\n\nexport type UpdateLiveActivityOptions = SharedLiveActivityOptions\n\nexport type EndLiveActivityOptions = {\n dismissalPolicy?: DismissalPolicy\n}\n\nexport type UseLiveActivityOptions = {\n /**\n * The name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityName?: string\n /**\n * Automatically start the Live Activity when the component mounts.\n */\n autoStart?: boolean\n /**\n * Automatically update the Live Activity when the component updates.\n */\n autoUpdate?: boolean\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n}\n\nexport type UseLiveActivityResult = {\n start: (options?: StartLiveActivityOptions) => Promise<void>\n update: (options?: UpdateLiveActivityOptions) => Promise<void>\n end: (options?: EndLiveActivityOptions) => Promise<void>\n isActive: boolean\n}\n\nconst normalizeSharedLiveActivityOptions = (\n options?: SharedLiveActivityOptions\n): SharedLiveActivityOptions | undefined => {\n if (!options) return undefined\n\n const normalizedOptions: SharedLiveActivityOptions = {}\n\n if (options.staleDate !== undefined) {\n if (options.staleDate < Date.now()) {\n logger.warn('Ignoring staleDate because it is in the past, the Live Activity would be dismissed immediately.')\n } else {\n normalizedOptions.staleDate = options.staleDate\n }\n }\n\n // Always include relevanceScore, defaulting to 0.0 if not provided\n const relevanceScore = options.relevanceScore ?? 0.0\n if (relevanceScore < 0 || relevanceScore > 1) {\n logger.warn('Ignoring relevanceScore because it is out of range [0.0, 1.0], using default 0.0')\n normalizedOptions.relevanceScore = 0.0\n } else {\n normalizedOptions.relevanceScore = relevanceScore\n }\n\n return Object.keys(normalizedOptions).length > 0 ? normalizedOptions : undefined\n}\n\nconst normalizeEndLiveActivityOptions = (\n options?: EndLiveActivityOptions\n): { dismissalPolicy?: { type: 'immediate' | 'after'; date?: number } } | undefined => {\n if (!options?.dismissalPolicy) return undefined\n\n if (typeof options.dismissalPolicy === 'string') {\n if (options.dismissalPolicy === 'immediate') {\n return { dismissalPolicy: { type: 'immediate' } }\n }\n } else if (typeof options.dismissalPolicy === 'object' && 'after' in options.dismissalPolicy) {\n return { dismissalPolicy: { type: 'after', date: options.dismissalPolicy.after } }\n }\n\n // Default to immediate if unrecognized\n return { dismissalPolicy: { type: 'immediate' } }\n}\n\n/**\n * React hook for managing Live Activities with automatic lifecycle handling.\n *\n * @param variants - The Live Activity content variants to display\n * @param options - Configuration options for the hook\n * @returns Object with start, update, end methods and isActive state\n *\n * @example\n * ```tsx\n * import { useLiveActivity, Voltra } from 'voltra'\n *\n * const MyLiveActivity = () => {\n * const { start, update, end, isActive } = useLiveActivity({\n * minimal: <Voltra.Text>Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * activityName: 'my-activity',\n * autoStart: true,\n * autoUpdate: true\n * })\n *\n * return (\n * <View>\n * <Button title={isActive ? \"Stop\" : \"Start\"} onPress={isActive ? end : start} />\n * </View>\n * )\n * }\n * ```\n */\nexport const useLiveActivity = (\n variants: LiveActivityVariants,\n options?: UseLiveActivityOptions\n): UseLiveActivityResult => {\n const [targetId, setTargetId] = useState<string | null>(() => {\n if (options?.activityName) {\n return isLiveActivityActive(options.activityName) ? options.activityName : null\n }\n\n return null\n })\n const isActive = targetId !== null\n const optionsRef = useRef(options)\n const variantsRef = useRef(variants)\n const lastUpdateOptionsRef = useRef<UpdateLiveActivityOptions | undefined>(undefined)\n\n // Update refs when values change\n useEffect(() => {\n optionsRef.current = options\n }, [options])\n\n useEffect(() => {\n variantsRef.current = variants\n }, [variants])\n\n useUpdateOnHMR()\n\n const start = useCallback(async (options?: StartLiveActivityOptions) => {\n const id = await startLiveActivity(variantsRef.current, { ...optionsRef.current, ...options })\n setTargetId(id)\n }, [])\n\n const update = useCallback(\n async (options?: UpdateLiveActivityOptions) => {\n if (!targetId) {\n return\n }\n\n const updateOptions = { ...optionsRef.current, ...options }\n lastUpdateOptionsRef.current = updateOptions\n await updateLiveActivity(targetId, variantsRef.current, updateOptions)\n },\n [targetId]\n )\n\n const end = useCallback(\n async (options?: EndLiveActivityOptions) => {\n if (!targetId) {\n return\n }\n\n await stopLiveActivity(targetId, options)\n setTargetId(null)\n },\n [targetId]\n )\n\n useEffect(() => {\n if (!options?.autoStart) {\n return\n }\n\n start()\n }, [options?.autoStart, start])\n\n useEffect(() => {\n if (!options?.autoUpdate) return\n update(lastUpdateOptionsRef.current)\n }, [options?.autoUpdate, update, variants])\n\n useEffect(() => {\n if (!targetId) return\n\n const subscription = addVoltraListener('stateChange', (event) => {\n if (event.activityName !== targetId) return\n\n if (event.activityState === 'dismissed' || event.activityState === 'ended') {\n // Live Activity is no longer active.\n setTargetId(null)\n }\n })\n\n return () => subscription.remove()\n }, [targetId])\n\n return {\n start,\n update,\n end,\n isActive,\n }\n}\n\n/**\n * Start a new Live Activity with the provided content variants.\n *\n * @param variants - The Live Activity content variants to display\n * @param options - Configuration options for the Live Activity\n * @returns Promise resolving to the activity ID\n *\n * @example\n * ```tsx\n * import { startLiveActivity, Voltra } from 'voltra'\n *\n * const activityId = await startLiveActivity({\n * minimal: <Voltra.Text>Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * activityName: 'my-activity',\n * deepLinkUrl: '/details',\n * relevanceScore: 0.8\n * })\n * ```\n */\nexport const startLiveActivity = async (\n variants: LiveActivityVariants,\n options?: StartLiveActivityOptions\n): Promise<string> => {\n if (!assertRunningOnApple()) return Promise.resolve('')\n\n const payload = renderLiveActivityToString(variants)\n\n const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)\n const targetId = await VoltraModule.startLiveActivity(payload, {\n target: 'liveActivity',\n deepLinkUrl: options?.deepLinkUrl,\n activityId: options?.activityName,\n ...normalizedSharedOptions,\n })\n return targetId\n}\n\n/**\n * Update an existing Live Activity with new content.\n *\n * @param targetId - The ID of the Live Activity to update\n * @param variants - The new Live Activity content variants\n * @param options - Update options like relevance score\n *\n * @example\n * ```tsx\n * import { updateLiveActivity, Voltra } from 'voltra'\n *\n * await updateLiveActivity('activity-123', {\n * minimal: <Voltra.Text>Updated: Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * relevanceScore: 0.9\n * })\n * ```\n */\nexport const updateLiveActivity = async (\n targetId: string,\n variants: LiveActivityVariants,\n options?: UpdateLiveActivityOptions\n): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const payload = renderLiveActivityToString(variants)\n\n const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)\n return VoltraModule.updateLiveActivity(targetId, payload, normalizedSharedOptions)\n}\n\n/**\n * Stop a Live Activity.\n *\n * @param targetId - The ID of the Live Activity to stop\n * @param options - Options for how to end the activity\n *\n * @example\n * ```tsx\n * import { stopLiveActivity } from 'voltra'\n *\n * await stopLiveActivity('activity-123', { dismissalPolicy: 'immediate' })\n * ```\n */\nexport const stopLiveActivity = async (targetId: string, options?: EndLiveActivityOptions): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const normalizedOptions = normalizeEndLiveActivityOptions(options)\n return VoltraModule.endLiveActivity(targetId, normalizedOptions)\n}\n\n/**\n * Check if a Live Activity with the given name is currently active.\n *\n * @param activityName - The name of the Live Activity to check\n * @returns true if the activity is active, false otherwise\n *\n * @example\n * ```tsx\n * import { isLiveActivityActive } from 'voltra'\n *\n * if (isLiveActivityActive('my-activity')) {\n * console.log('Activity is running')\n * }\n * ```\n */\nexport const isLiveActivityActive = (activityName: string): boolean => {\n if (!assertRunningOnApple()) return false\n\n return VoltraModule.isLiveActivityActive(activityName)\n}\n\n/**\n * End all active Live Activities.\n *\n * This function stops and dismisses all currently running Live Activities in the app.\n * It's useful for cleanup operations, such as when the app is being closed or\n * when you want to reset all Live Activity states.\n *\n * @example\n * ```typescript\n * import { endAllLiveActivities } from 'voltra'\n *\n * // End all active Live Activities\n * await endAllLiveActivities()\n * ```\n */\nexport async function endAllLiveActivities(): Promise<void> {\n if (!assertRunningOnApple()) return Promise.resolve()\n return VoltraModule.endAllLiveActivities()\n}\n"]}
@@ -1,40 +1,5 @@
1
- /**
2
- * Options for preloading a single image
3
- */
4
- export type PreloadImageOptions = {
5
- /**
6
- * The URL to download the image from
7
- */
8
- url: string;
9
- /**
10
- * The key to use when referencing this image (used as assetName in Image component)
11
- */
12
- key: string;
13
- /**
14
- * HTTP method to use. Defaults to 'GET'.
15
- */
16
- method?: 'GET' | 'POST' | 'PUT';
17
- /**
18
- * Optional HTTP headers to include in the request
19
- */
20
- headers?: Record<string, string>;
21
- };
22
- /**
23
- * Result of preloading images
24
- */
25
- export type PreloadImagesResult = {
26
- /**
27
- * Keys of images that were successfully preloaded
28
- */
29
- succeeded: string[];
30
- /**
31
- * Images that failed to preload, with error messages
32
- */
33
- failed: {
34
- key: string;
35
- error: string;
36
- }[];
37
- };
1
+ import type { PreloadImageOptions, PreloadImagesResult } from './types.js';
2
+ export type { PreloadImageOptions, PreloadImagesResult } from './types.js';
38
3
  /**
39
4
  * Preload images to App Group storage for use in Live Activities.
40
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"preload.d.ts","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB;;OAEG;IACH,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CACzC,CAAA;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAgB/F;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzE"}
1
+ {"version":3,"file":"preload.d.ts","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAI1E,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAQ1E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAgB/F;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzE"}
@@ -1 +1 @@
1
- {"version":3,"file":"preload.js","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,YAAY,MAAM,mBAAmB,CAAA;AAsC5C,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAA;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,2BAA2B,CAAC,CAAA;IAC7D,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAA6B;IAC/D,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC,EAAE,CAAA;IACpH,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAO,YAAoB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,EAAE;YACb,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC3B,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;aAChE,CAAC,CAAC;SACJ,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,aAAwB;IACjE,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC;QAAE,OAAM;IAE9C,IAAI,CAAC;QACH,MAAO,YAAoB,CAAC,oBAAoB,CAAC,aAAa,IAAI,IAAI,CAAC,CAAA;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAe;IACxD,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC;QAAE,OAAM;IAE9C,IAAI,CAAC;QACH,MAAO,YAAoB,CAAC,oBAAoB,CAAC,IAAI,IAAI,IAAI,CAAC,CAAA;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC","sourcesContent":["import { Platform } from 'react-native'\n\nimport VoltraModule from './VoltraModule.js'\n\n/**\n * Options for preloading a single image\n */\nexport type PreloadImageOptions = {\n /**\n * The URL to download the image from\n */\n url: string\n /**\n * The key to use when referencing this image (used as assetName in Image component)\n */\n key: string\n /**\n * HTTP method to use. Defaults to 'GET'.\n */\n method?: 'GET' | 'POST' | 'PUT'\n /**\n * Optional HTTP headers to include in the request\n */\n headers?: Record<string, string>\n}\n\n/**\n * Result of preloading images\n */\nexport type PreloadImagesResult = {\n /**\n * Keys of images that were successfully preloaded\n */\n succeeded: string[]\n /**\n * Images that failed to preload, with error messages\n */\n failed: { key: string; error: string }[]\n}\n\nfunction assertIOS(name: string): boolean {\n const isIOS = Platform.OS === 'ios'\n if (!isIOS) console.error(`${name} is only available on iOS`)\n return isIOS\n}\n\n/**\n * Preload images to App Group storage for use in Live Activities.\n *\n * Downloaded images are stored in shared storage accessible by both the app\n * and the Live Activity widget extension. Images can then be referenced using\n * the `assetName` property in the Image component.\n *\n * Images must be less than 4KB to comply with ActivityKit limits.\n *\n * @param images - Array of images to preload\n * @returns Result indicating which images succeeded or failed\n *\n * @example\n * ```typescript\n * const result = await preloadImages([\n * {\n * url: 'https://example.com/album-art.jpg',\n * key: 'current-album',\n * headers: { 'Authorization': 'Bearer token' }\n * }\n * ])\n *\n * // Use in Live Activity\n * <Voltra.Image source={{ assetName: 'current-album' }} />\n * ```\n */\nexport async function preloadImages(images: PreloadImageOptions[]): Promise<PreloadImagesResult> {\n if (!assertIOS('preloadImages')) {\n return { succeeded: [], failed: images.map((img) => ({ key: img.key, error: 'Not available on this platform' })) }\n }\n\n try {\n return await (VoltraModule as any).preloadImages(images)\n } catch (error) {\n return {\n succeeded: [],\n failed: images.map((img) => ({\n key: img.key,\n error: error instanceof Error ? error.message : 'Unknown error',\n })),\n }\n }\n}\n\n/**\n * Reload Live Activities to pick up newly preloaded images.\n *\n * This triggers an update on the specified Live Activities (or all if none specified)\n * with their current content state, forcing SwiftUI to re-render and load the\n * newly preloaded images from App Group storage.\n *\n * @param activityNames - Optional array of activity names to reload. If omitted, reloads all.\n *\n * @example\n * ```typescript\n * // Preload new image\n * await preloadImages([{ url: 'https://example.com/new-art.jpg', key: 'album-art' }])\n *\n * // Reload specific activity to pick up the new image\n * await reloadLiveActivities(['music-player'])\n *\n * // Or reload all activities\n * await reloadLiveActivities()\n * ```\n */\nexport async function reloadLiveActivities(activityNames?: string[]): Promise<void> {\n if (!assertIOS('reloadLiveActivities')) return\n\n try {\n await (VoltraModule as any).reloadLiveActivities(activityNames ?? null)\n } catch (error) {\n console.error('Failed to reload Live Activities:', error)\n }\n}\n\n/**\n * Clear preloaded images from App Group storage.\n *\n * @param keys - Optional array of image keys to clear. If omitted, clears all preloaded images.\n *\n * @example\n * ```typescript\n * // Clear specific images\n * await clearPreloadedImages(['album-art', 'profile-pic'])\n *\n * // Clear all preloaded images\n * await clearPreloadedImages()\n * ```\n */\nexport async function clearPreloadedImages(keys?: string[]): Promise<void> {\n if (!assertIOS('clearPreloadedImages')) return\n\n try {\n await (VoltraModule as any).clearPreloadedImages(keys ?? null)\n } catch (error) {\n console.error('Failed to clear preloaded images:', error)\n }\n}\n"]}
1
+ {"version":3,"file":"preload.js","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGvC,OAAO,YAAY,MAAM,mBAAmB,CAAA;AAK5C,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAA;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,2BAA2B,CAAC,CAAA;IAC7D,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAA6B;IAC/D,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC,EAAE,CAAA;IACpH,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAO,YAAoB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,EAAE;YACb,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC3B,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;aAChE,CAAC,CAAC;SACJ,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,aAAwB;IACjE,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC;QAAE,OAAM;IAE9C,IAAI,CAAC;QACH,MAAO,YAAoB,CAAC,oBAAoB,CAAC,aAAa,IAAI,IAAI,CAAC,CAAA;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAe;IACxD,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC;QAAE,OAAM;IAE9C,IAAI,CAAC;QACH,MAAO,YAAoB,CAAC,oBAAoB,CAAC,IAAI,IAAI,IAAI,CAAC,CAAA;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC","sourcesContent":["import { Platform } from 'react-native'\n\nimport type { PreloadImageOptions, PreloadImagesResult } from './types.js'\nimport VoltraModule from './VoltraModule.js'\n\n// Re-export types for public API\nexport type { PreloadImageOptions, PreloadImagesResult } from './types.js'\n\nfunction assertIOS(name: string): boolean {\n const isIOS = Platform.OS === 'ios'\n if (!isIOS) console.error(`${name} is only available on iOS`)\n return isIOS\n}\n\n/**\n * Preload images to App Group storage for use in Live Activities.\n *\n * Downloaded images are stored in shared storage accessible by both the app\n * and the Live Activity widget extension. Images can then be referenced using\n * the `assetName` property in the Image component.\n *\n * Images must be less than 4KB to comply with ActivityKit limits.\n *\n * @param images - Array of images to preload\n * @returns Result indicating which images succeeded or failed\n *\n * @example\n * ```typescript\n * const result = await preloadImages([\n * {\n * url: 'https://example.com/album-art.jpg',\n * key: 'current-album',\n * headers: { 'Authorization': 'Bearer token' }\n * }\n * ])\n *\n * // Use in Live Activity\n * <Voltra.Image source={{ assetName: 'current-album' }} />\n * ```\n */\nexport async function preloadImages(images: PreloadImageOptions[]): Promise<PreloadImagesResult> {\n if (!assertIOS('preloadImages')) {\n return { succeeded: [], failed: images.map((img) => ({ key: img.key, error: 'Not available on this platform' })) }\n }\n\n try {\n return await (VoltraModule as any).preloadImages(images)\n } catch (error) {\n return {\n succeeded: [],\n failed: images.map((img) => ({\n key: img.key,\n error: error instanceof Error ? error.message : 'Unknown error',\n })),\n }\n }\n}\n\n/**\n * Reload Live Activities to pick up newly preloaded images.\n *\n * This triggers an update on the specified Live Activities (or all if none specified)\n * with their current content state, forcing SwiftUI to re-render and load the\n * newly preloaded images from App Group storage.\n *\n * @param activityNames - Optional array of activity names to reload. If omitted, reloads all.\n *\n * @example\n * ```typescript\n * // Preload new image\n * await preloadImages([{ url: 'https://example.com/new-art.jpg', key: 'album-art' }])\n *\n * // Reload specific activity to pick up the new image\n * await reloadLiveActivities(['music-player'])\n *\n * // Or reload all activities\n * await reloadLiveActivities()\n * ```\n */\nexport async function reloadLiveActivities(activityNames?: string[]): Promise<void> {\n if (!assertIOS('reloadLiveActivities')) return\n\n try {\n await (VoltraModule as any).reloadLiveActivities(activityNames ?? null)\n } catch (error) {\n console.error('Failed to reload Live Activities:', error)\n }\n}\n\n/**\n * Clear preloaded images from App Group storage.\n *\n * @param keys - Optional array of image keys to clear. If omitted, clears all preloaded images.\n *\n * @example\n * ```typescript\n * // Clear specific images\n * await clearPreloadedImages(['album-art', 'profile-pic'])\n *\n * // Clear all preloaded images\n * await clearPreloadedImages()\n * ```\n */\nexport async function clearPreloadedImages(keys?: string[]): Promise<void> {\n if (!assertIOS('clearPreloadedImages')) return\n\n try {\n await (VoltraModule as any).clearPreloadedImages(keys ?? null)\n } catch (error) {\n console.error('Failed to clear preloaded images:', error)\n }\n}\n"]}
package/build/types.d.ts CHANGED
@@ -14,4 +14,62 @@ export type VoltraElementRef = {
14
14
  $r: number;
15
15
  };
16
16
  export type VoltraNodeJson = VoltraElementJson | VoltraElementJson[] | VoltraElementRef | string;
17
+ /**
18
+ * Event subscription interface
19
+ */
20
+ export type EventSubscription = {
21
+ remove: () => void;
22
+ };
23
+ /**
24
+ * Options for preloading a single image
25
+ */
26
+ export type PreloadImageOptions = {
27
+ /**
28
+ * The URL to download the image from
29
+ */
30
+ url: string;
31
+ /**
32
+ * The key to use when referencing this image (used as assetName in Image component)
33
+ */
34
+ key: string;
35
+ /**
36
+ * HTTP method to use. Defaults to 'GET'.
37
+ */
38
+ method?: 'GET' | 'POST' | 'PUT';
39
+ /**
40
+ * Optional HTTP headers to include in the request
41
+ */
42
+ headers?: Record<string, string>;
43
+ };
44
+ /**
45
+ * Result of a failed image preload
46
+ */
47
+ export type PreloadImageFailure = {
48
+ key: string;
49
+ error: string;
50
+ };
51
+ /**
52
+ * Result of preloading images
53
+ */
54
+ export type PreloadImagesResult = {
55
+ /**
56
+ * Keys of images that were successfully preloaded
57
+ */
58
+ succeeded: string[];
59
+ /**
60
+ * Images that failed to preload, with error messages
61
+ */
62
+ failed: PreloadImageFailure[];
63
+ };
64
+ /**
65
+ * Options for updating a home screen widget
66
+ */
67
+ export type UpdateWidgetOptions = {
68
+ /**
69
+ * URL to open when the widget is tapped.
70
+ * Can be a full URL (e.g., "myapp://screen/details")
71
+ * or a path that will be prefixed with your app's URL scheme.
72
+ */
73
+ deepLinkUrl?: string;
74
+ };
17
75
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,cAAc,CAAA;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,cAAc,CAAA;IAClB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACpC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,iBAAiB,EAAE,GAAG,gBAAgB,GAAG,MAAM,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,cAAc,CAAA;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,cAAc,CAAA;IAClB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACpC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,iBAAiB,EAAE,GAAG,gBAAgB,GAAG,MAAM,CAAA;AAEhG;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB;;OAEG;IACH,MAAM,EAAE,mBAAmB,EAAE,CAAA;CAC9B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type VoltraPropValue = string | number | boolean | null | VoltraNodeJson // Allow component trees in props\n\nexport type VoltraElementJson = {\n t: number\n i?: string\n c?: VoltraNodeJson\n p?: Record<string, VoltraPropValue>\n}\n\n/**\n * Reference to a shared element by index.\n * Used for element deduplication - when the same JSX element (by reference)\n * appears multiple times in the tree.\n */\nexport type VoltraElementRef = {\n $r: number\n}\n\nexport type VoltraNodeJson = VoltraElementJson | VoltraElementJson[] | VoltraElementRef | string\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type VoltraPropValue = string | number | boolean | null | VoltraNodeJson // Allow component trees in props\n\nexport type VoltraElementJson = {\n t: number\n i?: string\n c?: VoltraNodeJson\n p?: Record<string, VoltraPropValue>\n}\n\n/**\n * Reference to a shared element by index.\n * Used for element deduplication - when the same JSX element (by reference)\n * appears multiple times in the tree.\n */\nexport type VoltraElementRef = {\n $r: number\n}\n\nexport type VoltraNodeJson = VoltraElementJson | VoltraElementJson[] | VoltraElementRef | string\n\n/**\n * Event subscription interface\n */\nexport type EventSubscription = {\n remove: () => void\n}\n\n/**\n * Options for preloading a single image\n */\nexport type PreloadImageOptions = {\n /**\n * The URL to download the image from\n */\n url: string\n /**\n * The key to use when referencing this image (used as assetName in Image component)\n */\n key: string\n /**\n * HTTP method to use. Defaults to 'GET'.\n */\n method?: 'GET' | 'POST' | 'PUT'\n /**\n * Optional HTTP headers to include in the request\n */\n headers?: Record<string, string>\n}\n\n/**\n * Result of a failed image preload\n */\nexport type PreloadImageFailure = {\n key: string\n error: string\n}\n\n/**\n * Result of preloading images\n */\nexport type PreloadImagesResult = {\n /**\n * Keys of images that were successfully preloaded\n */\n succeeded: string[]\n /**\n * Images that failed to preload, with error messages\n */\n failed: PreloadImageFailure[]\n}\n\n/**\n * Options for updating a home screen widget\n */\nexport type UpdateWidgetOptions = {\n /**\n * URL to open when the widget is tapped.\n * Can be a full URL (e.g., \"myapp://screen/details\")\n * or a path that will be prefixed with your app's URL scheme.\n */\n deepLinkUrl?: string\n}\n"]}
@@ -1,15 +1,6 @@
1
+ import type { UpdateWidgetOptions } from '../types.js';
1
2
  import { WidgetVariants } from './types.js';
2
- /**
3
- * Options for updating a home screen widget
4
- */
5
- export type UpdateWidgetOptions = {
6
- /**
7
- * URL to open when the widget is tapped.
8
- * Can be a full URL (e.g., "myapp://screen/details")
9
- * or a path that will be prefixed with your app's URL scheme.
10
- */
11
- deepLinkUrl?: string;
12
- };
3
+ export type { UpdateWidgetOptions } from '../types.js';
13
4
  /**
14
5
  * Update a home screen widget with new content.
15
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"widget-api.d.ts","sourceRoot":"","sources":["../../src/widgets/widget-api.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,EAChB,UAAU,cAAc,EACxB,UAAU,mBAAmB,KAC5B,OAAO,CAAC,IAAI,CAQd,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,GAAU,YAAY,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAItE,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAIhE,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,QAAa,OAAO,CAAC,IAAI,CAIpD,CAAA"}
1
+ {"version":3,"file":"widget-api.d.ts","sourceRoot":"","sources":["../../src/widgets/widget-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAItD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAG3C,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,EAChB,UAAU,cAAc,EACxB,UAAU,mBAAmB,KAC5B,OAAO,CAAC,IAAI,CAQd,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,GAAU,YAAY,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAItE,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAIhE,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,QAAa,OAAO,CAAC,IAAI,CAIpD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"widget-api.js","sourceRoot":"","sources":["../../src/widgets/widget-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AACvE,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAepD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,QAAgB,EAChB,QAAwB,EACxB,OAA6B,EACd,EAAE;IACjB,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,MAAM,OAAO,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IAE9C,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE;QAClD,WAAW,EAAE,OAAO,EAAE,WAAW;KAClC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,SAAoB,EAAiB,EAAE;IACzE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,aAAa,CAAC,SAAS,IAAI,IAAI,CAAC,CAAA;AACtD,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAiB,EAAE;IACnE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;AAC3C,CAAC,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAmB,EAAE;IACvD,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,eAAe,EAAE,CAAA;AACvC,CAAC,CAAA","sourcesContent":["import { assertRunningOnApple } from '../utils/assertRunningOnApple.js'\nimport VoltraModule from '../VoltraModule.js'\nimport { renderWidgetToString } from './renderer.js'\nimport { WidgetVariants } from './types.js'\n\n/**\n * Options for updating a home screen widget\n */\nexport type UpdateWidgetOptions = {\n /**\n * URL to open when the widget is tapped.\n * Can be a full URL (e.g., \"myapp://screen/details\")\n * or a path that will be prefixed with your app's URL scheme.\n */\n deepLinkUrl?: string\n}\n\n/**\n * Update a home screen widget with new content.\n *\n * The content will be stored in App Group storage and the widget timeline\n * will be reloaded to display the new content.\n *\n * @param widgetId - The widget identifier (as defined in your config plugin)\n * @param variants - An object mapping widget families to specific content.\n * Each key corresponds to a widget size family.\n * @param options - Optional settings like deep link URL\n *\n * @example Different content per size\n * ```tsx\n * import { updateWidget, Voltra } from 'voltra'\n *\n * await updateWidget('weather', {\n * systemSmall: <Voltra.Text fontSize={32}>72°F</Voltra.Text>,\n * systemMedium: (\n * <Voltra.HStack>\n * <Voltra.Text fontSize={32}>72°F</Voltra.Text>\n * <Voltra.VStack>\n * <Voltra.Text>Sunny</Voltra.Text>\n * <Voltra.Text>High: 78° Low: 65°</Voltra.Text>\n * </Voltra.VStack>\n * </Voltra.HStack>\n * ),\n * }, { deepLinkUrl: '/weather' })\n * ```\n */\nexport const updateWidget = async (\n widgetId: string,\n variants: WidgetVariants,\n options?: UpdateWidgetOptions\n): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const payload = renderWidgetToString(variants)\n\n return VoltraModule.updateWidget(widgetId, payload, {\n deepLinkUrl: options?.deepLinkUrl,\n })\n}\n\n/**\n * Reload widget timelines to refresh their content.\n *\n * Use this after updating data that widgets depend on (e.g., after preloading\n * new images) to force them to re-render.\n *\n * @param widgetIds - Optional array of widget IDs to reload. If omitted, reloads all widgets.\n *\n * @example\n * ```typescript\n * // Reload specific widgets\n * await reloadWidgets(['weather', 'calendar'])\n *\n * // Reload all widgets\n * await reloadWidgets()\n * ```\n */\nexport const reloadWidgets = async (widgetIds?: string[]): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.reloadWidgets(widgetIds ?? null)\n}\n\n/**\n * Clear a widget's stored data.\n *\n * This removes the JSON content and deep link URL for the specified widget,\n * causing it to show its placeholder state.\n *\n * @param widgetId - The widget identifier to clear\n *\n * @example\n * ```typescript\n * await clearWidget('weather')\n * ```\n */\nexport const clearWidget = async (widgetId: string): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.clearWidget(widgetId)\n}\n\n/**\n * Clear all widgets' stored data.\n *\n * This removes the JSON content and deep link URLs for all configured widgets,\n * causing them to show their placeholder states.\n *\n * @example\n * ```typescript\n * await clearAllWidgets()\n * ```\n */\nexport const clearAllWidgets = async (): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.clearAllWidgets()\n}\n"]}
1
+ {"version":3,"file":"widget-api.js","sourceRoot":"","sources":["../../src/widgets/widget-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AACvE,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAMpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,QAAgB,EAChB,QAAwB,EACxB,OAA6B,EACd,EAAE;IACjB,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,MAAM,OAAO,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IAE9C,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE;QAClD,WAAW,EAAE,OAAO,EAAE,WAAW;KAClC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,SAAoB,EAAiB,EAAE;IACzE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,aAAa,CAAC,SAAS,IAAI,IAAI,CAAC,CAAA;AACtD,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAiB,EAAE;IACnE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;AAC3C,CAAC,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAmB,EAAE;IACvD,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,eAAe,EAAE,CAAA;AACvC,CAAC,CAAA","sourcesContent":["import type { UpdateWidgetOptions } from '../types.js'\nimport { assertRunningOnApple } from '../utils/assertRunningOnApple.js'\nimport VoltraModule from '../VoltraModule.js'\nimport { renderWidgetToString } from './renderer.js'\nimport { WidgetVariants } from './types.js'\n\n// Re-export type for public API\nexport type { UpdateWidgetOptions } from '../types.js'\n\n/**\n * Update a home screen widget with new content.\n *\n * The content will be stored in App Group storage and the widget timeline\n * will be reloaded to display the new content.\n *\n * @param widgetId - The widget identifier (as defined in your config plugin)\n * @param variants - An object mapping widget families to specific content.\n * Each key corresponds to a widget size family.\n * @param options - Optional settings like deep link URL\n *\n * @example Different content per size\n * ```tsx\n * import { updateWidget, Voltra } from 'voltra'\n *\n * await updateWidget('weather', {\n * systemSmall: <Voltra.Text fontSize={32}>72°F</Voltra.Text>,\n * systemMedium: (\n * <Voltra.HStack>\n * <Voltra.Text fontSize={32}>72°F</Voltra.Text>\n * <Voltra.VStack>\n * <Voltra.Text>Sunny</Voltra.Text>\n * <Voltra.Text>High: 78° Low: 65°</Voltra.Text>\n * </Voltra.VStack>\n * </Voltra.HStack>\n * ),\n * }, { deepLinkUrl: '/weather' })\n * ```\n */\nexport const updateWidget = async (\n widgetId: string,\n variants: WidgetVariants,\n options?: UpdateWidgetOptions\n): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const payload = renderWidgetToString(variants)\n\n return VoltraModule.updateWidget(widgetId, payload, {\n deepLinkUrl: options?.deepLinkUrl,\n })\n}\n\n/**\n * Reload widget timelines to refresh their content.\n *\n * Use this after updating data that widgets depend on (e.g., after preloading\n * new images) to force them to re-render.\n *\n * @param widgetIds - Optional array of widget IDs to reload. If omitted, reloads all widgets.\n *\n * @example\n * ```typescript\n * // Reload specific widgets\n * await reloadWidgets(['weather', 'calendar'])\n *\n * // Reload all widgets\n * await reloadWidgets()\n * ```\n */\nexport const reloadWidgets = async (widgetIds?: string[]): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.reloadWidgets(widgetIds ?? null)\n}\n\n/**\n * Clear a widget's stored data.\n *\n * This removes the JSON content and deep link URL for the specified widget,\n * causing it to show its placeholder state.\n *\n * @param widgetId - The widget identifier to clear\n *\n * @example\n * ```typescript\n * await clearWidget('weather')\n * ```\n */\nexport const clearWidget = async (widgetId: string): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.clearWidget(widgetId)\n}\n\n/**\n * Clear all widgets' stored data.\n *\n * This removes the JSON content and deep link URLs for all configured widgets,\n * causing them to show their placeholder states.\n *\n * @example\n * ```typescript\n * await clearAllWidgets()\n * ```\n */\nexport const clearAllWidgets = async (): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.clearAllWidgets()\n}\n"]}
@@ -22,26 +22,11 @@ Pod::Spec.new do |s|
22
22
  'DEFINES_MODULE' => 'YES',
23
23
  }
24
24
 
25
- # Default subspec: main app module (auto-linked by Expo)
26
- s.default_subspecs = 'Core'
25
+ s.dependency 'ExpoModulesCore'
27
26
 
28
- # Core subspec: React Native bridge module
29
- s.subspec 'Core' do |ss|
30
- ss.dependency 'ExpoModulesCore'
31
-
32
- ss.source_files = [
33
- "app/**/*.swift",
34
- "shared/**/*.swift",
35
- "ui/**/*.swift", # Add shared UI code
36
- ]
37
- end
38
-
39
- # Widget subspec: Widget extension code
40
- s.subspec 'Widget' do |ss|
41
- ss.source_files = [
42
- "shared/**/*.swift",
43
- "ui/**/*.swift", # Add shared UI code
44
- "target/**/*.swift", # Widget-specific files only
45
- ]
46
- end
27
+ s.source_files = [
28
+ "app/**/*.swift",
29
+ "ui/**/*.swift",
30
+ "shared/**/*.swift",
31
+ ]
47
32
  end
@@ -0,0 +1,30 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'VoltraWidget'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.description = 'Voltra Widget Extension support.'
10
+ s.license = package['license']
11
+ s.author = package['author']
12
+ s.homepage = package['homepage']
13
+ s.platforms = {
14
+ :ios => '16.2',
15
+ }
16
+ s.swift_version = '5.9'
17
+ s.source = { git: 'https://github.com/callstackincubator/voltra' }
18
+ s.static_framework = true
19
+
20
+ # Swift/Objective-C compatibility
21
+ s.pod_target_xcconfig = {
22
+ 'DEFINES_MODULE' => 'YES',
23
+ }
24
+
25
+ s.source_files = [
26
+ "ui/**/*.swift",
27
+ "shared/**/*.swift",
28
+ "target/**/*.swift",
29
+ ]
30
+ end
@@ -6,5 +6,3 @@ extension Data {
6
6
  map { String(format: "%02x", $0) }.joined()
7
7
  }
8
8
  }
9
-
10
-
@@ -1,6 +1,5 @@
1
1
  import SwiftUI
2
2
 
3
- // TODO: Refactor to NOT overwrite defaults.
4
3
  enum StyleConverter {
5
4
  static func convert(_ js: [String: Any]) -> (LayoutStyle, DecorationStyle, RenderingStyle, TextStyle) {
6
5
  (parseLayout(js), parseDecoration(js), parseRendering(js), parseText(js))
@@ -12,9 +11,9 @@ enum StyleConverter {
12
11
  let flexGrow = JSStyleParser.number(js["flexGrow"]) ?? 0
13
12
  let finalFlex = max(flexVal, flexGrow)
14
13
 
15
- // If it flexes, give it priority 1 so it beats fixed items (default 0).
16
- // Do NOT use the raw value (e.g. 2.0), or it will eat other flex items.
17
- let priority: Double = finalFlex > 0 ? 1.0 : 0.0
14
+ // If it flexes, give it priority 1 so it beats fixed items.
15
+ // Only set layoutPriority when flex is active; nil means "don't apply modifier".
16
+ let priority: Double? = finalFlex > 0 ? 1.0 : nil
18
17
 
19
18
  // Position parsing (offsetX/offsetY -> CGPoint)
20
19
  var position: CGPoint?
@@ -26,8 +25,8 @@ enum StyleConverter {
26
25
  position = CGPoint(x: 0, y: offsetY)
27
26
  }
28
27
 
29
- // zIndex parsing
30
- let zIndex = JSStyleParser.number(js["zIndex"]) ?? 0.0
28
+ // zIndex: only set if explicitly provided in JS
29
+ let zIndex = JSStyleParser.number(js["zIndex"])
31
30
 
32
31
  return LayoutStyle(
33
32
  // Dimensions
@@ -49,7 +48,7 @@ enum StyleConverter {
49
48
 
50
49
  // Positioning
51
50
  position: position,
52
- zIndex: zIndex
51
+ zIndex: zIndex.map { Double($0) }
53
52
  )
54
53
  }
55
54
 
package/package.json CHANGED
@@ -1,17 +1,9 @@
1
1
  {
2
2
  "name": "voltra",
3
- "version": "1.0.0-rc.1",
3
+ "version": "1.0.0",
4
4
  "description": "Build Live Activities with JSX in React Native",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
7
- "files": [
8
- "build",
9
- "plugin/build",
10
- "app.plugin.js",
11
- "expo-module.config.json",
12
- "ios-files",
13
- "ios"
14
- ],
15
7
  "exports": {
16
8
  ".": {
17
9
  "types": "./build/index.d.ts",
@@ -57,7 +57,7 @@ function generateWidgetBundleSwift(widgets) {
57
57
 
58
58
  import SwiftUI
59
59
  import WidgetKit
60
- import Voltra
60
+ import VoltraWidget
61
61
 
62
62
  @main
63
63
  struct VoltraWidgetBundle: WidgetBundle {
@@ -90,7 +90,7 @@ function generateDefaultWidgetBundleSwift() {
90
90
 
91
91
  import SwiftUI
92
92
  import WidgetKit
93
- import Voltra // Import Voltra widgets
93
+ import VoltraWidget // Import Voltra widgets
94
94
 
95
95
  @main
96
96
  struct VoltraWidgetBundle: WidgetBundle {
@@ -26,7 +26,7 @@ target '${targetName}' do
26
26
  voltra_module = JSON.parse(${backtick}npx expo-modules-autolinking search -p apple --json --project-root #{project_root}${backtick})
27
27
  podspec_dir_path = Pathname.new(File.join(voltra_module['${libraryName}']['path'], 'ios')).relative_path_from(Pathname.new(__dir__)).to_path
28
28
 
29
- pod 'Voltra/Widget', :path => podspec_dir_path
29
+ pod 'VoltraWidget', :path => podspec_dir_path
30
30
  end`;
31
31
  }
32
32
  /**