expo-invoke 1.2.0 → 2.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.
Files changed (117) hide show
  1. package/android/src/main/java/expo/modules/invoke/InteractiveWidgetReceiver.kt +47 -0
  2. package/android/src/main/java/expo/modules/invoke/InvokeSliceProvider.kt +83 -0
  3. package/android/src/main/java/expo/modules/invoke/ShortcutsHelper.kt +38 -32
  4. package/build/plugin/android/withAndroidInvoke.d.ts +3 -1
  5. package/build/plugin/android/withAndroidInvoke.js +71 -15
  6. package/build/plugin/android/withAndroidInvoke.js.map +1 -1
  7. package/build/plugin/codegen/generateSwiftAppClip.d.ts +2 -0
  8. package/build/plugin/codegen/generateSwiftAppClip.js +20 -0
  9. package/build/plugin/codegen/generateSwiftAppClip.js.map +1 -0
  10. package/build/plugin/codegen/generateSwiftEntities.d.ts +2 -0
  11. package/build/plugin/codegen/generateSwiftEntities.js +91 -0
  12. package/build/plugin/codegen/generateSwiftEntities.js.map +1 -0
  13. package/build/plugin/codegen/generateSwiftFocusFilters.d.ts +2 -0
  14. package/build/plugin/codegen/generateSwiftFocusFilters.js +42 -0
  15. package/build/plugin/codegen/generateSwiftFocusFilters.js.map +1 -0
  16. package/build/plugin/codegen/generateSwiftIntents.d.ts +2 -0
  17. package/build/plugin/codegen/generateSwiftIntents.js +43 -13
  18. package/build/plugin/codegen/generateSwiftIntents.js.map +1 -1
  19. package/build/plugin/ios/withIOSInvoke.d.ts +8 -1
  20. package/build/plugin/ios/withIOSInvoke.js +61 -10
  21. package/build/plugin/ios/withIOSInvoke.js.map +1 -1
  22. package/build/plugin/src/withInvoke.d.ts +20 -3
  23. package/build/plugin/src/withInvoke.js +23 -4
  24. package/build/plugin/src/withInvoke.js.map +1 -1
  25. package/build/src/components/AddToSiriButton.d.ts +1 -1
  26. package/build/src/components/AddToSiriButton.d.ts.map +1 -1
  27. package/build/src/components/InvokeDebugger.d.ts +1 -1
  28. package/build/src/components/InvokeDebugger.d.ts.map +1 -1
  29. package/build/src/components/ShortcutChip.d.ts +1 -1
  30. package/build/src/components/ShortcutChip.d.ts.map +1 -1
  31. package/build/src/hooks/useBackgroundIntent.d.ts +15 -0
  32. package/build/src/hooks/useBackgroundIntent.d.ts.map +1 -0
  33. package/build/src/hooks/useBackgroundIntent.js +41 -0
  34. package/build/src/hooks/useBackgroundIntent.js.map +1 -0
  35. package/build/src/hooks/useEntityQuery.d.ts +26 -0
  36. package/build/src/hooks/useEntityQuery.d.ts.map +1 -0
  37. package/build/src/hooks/useEntityQuery.js +47 -0
  38. package/build/src/hooks/useEntityQuery.js.map +1 -0
  39. package/build/src/hooks/useFocusFilter.d.ts +1 -1
  40. package/build/src/hooks/useFocusFilter.d.ts.map +1 -1
  41. package/build/src/hooks/useFocusFilter.js.map +1 -1
  42. package/build/src/hooks/useFocusFilterState.d.ts +28 -0
  43. package/build/src/hooks/useFocusFilterState.d.ts.map +1 -0
  44. package/build/src/hooks/useFocusFilterState.js +47 -0
  45. package/build/src/hooks/useFocusFilterState.js.map +1 -0
  46. package/build/src/hooks/useInvoke.d.ts.map +1 -1
  47. package/build/src/hooks/useInvoke.js +3 -0
  48. package/build/src/hooks/useInvoke.js.map +1 -1
  49. package/build/src/hooks/useInvokeAnalytics.d.ts +10 -14
  50. package/build/src/hooks/useInvokeAnalytics.d.ts.map +1 -1
  51. package/build/src/hooks/useInvokeAnalytics.js +21 -14
  52. package/build/src/hooks/useInvokeAnalytics.js.map +1 -1
  53. package/build/src/hooks/useInvokeQueue.d.ts +32 -0
  54. package/build/src/hooks/useInvokeQueue.d.ts.map +1 -0
  55. package/build/src/hooks/useInvokeQueue.js +77 -0
  56. package/build/src/hooks/useInvokeQueue.js.map +1 -0
  57. package/build/src/hooks/useLiveActivity.d.ts +37 -0
  58. package/build/src/hooks/useLiveActivity.d.ts.map +1 -0
  59. package/build/src/hooks/useLiveActivity.js +74 -0
  60. package/build/src/hooks/useLiveActivity.js.map +1 -0
  61. package/build/src/hooks/useOTAConfig.d.ts +24 -0
  62. package/build/src/hooks/useOTAConfig.d.ts.map +1 -0
  63. package/build/src/hooks/useOTAConfig.js +40 -0
  64. package/build/src/hooks/useOTAConfig.js.map +1 -0
  65. package/build/src/hooks/usePushToTalk.d.ts +35 -0
  66. package/build/src/hooks/usePushToTalk.d.ts.map +1 -0
  67. package/build/src/hooks/usePushToTalk.js +101 -0
  68. package/build/src/hooks/usePushToTalk.js.map +1 -0
  69. package/build/src/hooks/useSlice.d.ts +19 -0
  70. package/build/src/hooks/useSlice.d.ts.map +1 -0
  71. package/build/src/hooks/useSlice.js +22 -0
  72. package/build/src/hooks/useSlice.js.map +1 -0
  73. package/build/src/index.d.ts +19 -3
  74. package/build/src/index.d.ts.map +1 -1
  75. package/build/src/index.js +16 -1
  76. package/build/src/index.js.map +1 -1
  77. package/build/src/module.d.ts +18 -3
  78. package/build/src/module.d.ts.map +1 -1
  79. package/build/src/module.js +77 -0
  80. package/build/src/module.js.map +1 -1
  81. package/build/src/types/index.d.ts +117 -4
  82. package/build/src/types/index.d.ts.map +1 -1
  83. package/build/src/utils/analytics.d.ts +1 -7
  84. package/build/src/utils/analytics.d.ts.map +1 -1
  85. package/build/src/utils/analytics.js +9 -0
  86. package/build/src/utils/analytics.js.map +1 -1
  87. package/build/src/utils/invokeError.d.ts +28 -0
  88. package/build/src/utils/invokeError.d.ts.map +1 -0
  89. package/build/src/utils/invokeError.js +57 -0
  90. package/build/src/utils/invokeError.js.map +1 -0
  91. package/build/src/utils/otaConfig.d.ts +9 -0
  92. package/build/src/utils/otaConfig.d.ts.map +1 -0
  93. package/build/src/utils/otaConfig.js +45 -0
  94. package/build/src/utils/otaConfig.js.map +1 -0
  95. package/build/src/utils/persistentAnalytics.d.ts +5 -0
  96. package/build/src/utils/persistentAnalytics.d.ts.map +1 -0
  97. package/build/src/utils/persistentAnalytics.js +52 -0
  98. package/build/src/utils/persistentAnalytics.js.map +1 -0
  99. package/build/src/utils/validation.d.ts +12 -0
  100. package/build/src/utils/validation.d.ts.map +1 -1
  101. package/build/src/utils/validation.js +81 -1
  102. package/build/src/utils/validation.js.map +1 -1
  103. package/build/src/web/index.d.ts +39 -0
  104. package/build/src/web/index.d.ts.map +1 -0
  105. package/build/src/web/index.js +37 -0
  106. package/build/src/web/index.js.map +1 -0
  107. package/build/src/web/module.d.ts +40 -0
  108. package/build/src/web/module.d.ts.map +1 -0
  109. package/build/src/web/module.js +46 -0
  110. package/build/src/web/module.js.map +1 -0
  111. package/ios/AppClip/AppClipHandler.swift +41 -0
  112. package/ios/Background/BackgroundIntentBridge.swift +56 -0
  113. package/ios/Entities/EntityQueryBridge.swift +40 -0
  114. package/ios/FocusFilter/FocusFilterRegistrar.swift +40 -0
  115. package/ios/LiveActivity/LiveActivityManager.swift +83 -0
  116. package/ios/PTT/PTTManager.swift +51 -0
  117. package/package.json +5 -1
@@ -1,6 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.swiftWidgetFamily = swiftWidgetFamily;
3
4
  exports.generateSwiftIntents = generateSwiftIntents;
5
+ /** Escape a string for safe embedding inside Swift double-quoted string literals. */
6
+ function escapeSwiftString(s) {
7
+ return s
8
+ .replace(/\\/g, '\\\\')
9
+ .replace(/"/g, '\\"')
10
+ .replace(/\n/g, '\\n')
11
+ .replace(/\r/g, '\\r')
12
+ .replace(/\t/g, '\\t');
13
+ }
4
14
  function toPascalCase(id) {
5
15
  return id.split(/[_\s-]+/).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join('');
6
16
  }
@@ -9,6 +19,7 @@ function toCamelCase(id) {
9
19
  return pascal.charAt(0).toLowerCase() + pascal.slice(1);
10
20
  }
11
21
  function swiftParamType(param) {
22
+ var _a;
12
23
  switch (param.type) {
13
24
  case 'text': return 'String';
14
25
  case 'number': return 'Double';
@@ -24,6 +35,7 @@ function swiftParamType(param) {
24
35
  case 'location': return '[LocationEntity]';
25
36
  default: return '[String]';
26
37
  }
38
+ case 'entity': return `${toPascalCase((_a = param.entityId) !== null && _a !== void 0 ? _a : 'app')}Entity`;
27
39
  default: return 'String';
28
40
  }
29
41
  }
@@ -44,6 +56,8 @@ function paramToJSON(param) {
44
56
  return `if let v = ${name} { params["${name}"] = v }`;
45
57
  case 'array':
46
58
  return `if let v = ${name} { params["${name}"] = v }`;
59
+ case 'entity':
60
+ return `if let v = ${name} { params["${name}"] = v.toJSON() }`;
47
61
  default:
48
62
  return `if let v = ${name} { params["${name}"] = v }`;
49
63
  }
@@ -57,7 +71,7 @@ function generateIntentStruct(intent) {
57
71
  const swiftType = swiftParamType(p);
58
72
  const optional = p.optional !== false ? '?' : '';
59
73
  const swiftName = toCamelCase(p.name);
60
- return ` @Parameter(title: "${p.title}")
74
+ return ` @Parameter(title: "${escapeSwiftString(p.title)}")
61
75
  var ${swiftName}: ${swiftType}${optional}`;
62
76
  }).join('\n\n');
63
77
  const paramExtraction = params.map((p) => {
@@ -67,27 +81,30 @@ function generateIntentStruct(intent) {
67
81
  }).join('\n');
68
82
  const spokenResult = intent.spokenResponse
69
83
  ? `
70
- let spoken = "${intent.spokenResponse}"
84
+ let spoken = "${escapeSwiftString(intent.spokenResponse)}"
71
85
  return .result(dialog: IntentDialog(full: .init(stringLiteral: spoken)))`
72
86
  : `
73
87
  return .result()`;
88
+ const backgroundCall = intent.openAppWhenRun === false
89
+ ? ` await ExpoInvokeBackgroundBridge.shared.dispatch(intentId: "${escapeSwiftString(intent.id)}", parameters: params)`
90
+ : ` ExpoInvokeModule.writePendingIntent(
91
+ intentId: "${escapeSwiftString(intent.id)}",
92
+ source: "siri",
93
+ parameters: params,
94
+ spokenResponse: ${intent.spokenResponse ? `"${escapeSwiftString(intent.spokenResponse)}"` : 'nil'}
95
+ )`;
74
96
  return `@available(iOS 16.0, *)
75
97
  struct ${structName}: AppIntent {
76
- static var title: LocalizedStringResource = "${intent.title}"
98
+ static var title: LocalizedStringResource = "${escapeSwiftString(intent.title)}"
77
99
  static var openAppWhenRun: Bool = ${openApp}
78
- static var description = IntentDescription("${(_b = intent.description) !== null && _b !== void 0 ? _b : intent.title}")
100
+ static var description = IntentDescription("${escapeSwiftString((_b = intent.description) !== null && _b !== void 0 ? _b : intent.title)}")
79
101
 
80
102
  ${paramDecls || ' // No parameters'}
81
103
 
82
104
  func perform() async throws -> some IntentResult {
83
105
  var params: [String: Any] = [:]
84
106
  ${paramExtraction}
85
- ExpoInvokeModule.writePendingIntent(
86
- intentId: "${intent.id}",
87
- source: "siri",
88
- parameters: params,
89
- spokenResponse: ${intent.spokenResponse ? `"${intent.spokenResponse}"` : 'nil'}
90
- )${spokenResult}
107
+ ${backgroundCall}${spokenResult}
91
108
  }
92
109
  }`;
93
110
  }
@@ -98,9 +115,9 @@ function generateShortcutsProvider(intents) {
98
115
  var _a, _b;
99
116
  return ` AppShortcut(
100
117
  intent: ${structName}(),
101
- phrases: ["${p}"],
102
- shortTitle: "${(_a = i.shortTitle) !== null && _a !== void 0 ? _a : i.title}",
103
- systemImageName: "${(_b = i.icon) !== null && _b !== void 0 ? _b : 'star'}"
118
+ phrases: ["${escapeSwiftString(p)}"],
119
+ shortTitle: "${escapeSwiftString((_a = i.shortTitle) !== null && _a !== void 0 ? _a : i.title)}",
120
+ systemImageName: "${escapeSwiftString((_b = i.icon) !== null && _b !== void 0 ? _b : 'star')}"
104
121
  )`;
105
122
  }).join(',\n');
106
123
  return phrases;
@@ -114,6 +131,19 @@ ${intentRefs}
114
131
  }
115
132
  }`;
116
133
  }
134
+ const WIDGET_SIZE_MAP = {
135
+ small: '.systemSmall',
136
+ medium: '.systemMedium',
137
+ large: '.systemLarge',
138
+ extraLarge: '.systemExtraLarge',
139
+ accessory: '.accessoryCircular',
140
+ accessoryStandBy: '.accessoryCorner',
141
+ };
142
+ /** Maps a WidgetSize string to its Swift WidgetFamily case */
143
+ function swiftWidgetFamily(size) {
144
+ var _a;
145
+ return (_a = WIDGET_SIZE_MAP[size]) !== null && _a !== void 0 ? _a : '.systemSmall';
146
+ }
117
147
  function generateSwiftIntents(intents) {
118
148
  const structs = intents.map(generateIntentStruct).join('\n\n');
119
149
  const provider = generateShortcutsProvider(intents);
@@ -1 +1 @@
1
- {"version":3,"file":"generateSwiftIntents.js","sourceRoot":"","sources":["../../../plugin/codegen/generateSwiftIntents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generateSwiftIntents.js","sourceRoot":"","sources":["../../../plugin/codegen/generateSwiftIntents.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,16 @@
1
1
  import { type ConfigPlugin } from '@expo/config-plugins';
2
- import type { IntentDefinition } from '../../src/types';
2
+ import type { IntentDefinition, AppEntityDefinition, FocusFilterDefinition, AppClipDefinition } from '../../src/types';
3
3
  interface IOSInvokeOptions {
4
4
  intents: IntentDefinition[];
5
5
  voiceUsageDescription?: string;
6
6
  appGroupId?: string;
7
+ entities?: AppEntityDefinition[];
8
+ focusFilters?: FocusFilterDefinition[];
9
+ appClips?: AppClipDefinition[];
10
+ enablePushToTalk?: boolean;
11
+ pttUsageDescription?: string;
12
+ enableLiveActivities?: boolean;
13
+ liveActivityTypes?: string[];
7
14
  }
8
15
  export declare const withIOSInvoke: ConfigPlugin<IOSInvokeOptions>;
9
16
  export {};
@@ -38,18 +38,43 @@ const config_plugins_1 = require("@expo/config-plugins");
38
38
  const fs = __importStar(require("fs"));
39
39
  const path = __importStar(require("path"));
40
40
  const generateSwiftIntents_1 = require("../codegen/generateSwiftIntents");
41
+ const generateSwiftEntities_1 = require("../codegen/generateSwiftEntities");
42
+ const generateSwiftFocusFilters_1 = require("../codegen/generateSwiftFocusFilters");
43
+ const generateSwiftAppClip_1 = require("../codegen/generateSwiftAppClip");
41
44
  const withIOSInvoke = (config, options) => {
42
- const { intents, voiceUsageDescription, appGroupId } = options;
43
- // 1. Info.plist usage description
45
+ const { intents, voiceUsageDescription, appGroupId, entities = [], focusFilters = [], appClips = [], enablePushToTalk = false, pttUsageDescription, enableLiveActivities = false, } = options;
46
+ // 1. Info.plist usage descriptions + feature flags
44
47
  config = (0, config_plugins_1.withInfoPlist)(config, (cfg) => {
48
+ var _a;
45
49
  cfg.modResults.NSSiriUsageDescription =
46
50
  voiceUsageDescription !== null && voiceUsageDescription !== void 0 ? voiceUsageDescription : 'This app uses Siri to perform quick actions.';
47
51
  cfg.modResults.NSVoiceUsageDescription =
48
52
  voiceUsageDescription !== null && voiceUsageDescription !== void 0 ? voiceUsageDescription : 'This app uses voice commands to perform quick actions.';
53
+ if (enablePushToTalk) {
54
+ cfg.modResults.NSPushToTalkUsageDescription =
55
+ pttUsageDescription !== null && pttUsageDescription !== void 0 ? pttUsageDescription : 'This app uses Push to Talk for voice communication.';
56
+ // Add voip background mode
57
+ const modes = (_a = cfg.modResults.UIBackgroundModes) !== null && _a !== void 0 ? _a : [];
58
+ if (!modes.includes('voip')) {
59
+ cfg.modResults.UIBackgroundModes = [...modes, 'voip'];
60
+ }
61
+ }
62
+ if (enableLiveActivities) {
63
+ cfg.modResults.NSSupportsLiveActivities = true;
64
+ cfg.modResults.NSSupportsLiveActivitiesFrequentUpdates = true;
65
+ }
66
+ if (appClips.length > 0) {
67
+ cfg.modResults.NSAppClip = {
68
+ NSAppClipRequestEphemeralUserNotification: true,
69
+ NSAppClipRequestLocationConfirmation: true,
70
+ };
71
+ }
72
+ if (focusFilters.length > 0) {
73
+ cfg.modResults.NSFocusFilterEnabled = true;
74
+ }
49
75
  return cfg;
50
76
  });
51
- // 2. App Groups entitlement (needed for widget data sharing)
52
- // plist values are typed as a union — cast the existing array explicitly
77
+ // 2. App Groups entitlement (widget data sharing + App Clips)
53
78
  if (appGroupId) {
54
79
  config = (0, config_plugins_1.withEntitlementsPlist)(config, (cfg) => {
55
80
  var _a;
@@ -60,20 +85,46 @@ const withIOSInvoke = (config, options) => {
60
85
  return cfg;
61
86
  });
62
87
  }
63
- // 3. Generate InvokeIntents.swift via withDangerousMod
88
+ // 3. Generate Swift files via withDangerousMod
64
89
  config = (0, config_plugins_1.withDangerousMod)(config, [
65
90
  'ios',
66
91
  async (cfg) => {
67
92
  var _a;
68
93
  const appName = (_a = cfg.modRequest.projectName) !== null && _a !== void 0 ? _a : 'app';
69
94
  const iosDir = path.join(cfg.modRequest.platformProjectRoot, appName);
70
- // Ensure directory exists
71
- if (!fs.existsSync(iosDir)) {
95
+ try {
72
96
  fs.mkdirSync(iosDir, { recursive: true });
73
97
  }
74
- const swiftCode = (0, generateSwiftIntents_1.generateSwiftIntents)(intents);
75
- const outputPath = path.join(iosDir, 'InvokeIntents.swift');
76
- fs.writeFileSync(outputPath, swiftCode, 'utf8');
98
+ catch (e) {
99
+ throw new Error(`[expo-invoke] Could not create iOS project directory at "${iosDir}".\n` +
100
+ `Cause: ${e instanceof Error ? e.message : e}\n` +
101
+ `Fix: Ensure the path is writable. Try running \`npx expo prebuild --clean\`.`);
102
+ }
103
+ const writeSwift = (filename, content) => {
104
+ const filePath = path.join(iosDir, filename);
105
+ try {
106
+ fs.writeFileSync(filePath, content, 'utf8');
107
+ }
108
+ catch (e) {
109
+ throw new Error(`[expo-invoke] Failed to write ${filename} to "${iosDir}".\n` +
110
+ `Cause: ${e instanceof Error ? e.message : e}\n` +
111
+ `Fix: Ensure the iOS project directory is writable. Run \`npx expo prebuild --clean\`.`);
112
+ }
113
+ };
114
+ // InvokeIntents.swift — AppIntent structs + AppShortcutsProvider
115
+ writeSwift('InvokeIntents.swift', (0, generateSwiftIntents_1.generateSwiftIntents)(intents));
116
+ // InvokeEntities.swift — AppEntity + EntityQuery structs
117
+ const entityCode = (0, generateSwiftEntities_1.generateSwiftEntities)(entities);
118
+ if (entityCode)
119
+ writeSwift('InvokeEntities.swift', entityCode);
120
+ // InvokeFocusFilters.swift — SetFocusFilterIntent structs
121
+ const focusCode = (0, generateSwiftFocusFilters_1.generateSwiftFocusFilters)(focusFilters);
122
+ if (focusCode)
123
+ writeSwift('InvokeFocusFilters.swift', focusCode);
124
+ // InvokeAppClip.swift — App Clip URL → intent registrations
125
+ const clipCode = (0, generateSwiftAppClip_1.generateSwiftAppClip)(appClips);
126
+ if (clipCode)
127
+ writeSwift('InvokeAppClip.swift', clipCode);
77
128
  return cfg;
78
129
  },
79
130
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"withIOSInvoke.js","sourceRoot":"","sources":["../../../plugin/ios/withIOSInvoke.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yDAK8B;AAC9B,uCAAyB;AACzB,2CAA6B;AAC7B,0EAAuE;AAShE,MAAM,aAAa,GAAmC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IAC/E,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAE/D,kCAAkC;IAClC,MAAM,GAAG,IAAA,8BAAa,EAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;QACrC,GAAG,CAAC,UAAU,CAAC,sBAAsB;YACnC,qBAAqB,aAArB,qBAAqB,cAArB,qBAAqB,GAAI,8CAA8C,CAAC;QAC1E,GAAG,CAAC,UAAU,CAAC,uBAAuB;YACpC,qBAAqB,aAArB,qBAAqB,cAArB,qBAAqB,GAAI,wDAAwD,CAAC;QACpF,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,6DAA6D;IAC7D,yEAAyE;IACzE,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,GAAG,IAAA,sCAAqB,EAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;;YAC7C,MAAM,QAAQ,GAAG,MAAC,GAAG,CAAC,UAAU,CAAC,uCAAuC,CAA0B,mCAAI,EAAE,CAAC;YACzG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnC,GAAG,CAAC,UAAU,CAAC,uCAAuC,CAAC,GAAG,CAAC,GAAG,QAAQ,EAAE,UAAU,CAAC,CAAC;YACtF,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IAED,uDAAuD;IACvD,MAAM,GAAG,IAAA,iCAAgB,EAAC,MAAM,EAAE;QAChC,KAAK;QACL,KAAK,EAAE,GAAG,EAAE,EAAE;;YACZ,MAAM,OAAO,GAAG,MAAA,GAAG,CAAC,UAAU,CAAC,WAAW,mCAAI,KAAK,CAAC;YACpD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC;YAEtE,0BAA0B;YAC1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,CAAC;YAED,MAAM,SAAS,GAAG,IAAA,2CAAoB,EAAC,OAAO,CAAC,CAAC;YAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;YAC5D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;YAEhD,OAAO,GAAG,CAAC;QACb,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AA7CW,QAAA,aAAa,iBA6CxB"}
1
+ {"version":3,"file":"withIOSInvoke.js","sourceRoot":"","sources":["../../../plugin/ios/withIOSInvoke.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,4 @@
1
- import { type ConfigPlugin } from '@expo/config-plugins';
2
- import type { IntentDefinition, WidgetDefinition, NotificationCategoryDefinition } from '../../src/types';
1
+ import type { IntentDefinition, WidgetDefinition, NotificationCategoryDefinition, AppEntityDefinition, FocusFilterDefinition, AppClipDefinition, SliceDefinition } from '../../src/types';
3
2
  export interface InvokePluginOptions {
4
3
  /** Intent definitions. Each intent maps to Siri voice phrases, shortcuts, widget buttons, etc. */
5
4
  intents: IntentDefinition[];
@@ -11,6 +10,24 @@ export interface InvokePluginOptions {
11
10
  voiceUsageDescription?: string;
12
11
  /** iOS App Group identifier for widget data sharing (e.g. "group.com.myapp.invoke") */
13
12
  appGroupId?: string;
13
+ /** App Entity definitions for Siri parameter resolution (iOS 16.4+) */
14
+ entities?: AppEntityDefinition[];
15
+ /** Focus filter definitions — register the app as a Focus filter (iOS 16+) */
16
+ focusFilters?: FocusFilterDefinition[];
17
+ /** App Clip definitions (iOS 14+) */
18
+ appClips?: AppClipDefinition[];
19
+ /** Android Slice definitions for Google Search / Assistant inline content */
20
+ slices?: SliceDefinition[];
21
+ /** Enable interactive widget controls that fire without opening the app (iOS 17+ / Android 12+) */
22
+ enableInteractiveWidgets?: boolean;
23
+ /** Enable Push-to-Talk framework integration (iOS 16+) */
24
+ enablePushToTalk?: boolean;
25
+ /** NSPushToTalkUsageDescription — required if enablePushToTalk is true */
26
+ pttUsageDescription?: string;
27
+ /** Set NSSupportsLiveActivities in Info.plist */
28
+ enableLiveActivities?: boolean;
29
+ /** ActivityAttributes class names your app defines (for documentation / validation) */
30
+ liveActivityTypes?: string[];
14
31
  }
15
- declare const _default: ConfigPlugin<InvokePluginOptions>;
32
+ declare const _default: any;
16
33
  export default _default;
@@ -3,11 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const config_plugins_1 = require("@expo/config-plugins");
4
4
  const withIOSInvoke_1 = require("../ios/withIOSInvoke");
5
5
  const withAndroidInvoke_1 = require("../android/withAndroidInvoke");
6
+ const validation_1 = require("../../src/utils/validation");
6
7
  const withInvoke = (config, options) => {
7
- const { intents = [], widgets, notificationActions, voiceUsageDescription, appGroupId } = options;
8
- config = (0, withIOSInvoke_1.withIOSInvoke)(config, { intents, voiceUsageDescription, appGroupId });
9
- config = (0, withAndroidInvoke_1.withAndroidInvoke)(config, { intents, notificationActions });
8
+ const { intents = [], widgets: _widgets, notificationActions, voiceUsageDescription, appGroupId, entities = [], focusFilters = [], appClips = [], slices = [], enableInteractiveWidgets = false, enablePushToTalk = false, pttUsageDescription, enableLiveActivities = false, liveActivityTypes = [], } = options;
9
+ // Validate options early throws with a helpful message if misconfigured
10
+ (0, validation_1.validatePluginOptions)({ enablePushToTalk, pttUsageDescription, enableLiveActivities, liveActivityTypes });
11
+ config = (0, withIOSInvoke_1.withIOSInvoke)(config, {
12
+ intents,
13
+ voiceUsageDescription,
14
+ appGroupId,
15
+ entities,
16
+ focusFilters,
17
+ appClips,
18
+ enablePushToTalk,
19
+ pttUsageDescription,
20
+ enableLiveActivities,
21
+ liveActivityTypes,
22
+ });
23
+ config = (0, withAndroidInvoke_1.withAndroidInvoke)(config, {
24
+ intents,
25
+ notificationActions,
26
+ slices,
27
+ enableInteractiveWidgets,
28
+ });
10
29
  return config;
11
30
  };
12
- exports.default = (0, config_plugins_1.createRunOncePlugin)(withInvoke, 'expo-invoke', '1.0.0');
31
+ exports.default = (0, config_plugins_1.createRunOncePlugin)(withInvoke, 'expo-invoke', '2.0.0');
13
32
  //# sourceMappingURL=withInvoke.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"withInvoke.js","sourceRoot":"","sources":["../../../plugin/src/withInvoke.ts"],"names":[],"mappings":";;AAAA,yDAA8E;AAC9E,wDAAqD;AACrD,oEAAiE;AAoBjE,MAAM,UAAU,GAAsC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IACxE,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAElG,MAAM,GAAG,IAAA,6BAAa,EAAC,MAAM,EAAE,EAAE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,CAAC,CAAC;IAC/E,MAAM,GAAG,IAAA,qCAAiB,EAAC,MAAM,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAErE,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,kBAAe,IAAA,oCAAmB,EAAC,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"withInvoke.js","sourceRoot":"","sources":["../../../plugin/src/withInvoke.ts"],"names":[],"mappings":";;AAAA,yDAA8E;AAC9E,wDAAqD;AACrD,oEAAiE;AACjE,2DAAmE;AA0CnE,MAAM,UAAU,GAAsC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IACxE,MAAM,EACJ,OAAO,GAAG,EAAE,EACZ,OAAO,EAAE,QAAQ,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,QAAQ,GAAG,EAAE,EACb,YAAY,GAAG,EAAE,EACjB,QAAQ,GAAG,EAAE,EACb,MAAM,GAAG,EAAE,EACX,wBAAwB,GAAG,KAAK,EAChC,gBAAgB,GAAG,KAAK,EACxB,mBAAmB,EACnB,oBAAoB,GAAG,KAAK,EAC5B,iBAAiB,GAAG,EAAE,GACvB,GAAG,OAAO,CAAC;IAEZ,0EAA0E;IAC1E,IAAA,kCAAqB,EAAC,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAE1G,MAAM,GAAG,IAAA,6BAAa,EAAC,MAAM,EAAE;QAC7B,OAAO;QACP,qBAAqB;QACrB,UAAU;QACV,QAAQ;QACR,YAAY;QACZ,QAAQ;QACR,gBAAgB;QAChB,mBAAmB;QACnB,oBAAoB;QACpB,iBAAiB;KAClB,CAAC,CAAC;IAEH,MAAM,GAAG,IAAA,qCAAiB,EAAC,MAAM,EAAE;QACjC,OAAO;QACP,mBAAmB;QACnB,MAAM;QACN,wBAAwB;KACzB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,kBAAe,IAAA,oCAAmB,EAAC,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC"}
@@ -13,6 +13,6 @@ interface AddToSiriButtonProps {
13
13
  * @example
14
14
  * <AddToSiriButton intentId="create_errand" />
15
15
  */
16
- export declare function AddToSiriButton({ intentId, style, labelStyle, onPress }: AddToSiriButtonProps): any;
16
+ export declare function AddToSiriButton({ intentId, style, labelStyle, onPress }: AddToSiriButtonProps): import("react").JSX.Element | null;
17
17
  export {};
18
18
  //# sourceMappingURL=AddToSiriButton.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AddToSiriButton.d.ts","sourceRoot":"","sources":["../../../src/components/AddToSiriButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGhG,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,oBAAoB,OAkB7F"}
1
+ {"version":3,"file":"AddToSiriButton.d.ts","sourceRoot":"","sources":["../../../src/components/AddToSiriButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGhG,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,oBAAoB,sCAkB7F"}
@@ -8,5 +8,5 @@
8
8
  * // app/_layout.tsx (dev only)
9
9
  * { __DEV__ && <InvokeDebugger /> }
10
10
  */
11
- export declare function InvokeDebugger(): any;
11
+ export declare function InvokeDebugger(): import("react").JSX.Element | null;
12
12
  //# sourceMappingURL=InvokeDebugger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InvokeDebugger.d.ts","sourceRoot":"","sources":["../../../src/components/InvokeDebugger.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,wBAAgB,cAAc,QAI7B"}
1
+ {"version":3,"file":"InvokeDebugger.d.ts","sourceRoot":"","sources":["../../../src/components/InvokeDebugger.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,wBAAgB,cAAc,uCAI7B"}
@@ -15,6 +15,6 @@ interface ShortcutChipProps {
15
15
  * @example
16
16
  * <ShortcutChip shortcutId="quick_errand" label="Quick Errand" icon="📦" />
17
17
  */
18
- export declare function ShortcutChip({ shortcutId, label, icon, style, labelStyle, onPress }: ShortcutChipProps): any;
18
+ export declare function ShortcutChip({ shortcutId, label, icon, style, labelStyle, onPress }: ShortcutChipProps): import("react").JSX.Element;
19
19
  export {};
20
20
  //# sourceMappingURL=ShortcutChip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ShortcutChip.d.ts","sourceRoot":"","sources":["../../../src/components/ShortcutChip.tsx"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGtF,UAAU,iBAAiB;IACzB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,iBAAiB,OAuBtG"}
1
+ {"version":3,"file":"ShortcutChip.d.ts","sourceRoot":"","sources":["../../../src/components/ShortcutChip.tsx"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGtF,UAAU,iBAAiB;IACzB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,iBAAiB,+BAuBtG"}
@@ -0,0 +1,15 @@
1
+ import type { BackgroundIntentResult, ParameterValue } from '../types';
2
+ /**
3
+ * Register a handler for a background intent — one that runs without opening the app.
4
+ * The intent must have `openAppWhenRun: false` in app.json.
5
+ *
6
+ * iOS 16+ only. On Android, the handler fires normally (app opens first).
7
+ *
8
+ * @example
9
+ * useBackgroundIntent('mark_complete', async ({ errandId }) => {
10
+ * await api.markComplete(errandId as string);
11
+ * return { success: true, spokenResponse: 'Errand marked as complete.' };
12
+ * });
13
+ */
14
+ export declare function useBackgroundIntent(intentId: string, handler: (parameters: Record<string, ParameterValue>) => Promise<BackgroundIntentResult>): void;
15
+ //# sourceMappingURL=useBackgroundIntent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBackgroundIntent.d.ts","sourceRoot":"","sources":["../../../src/hooks/useBackgroundIntent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEvE;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,OAAO,CAAC,sBAAsB,CAAC,GACvF,IAAI,CAyBN"}
@@ -0,0 +1,41 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { registerBackgroundHandler, reportBackgroundResult, addIntentListener } from '../module';
3
+ /**
4
+ * Register a handler for a background intent — one that runs without opening the app.
5
+ * The intent must have `openAppWhenRun: false` in app.json.
6
+ *
7
+ * iOS 16+ only. On Android, the handler fires normally (app opens first).
8
+ *
9
+ * @example
10
+ * useBackgroundIntent('mark_complete', async ({ errandId }) => {
11
+ * await api.markComplete(errandId as string);
12
+ * return { success: true, spokenResponse: 'Errand marked as complete.' };
13
+ * });
14
+ */
15
+ export function useBackgroundIntent(intentId, handler) {
16
+ const handlerRef = useRef(handler);
17
+ handlerRef.current = handler;
18
+ useEffect(() => {
19
+ registerBackgroundHandler(intentId);
20
+ const sub = addIntentListener(async (intent) => {
21
+ var _a;
22
+ if (intent.intentId !== intentId || intent.source !== 'background')
23
+ return;
24
+ try {
25
+ const result = await handlerRef.current((_a = intent.parameters) !== null && _a !== void 0 ? _a : {});
26
+ reportBackgroundResult(intentId, result);
27
+ }
28
+ catch (e) {
29
+ reportBackgroundResult(intentId, {
30
+ success: false,
31
+ error: e instanceof Error ? e.message : 'Handler error',
32
+ spokenResponse: 'Sorry, something went wrong.',
33
+ });
34
+ }
35
+ });
36
+ return () => sub.remove();
37
+ // intentId is stable — re-register only if it changes
38
+ // eslint-disable-next-line react-hooks/exhaustive-deps
39
+ }, [intentId]);
40
+ }
41
+ //# sourceMappingURL=useBackgroundIntent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBackgroundIntent.js","sourceRoot":"","sources":["../../../src/hooks/useBackgroundIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGjG;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,OAAwF;IAExF,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,SAAS,CAAC,GAAG,EAAE;QACb,yBAAyB,CAAC,QAAQ,CAAC,CAAC;QAEpC,MAAM,GAAG,GAAG,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;;YAC7C,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY;gBAAE,OAAO;YAC3E,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAA,MAAM,CAAC,UAAU,mCAAI,EAAE,CAAC,CAAC;gBACjE,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC3C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,sBAAsB,CAAC,QAAQ,EAAE;oBAC/B,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;oBACvD,cAAc,EAAE,8BAA8B;iBAC/C,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAC5B,sDAAsD;QACtD,uDAAuD;IACvD,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ParameterValue } from '../types';
2
+ import { type InvokeError } from '../utils/invokeError';
3
+ export interface UseEntityQueryOptions {
4
+ /** Called when the handler throws. Receives a structured InvokeError. */
5
+ onError?: (error: InvokeError) => void;
6
+ }
7
+ /**
8
+ * Register a handler that Siri calls when it needs to resolve entity parameters.
9
+ * When the user says "Send my errand to [carrier name]", Siri fires this handler
10
+ * with the entity type and the user's spoken query — your app returns matching results.
11
+ *
12
+ * iOS 16.4+ only. No-op on Android.
13
+ *
14
+ * Errors from your handler are caught — Siri receives an empty result set instead of crashing.
15
+ *
16
+ * @param entityId - Must match an AppEntityDefinition id in app.json
17
+ * @param handler - Called with the user's query string, return matching entity records
18
+ *
19
+ * @example
20
+ * useEntityQuery('carrier', async (query) => {
21
+ * const carriers = await api.searchCarriers(query);
22
+ * return carriers.map((c) => ({ id: c.id, name: c.name, rating: c.rating }));
23
+ * });
24
+ */
25
+ export declare function useEntityQuery(entityId: string, handler: (query: string) => Promise<Record<string, ParameterValue>[]>, options?: UseEntityQueryOptions): void;
26
+ //# sourceMappingURL=useEntityQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEntityQuery.d.ts","sourceRoot":"","sources":["../../../src/hooks/useEntityQuery.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC,yEAAyE;IACzE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC,EACrE,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAsBN"}
@@ -0,0 +1,47 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { addIntentListener, provideEntityResults } from '../module';
3
+ import { reportInvokeError } from '../utils/invokeError';
4
+ /**
5
+ * Register a handler that Siri calls when it needs to resolve entity parameters.
6
+ * When the user says "Send my errand to [carrier name]", Siri fires this handler
7
+ * with the entity type and the user's spoken query — your app returns matching results.
8
+ *
9
+ * iOS 16.4+ only. No-op on Android.
10
+ *
11
+ * Errors from your handler are caught — Siri receives an empty result set instead of crashing.
12
+ *
13
+ * @param entityId - Must match an AppEntityDefinition id in app.json
14
+ * @param handler - Called with the user's query string, return matching entity records
15
+ *
16
+ * @example
17
+ * useEntityQuery('carrier', async (query) => {
18
+ * const carriers = await api.searchCarriers(query);
19
+ * return carriers.map((c) => ({ id: c.id, name: c.name, rating: c.rating }));
20
+ * });
21
+ */
22
+ export function useEntityQuery(entityId, handler, options = {}) {
23
+ const handlerRef = useRef(handler);
24
+ handlerRef.current = handler;
25
+ const optionsRef = useRef(options);
26
+ optionsRef.current = options;
27
+ useEffect(() => {
28
+ const sub = addIntentListener(async (intent) => {
29
+ var _a, _b, _c, _d;
30
+ if (intent.intentId !== `__entityQuery_${entityId}`)
31
+ return;
32
+ const query = (_b = (_a = intent.parameters) === null || _a === void 0 ? void 0 : _a.query) !== null && _b !== void 0 ? _b : '';
33
+ try {
34
+ const results = await handlerRef.current(query);
35
+ provideEntityResults(entityId, results);
36
+ }
37
+ catch (e) {
38
+ const err = reportInvokeError('ENTITY_QUERY_FAILED', e);
39
+ (_d = (_c = optionsRef.current).onError) === null || _d === void 0 ? void 0 : _d.call(_c, err);
40
+ provideEntityResults(entityId, []);
41
+ }
42
+ });
43
+ return () => sub.remove();
44
+ // eslint-disable-next-line react-hooks/exhaustive-deps
45
+ }, [entityId]);
46
+ }
47
+ //# sourceMappingURL=useEntityQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEntityQuery.js","sourceRoot":"","sources":["../../../src/hooks/useEntityQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAoB,MAAM,sBAAsB,CAAC;AAO3E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,OAAqE,EACrE,UAAiC,EAAE;IAEnC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,GAAG,GAAG,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;;YAC7C,IAAI,MAAM,CAAC,QAAQ,KAAK,iBAAiB,QAAQ,EAAE;gBAAE,OAAO;YAC5D,MAAM,KAAK,GAAG,MAAC,MAAA,MAAM,CAAC,UAAU,0CAAE,KAAgB,mCAAI,EAAE,CAAC;YACzD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAChD,oBAAoB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC1C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,GAAG,GAAG,iBAAiB,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC;gBACxD,MAAA,MAAA,UAAU,CAAC,OAAO,EAAC,OAAO,mDAAG,GAAG,CAAC,CAAC;gBAClC,oBAAoB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YACrC,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAC5B,uDAAuD;IACvD,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type FocusMode } from '../module';
1
+ import type { FocusMode } from '../types';
2
2
  /**
3
3
  * Returns the current iOS Focus mode. Re-reads when the app becomes active.
4
4
  * Returns null on Android or when no Focus is active.
@@ -1 +1 @@
1
- {"version":3,"file":"useFocusFilter.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFocusFilter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,SAAS,CAa1C"}
1
+ {"version":3,"file":"useFocusFilter.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFocusFilter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,SAAS,CAa1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"useFocusFilter.js","sourceRoot":"","sources":["../../../src/hooks/useFocusFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAuB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAkB,MAAM,WAAW,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAY,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,GAAG,GAAG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,KAAqB,EAAE,EAAE;YACxE,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACvB,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"useFocusFilter.js","sourceRoot":"","sources":["../../../src/hooks/useFocusFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAuB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGzC;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAY,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,GAAG,GAAG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,KAAqB,EAAE,EAAE;YACxE,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACvB,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { ParameterValue } from '../types';
2
+ export interface UseFocusFilterStateResult {
3
+ /** True when the user has applied a Focus that includes this filter */
4
+ isActive: boolean;
5
+ /** Parameters the user configured in the Focus filter sheet */
6
+ parameters: Record<string, ParameterValue>;
7
+ /** Call to signal the filter has been applied successfully */
8
+ confirm: () => void;
9
+ /** Call to signal the filter failed to apply */
10
+ reject: () => void;
11
+ }
12
+ /**
13
+ * Reads the current state of a registered Focus filter.
14
+ * Fires when the user enables/disables a Focus mode that includes this app's filter.
15
+ * iOS 16+ only. Returns a no-op result on Android and older iOS.
16
+ *
17
+ * @param filterId - Must match the FocusFilterDefinition id in app.json
18
+ *
19
+ * @example
20
+ * const { isActive, parameters, confirm } = useFocusFilterState('work-mode');
21
+ * useEffect(() => {
22
+ * if (!isActive) return;
23
+ * hidePersonalErrands(parameters.hidePersonal as boolean);
24
+ * confirm();
25
+ * }, [isActive]);
26
+ */
27
+ export declare function useFocusFilterState(filterId: string): UseFocusFilterStateResult;
28
+ //# sourceMappingURL=useFocusFilterState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFocusFilterState.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFocusFilterState.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,yBAAyB;IACxC,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3C,8DAA8D;IAC9D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gDAAgD;IAChD,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,yBAAyB,CA8B/E"}