@kosdev-code/kos-dispense-sdk 3.0.27 → 3.0.29

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 (190) hide show
  1. package/.kos.json +7 -0
  2. package/{dispense-registration-manager-Dtb31fcI.cjs → dispense-registration-manager-CfWgJqfq.cjs} +590 -172
  3. package/dispense-registration-manager-CfWgJqfq.cjs.map +1 -0
  4. package/{dispense-registration-manager-Da9CW_cN.js → dispense-registration-manager-DtN0T_JG.js} +623 -205
  5. package/dispense-registration-manager-DtN0T_JG.js.map +1 -0
  6. package/{extension-utils-Cfhe358W.cjs → extension-utils-BWYG2dYG.cjs} +2 -2
  7. package/extension-utils-BWYG2dYG.cjs.map +1 -0
  8. package/{extension-utils-D_dnBLH6.js → extension-utils-BoXtjU5_.js} +2 -2
  9. package/extension-utils-BoXtjU5_.js.map +1 -0
  10. package/index.cjs +7 -5
  11. package/index.cjs.map +1 -1
  12. package/index.js +67 -65
  13. package/index.js.map +1 -1
  14. package/models/models/assembly/assembly-model.d.ts +8 -0
  15. package/models/models/assembly/assembly-model.d.ts.map +1 -1
  16. package/models/models/assembly/assembly-registration.d.ts +2 -0
  17. package/models/models/assembly/assembly-registration.d.ts.map +1 -1
  18. package/models/models/assembly/board-utils.d.ts.map +1 -1
  19. package/models/models/assembly/nozzle-utils.d.ts.map +1 -1
  20. package/models/models/assembly/pump-utils.d.ts.map +1 -1
  21. package/models/models/assembly/services/assembly-services.d.ts.map +1 -1
  22. package/models/models/assembly/types/index.d.ts +6 -0
  23. package/models/models/availability/availability-model.d.ts +2 -0
  24. package/models/models/availability/availability-model.d.ts.map +1 -1
  25. package/models/models/availability/types/index.d.ts +4 -0
  26. package/models/models/board/board-container-model.d.ts +8 -0
  27. package/models/models/board/board-container-model.d.ts.map +1 -1
  28. package/models/models/board/board-container-registration.d.ts +2 -0
  29. package/models/models/board/board-container-registration.d.ts.map +1 -1
  30. package/models/models/board/board-registration.d.ts +2 -0
  31. package/models/models/board/board-registration.d.ts.map +1 -1
  32. package/models/models/board/types/index.d.ts +12 -0
  33. package/models/models/cui-kit-state/cui-kit-state-model.d.ts +133 -0
  34. package/models/models/cui-kit-state/cui-kit-state-model.d.ts.map +1 -0
  35. package/models/models/cui-kit-state/index.d.ts +4 -0
  36. package/models/models/cui-kit-state/index.d.ts.map +1 -0
  37. package/models/models/cui-kit-state/types/index.d.ts +82 -0
  38. package/models/models/device-assembly/device-assembly-model.d.ts +4 -0
  39. package/models/models/device-assembly/device-assembly-model.d.ts.map +1 -1
  40. package/models/models/device-assembly/device-assembly-registration.d.ts +2 -0
  41. package/models/models/device-assembly/device-assembly-registration.d.ts.map +1 -1
  42. package/models/models/device-assembly/types/index.d.ts +4 -0
  43. package/models/models/generic-pour/generic-pour-model.d.ts +16 -0
  44. package/models/models/generic-pour/generic-pour-model.d.ts.map +1 -1
  45. package/models/models/generic-pour/generic-pour-registration.d.ts +2 -0
  46. package/models/models/generic-pour/generic-pour-registration.d.ts.map +1 -1
  47. package/models/models/generic-pour/types/index.d.ts +4 -0
  48. package/models/models/holder/holder-model.d.ts +6 -0
  49. package/models/models/holder/holder-model.d.ts.map +1 -1
  50. package/models/models/holder/services/holder-services.d.ts.map +1 -1
  51. package/models/models/holder/types/index.d.ts +6 -0
  52. package/models/models/holder-container/holder-container-model.d.ts +2 -0
  53. package/models/models/holder-container/holder-container-model.d.ts.map +1 -1
  54. package/models/models/holder-container/types/index.d.ts +14 -0
  55. package/models/models/index.d.ts +1 -0
  56. package/models/models/index.d.ts.map +1 -1
  57. package/models/models/ingredient/ingredient-model.d.ts +2 -0
  58. package/models/models/ingredient/ingredient-model.d.ts.map +1 -1
  59. package/models/models/ingredient/types/index.d.ts +4 -1
  60. package/models/models/ingredient-container/ingredient-container-model.d.ts +2 -0
  61. package/models/models/ingredient-container/ingredient-container-model.d.ts.map +1 -1
  62. package/models/models/ingredient-container/types/index.d.ts +6 -0
  63. package/models/models/nozzle/nozzle-model.d.ts +4 -2
  64. package/models/models/nozzle/nozzle-model.d.ts.map +1 -1
  65. package/models/models/nozzle/types/index.d.ts +6 -0
  66. package/models/models/pump/pump-model.d.ts +2 -0
  67. package/models/models/pump/pump-model.d.ts.map +1 -1
  68. package/models/models/pump/types/index.d.ts +6 -0
  69. package/models/models/pump-container/pump-container-model.d.ts +6 -0
  70. package/models/models/pump-container/pump-container-model.d.ts.map +1 -1
  71. package/models/models/pump-container/types/index.d.ts +6 -0
  72. package/models/utils/dispense-registration-manager.d.ts +29 -4
  73. package/models/utils/dispense-registration-manager.d.ts.map +1 -1
  74. package/models/utils/extension-utils.d.ts +22 -0
  75. package/models/utils/extension-utils.d.ts.map +1 -1
  76. package/models/utils/pour-context.d.ts +8 -0
  77. package/models/utils/pour-context.d.ts.map +1 -0
  78. package/models/utils/service.d.ts +1 -1
  79. package/models/utils/services/dispense/1.6.5/service.d.ts +1 -1
  80. package/models/utils/services/dispense/1.8.1/service.d.ts +1 -1
  81. package/models/utils/services/dispense/daily/service.d.ts +1 -1
  82. package/models.cjs +4 -2
  83. package/models.cjs.map +1 -1
  84. package/models.js +17 -15
  85. package/package.json +2 -2
  86. package/{pump-provider-uNNMh9uh.cjs → pump-provider-B4WR3LiY.cjs} +402 -443
  87. package/pump-provider-B4WR3LiY.cjs.map +1 -0
  88. package/{pump-provider-BQmCKz7S.js → pump-provider-CPUsLke5.js} +448 -489
  89. package/pump-provider-CPUsLke5.js.map +1 -0
  90. package/ui/contexts/assembly/assembly-provider.d.ts +8 -0
  91. package/ui/contexts/assembly/assembly-provider.d.ts.map +1 -1
  92. package/ui/contexts/availability/availability-provider.d.ts +8 -0
  93. package/ui/contexts/availability/availability-provider.d.ts.map +1 -1
  94. package/ui/contexts/board/board-provider.d.ts +8 -0
  95. package/ui/contexts/board/board-provider.d.ts.map +1 -1
  96. package/ui/contexts/board-container/board-container-provider.d.ts +8 -0
  97. package/ui/contexts/board-container/board-container-provider.d.ts.map +1 -1
  98. package/ui/contexts/cui-kit/cui-kit.d.ts +16 -1
  99. package/ui/contexts/cui-kit/cui-kit.d.ts.map +1 -1
  100. package/ui/contexts/device-assembly/device-assembly-provider.d.ts +8 -0
  101. package/ui/contexts/device-assembly/device-assembly-provider.d.ts.map +1 -1
  102. package/ui/contexts/holder/holder-provider.d.ts +8 -0
  103. package/ui/contexts/holder/holder-provider.d.ts.map +1 -1
  104. package/ui/contexts/holder-container/holder-container-provider.d.ts +8 -0
  105. package/ui/contexts/holder-container/holder-container-provider.d.ts.map +1 -1
  106. package/ui/contexts/ingredient/ingredient-provider.d.ts +8 -0
  107. package/ui/contexts/ingredient/ingredient-provider.d.ts.map +1 -1
  108. package/ui/contexts/ingredient-container/ingredient-container-provider.d.ts +8 -0
  109. package/ui/contexts/ingredient-container/ingredient-container-provider.d.ts.map +1 -1
  110. package/ui/contexts/nozzle/nozzle-provider.d.ts +8 -0
  111. package/ui/contexts/nozzle/nozzle-provider.d.ts.map +1 -1
  112. package/ui/contexts/pump/pump-provider.d.ts +8 -0
  113. package/ui/contexts/pump/pump-provider.d.ts.map +1 -1
  114. package/ui/hooks/assembly/use-assembly.d.ts +4 -0
  115. package/ui/hooks/assembly/use-assembly.d.ts.map +1 -1
  116. package/ui/hooks/assembly/with-assembly.d.ts +4 -0
  117. package/ui/hooks/assembly/with-assembly.d.ts.map +1 -1
  118. package/ui/hooks/availability/use-availability.d.ts +4 -0
  119. package/ui/hooks/availability/use-availability.d.ts.map +1 -1
  120. package/ui/hooks/board/use-board.d.ts +4 -0
  121. package/ui/hooks/board/use-board.d.ts.map +1 -1
  122. package/ui/hooks/board/with-board.d.ts +4 -0
  123. package/ui/hooks/board/with-board.d.ts.map +1 -1
  124. package/ui/hooks/board-container/use-board-container.d.ts +4 -0
  125. package/ui/hooks/board-container/use-board-container.d.ts.map +1 -1
  126. package/ui/hooks/board-container/with-board-container.d.ts +4 -0
  127. package/ui/hooks/board-container/with-board-container.d.ts.map +1 -1
  128. package/ui/hooks/cui-kit/use-ambient-attract-timers.d.ts.map +1 -1
  129. package/ui/hooks/cui-kit/use-brands.d.ts.map +1 -1
  130. package/ui/hooks/cui-kit/use-cui-kit.d.ts +50 -5
  131. package/ui/hooks/cui-kit/use-cui-kit.d.ts.map +1 -1
  132. package/ui/hooks/cui-kit/use-default-cui-kit-lifecycle.d.ts.map +1 -1
  133. package/ui/hooks/cui-kit/use-dispense-timers.d.ts.map +1 -1
  134. package/ui/hooks/device-assembly/use-device-assembly.d.ts +4 -0
  135. package/ui/hooks/device-assembly/use-device-assembly.d.ts.map +1 -1
  136. package/ui/hooks/device-assembly/with-device-assembly.d.ts +4 -0
  137. package/ui/hooks/device-assembly/with-device-assembly.d.ts.map +1 -1
  138. package/ui/hooks/generic-pour/use-generic-pour.d.ts +4 -0
  139. package/ui/hooks/generic-pour/use-generic-pour.d.ts.map +1 -1
  140. package/ui/hooks/generic-pour/with-generic-pour.d.ts +4 -0
  141. package/ui/hooks/generic-pour/with-generic-pour.d.ts.map +1 -1
  142. package/ui/hooks/holder/use-holder.d.ts +4 -0
  143. package/ui/hooks/holder/use-holder.d.ts.map +1 -1
  144. package/ui/hooks/holder/with-holder.d.ts +4 -0
  145. package/ui/hooks/holder/with-holder.d.ts.map +1 -1
  146. package/ui/hooks/holder-container/use-holder-container.d.ts +4 -0
  147. package/ui/hooks/holder-container/use-holder-container.d.ts.map +1 -1
  148. package/ui/hooks/holder-container/with-holder-container.d.ts +4 -0
  149. package/ui/hooks/holder-container/with-holder-container.d.ts.map +1 -1
  150. package/ui/hooks/ingredient/use-ingredient-pour.d.ts +7 -1
  151. package/ui/hooks/ingredient/use-ingredient-pour.d.ts.map +1 -1
  152. package/ui/hooks/ingredient/use-ingredient.d.ts +4 -0
  153. package/ui/hooks/ingredient/use-ingredient.d.ts.map +1 -1
  154. package/ui/hooks/ingredient/with-ingredient.d.ts +4 -0
  155. package/ui/hooks/ingredient/with-ingredient.d.ts.map +1 -1
  156. package/ui/hooks/ingredient-container/use-ingredient-container.d.ts +4 -0
  157. package/ui/hooks/ingredient-container/use-ingredient-container.d.ts.map +1 -1
  158. package/ui/hooks/ingredient-container/with-ingredient-container.d.ts +4 -0
  159. package/ui/hooks/ingredient-container/with-ingredient-container.d.ts.map +1 -1
  160. package/ui/hooks/nozzle/use-nozzle.d.ts +4 -0
  161. package/ui/hooks/nozzle/use-nozzle.d.ts.map +1 -1
  162. package/ui/hooks/nozzle/with-nozzle.d.ts +4 -0
  163. package/ui/hooks/nozzle/with-nozzle.d.ts.map +1 -1
  164. package/ui/hooks/nozzle-pour/use-nozzle-pour.d.ts +7 -1
  165. package/ui/hooks/nozzle-pour/use-nozzle-pour.d.ts.map +1 -1
  166. package/ui/hooks/pour/use-pour.d.ts.map +1 -1
  167. package/ui/hooks/utils/pour-strategy/hold-to-pour-intent-strategy.d.ts +4 -0
  168. package/ui/hooks/utils/pour-strategy/hold-to-pour-intent-strategy.d.ts.map +1 -1
  169. package/ui/hooks/utils/pour-strategy/hold-to-pour-strategy.d.ts +4 -0
  170. package/ui/hooks/utils/pour-strategy/hold-to-pour-strategy.d.ts.map +1 -1
  171. package/ui/hooks/utils/pour-strategy/pour-strategy.d.ts +10 -0
  172. package/ui/hooks/utils/pour-strategy/pour-strategy.d.ts.map +1 -1
  173. package/ui/hooks/utils/pour-strategy/tap-or-hold-to-pour-intent-strategy.d.ts +4 -0
  174. package/ui/hooks/utils/pour-strategy/tap-or-hold-to-pour-intent-strategy.d.ts.map +1 -1
  175. package/ui/hooks/utils/pour-strategy/tap-to-pour-intent-strategy.d.ts +4 -0
  176. package/ui/hooks/utils/pour-strategy/tap-to-pour-intent-strategy.d.ts.map +1 -1
  177. package/ui/hooks/utils/pour-strategy/tap-to-pour-strategy.d.ts +4 -0
  178. package/ui/hooks/utils/pour-strategy/tap-to-pour-strategy.d.ts.map +1 -1
  179. package/ui/utils/pour-context.d.ts +1 -7
  180. package/ui/utils/pour-context.d.ts.map +1 -1
  181. package/ui.cjs +3 -2
  182. package/ui.cjs.map +1 -1
  183. package/ui.js +49 -48
  184. package/ui.js.map +1 -1
  185. package/dispense-registration-manager-Da9CW_cN.js.map +0 -1
  186. package/dispense-registration-manager-Dtb31fcI.cjs.map +0 -1
  187. package/extension-utils-Cfhe358W.cjs.map +0 -1
  188. package/extension-utils-D_dnBLH6.js.map +0 -1
  189. package/pump-provider-BQmCKz7S.js.map +0 -1
  190. package/pump-provider-uNNMh9uh.cjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  const jsxRuntime = require("@emotion/react/jsx-runtime");
3
3
  const kosUiSdk = require("@kosdev-code/kos-ui-sdk");
4
- const dispenseRegistrationManager = require("./dispense-registration-manager-Dtb31fcI.cjs");
5
4
  const React = require("react");
5
+ const dispenseRegistrationManager = require("./dispense-registration-manager-CfWgJqfq.cjs");
6
6
  const useAssembly = () => {
7
7
  const modelId = dispenseRegistrationManager.Assembly.type;
8
8
  const result = kosUiSdk.useKosModel({
@@ -146,6 +146,7 @@ const useBeverages = ({
146
146
  clearBeverage
147
147
  };
148
148
  };
149
+ const log$4 = kosUiSdk.KosLog.createLogger({ group: kosUiSdk.LogGroup.ui, name: "use-brands" });
149
150
  const useBrands = ({
150
151
  onBrandSelected,
151
152
  onBrandCleared,
@@ -162,9 +163,7 @@ const useBrands = ({
162
163
  async (brand, context, forceUpdate) => {
163
164
  setSelectedBrand(brand);
164
165
  if (forceUpdate) {
165
- kosUiSdk.KosLog.warn(
166
- `forceUpdate is not currently supported when setting brand`
167
- );
166
+ log$4.warn(`forceUpdate is not currently supported when setting brand`);
168
167
  }
169
168
  nozzle?.setSelectedBrand(brand, context);
170
169
  onBrandSelected?.(brand);
@@ -193,30 +192,39 @@ const useBrands = ({
193
192
  clearBrand
194
193
  };
195
194
  };
196
- class PourContext {
197
- _data = /* @__PURE__ */ new Map();
198
- get(key) {
199
- return this._data.get(key);
200
- }
201
- set(key, value) {
202
- this._data.set(key, value);
203
- }
204
- remove(key) {
205
- this._data.delete(key);
206
- }
207
- has(key) {
208
- return this._data.has(key);
209
- }
210
- }
211
195
  const logger$7 = kosUiSdk.KosLog.createLogger({
212
- name: "HoldToPourStrategy",
213
- group: "kos-hooks"
196
+ group: kosUiSdk.LogGroup.ui,
197
+ name: "HoldToPourIntentStrategy"
198
+ });
199
+ const HoldToPourIntentStrategy = {
200
+ name: "HoldToPourIntentStrategy",
201
+ requiresHold: true,
202
+ async initiate(model, intent) {
203
+ if (!model?.canPour) {
204
+ logger$7.debug(`${model?.id} cannot pour. Returning early.`);
205
+ return;
206
+ }
207
+ if (intent) {
208
+ logger$7.debug(`performing intent: ${intent}`);
209
+ await model?.performIntent(intent);
210
+ } else {
211
+ logger$7.debug("no intent provided. Returning early.");
212
+ }
213
+ },
214
+ async initiateEnded(nozzle) {
215
+ await nozzle?.cancelPour();
216
+ }
217
+ };
218
+ const logger$6 = kosUiSdk.KosLog.createLogger({
219
+ group: kosUiSdk.LogGroup.ui,
220
+ name: "HoldToPourStrategy"
214
221
  });
215
222
  const HoldToPourStrategy = {
216
223
  name: "HoldToPourStrategy",
224
+ requiresHold: true,
217
225
  async initiate(nozzle) {
218
226
  if (!nozzle?.canPour) {
219
- logger$7.debug(`Nozzle ${nozzle?.id} cannot pour. Returning early.`);
227
+ logger$6.debug(`Nozzle ${nozzle?.id} cannot pour. Returning early.`);
220
228
  return;
221
229
  }
222
230
  await nozzle?.pour();
@@ -225,297 +233,191 @@ const HoldToPourStrategy = {
225
233
  await nozzle?.cancelPour();
226
234
  }
227
235
  };
228
- const logger$6 = kosUiSdk.KosLog.createLogger({
229
- name: "useNozzlePour",
230
- group: "kos-hooks"
236
+ const logger$5 = kosUiSdk.KosLog.createLogger({
237
+ group: kosUiSdk.LogGroup.ui,
238
+ name: "TapOrHoldIntentStrategy"
231
239
  });
232
- const useNozzlePour = ({
233
- onPour,
234
- onPourCancel,
235
- onBeforePour,
236
- onBeforePourRejected,
237
- pourContext,
238
- strategy = HoldToPourStrategy
239
- }) => {
240
- const { model: nozzle } = useNozzleContext();
241
- const [context, _setContext] = React.useState(
242
- pourContext || new PourContext()
243
- );
244
- const handlePour = React.useCallback(async () => {
245
- const canPour = onBeforePour ? await onBeforePour?.(context) : true;
246
- if (canPour) {
247
- logger$6.debug(
248
- `[${strategy?.name}] - Pour initiated for nozzle ${nozzle?.id}.`
249
- );
250
- strategy?.initiate(nozzle);
251
- onPour?.();
240
+ class TapOrHoldIntentStrategy {
241
+ intent;
242
+ name = "TapOrHoldIntentStrategy";
243
+ isHold = false;
244
+ disposer = null;
245
+ constructor(intent) {
246
+ this.intent = intent;
247
+ }
248
+ async initiate(model, intent = this.intent) {
249
+ this.isHold = false;
250
+ this.disposer = setTimeout(() => {
251
+ this.isHold = true;
252
+ }, 250);
253
+ if (model?.isPouring && !this.isHold) {
254
+ logger$5.debug(`additional tap detected. cancelling pour`);
255
+ await model.cancelPour();
256
+ return;
257
+ }
258
+ if (!model?.canPour) {
259
+ logger$5.debug(`${model?.id} cannot pour. Returning early.`);
260
+ return;
261
+ }
262
+ if (intent) {
263
+ logger$5.debug(`performing intent: ${intent}`);
264
+ await model?.performIntent(intent);
252
265
  } else {
253
- logger$6.debug(
254
- `[${strategy?.name}] - Did not pass onBeforePour gate for nozzle ${nozzle?.id}. Cancelling pour.`
255
- );
256
- onBeforePourRejected?.();
266
+ logger$5.debug("no intent provided. Returning early.");
257
267
  }
258
- }, [
259
- onPour,
260
- nozzle,
261
- strategy,
262
- onBeforePour,
263
- onPourCancel,
264
- context,
265
- onBeforePourRejected
266
- ]);
267
- const handleCancelPour = React.useCallback(() => {
268
- logger$6.debug(
269
- `[${strategy?.name}] - Pour initiate ended called for nozzle ${nozzle?.id}.`
270
- );
271
- strategy?.initiateEnded?.(nozzle);
272
- onPourCancel?.();
273
- }, [onPourCancel, nozzle, strategy]);
274
- const forceCancelPour = React.useCallback(() => {
275
- logger$6.debug(`Force cancelling pour for nozzle ${nozzle?.id}.`);
276
- nozzle?.cancelPour();
277
- onPourCancel?.();
278
- }, [onPourCancel, nozzle]);
279
- const handleUpdateContext = React.useCallback(
280
- (key, value) => {
281
- context.set(key, value);
282
- },
283
- [context]
284
- );
285
- const handleRemoveFromContext = React.useCallback(
286
- (key) => {
287
- context.remove(key);
288
- },
289
- [context]
290
- );
291
- const handlers = kosUiSdk.usePressGesture({
292
- onPressed: handlePour,
293
- onRelease: handleCancelPour
294
- });
295
- return {
296
- handlers: handlers.dom,
297
- cancel: forceCancelPour,
298
- updatePourContext: handleUpdateContext,
299
- removeFromPourContext: handleRemoveFromContext,
300
- status: nozzle
301
- };
268
+ }
269
+ async initiateEnded(nozzle) {
270
+ if (this.disposer) clearTimeout(this.disposer);
271
+ this.disposer = null;
272
+ if (!this.isHold) {
273
+ logger$5.debug("Tap detected. don't cancel and return.");
274
+ return true;
275
+ }
276
+ await nozzle?.cancelPour();
277
+ return false;
278
+ }
279
+ }
280
+ const logger$4 = kosUiSdk.KosLog.createLogger({
281
+ group: kosUiSdk.LogGroup.ui,
282
+ name: "TapToPourIntentStrategy"
283
+ });
284
+ const TapToPourIntentStrategy = {
285
+ name: "TapToPourIntentStrategy",
286
+ async initiate(model, intent) {
287
+ if (model?.isPouring) {
288
+ logger$4.debug(`Nozzle ${model?.id} is already pouring. cancelling pour`);
289
+ await model.cancelPour();
290
+ return;
291
+ }
292
+ if (!model?.canPour) {
293
+ logger$4.debug(`Nozzle ${model?.id} cannot pour. Returning early.`);
294
+ return;
295
+ }
296
+ if (intent) {
297
+ logger$4.debug(`performing intent: ${intent}`);
298
+ await model?.performIntent(intent);
299
+ } else {
300
+ logger$4.debug("no intent provided. Returning early.");
301
+ }
302
+ },
303
+ async initiateEnded(_nozzle) {
304
+ return true;
305
+ }
302
306
  };
303
- const useFlavors = ({
304
- onFlavorSelected,
305
- onFlavorCleared,
306
- companionType
307
- }) => {
308
- const { model: nozzle } = useNozzleContext();
309
- const flavors = React.useMemo(
310
- () => nozzle?.getGroupAvailabilityItems("flavors").filter((f) => f.visible) ?? [],
311
- [nozzle]
312
- );
313
- const companions = React.useMemo(() => {
314
- if (!companionType) return [];
315
- return flavors.map(
316
- (flavor) => kosUiSdk.getKosCompanionModel(flavor, companionType)
317
- );
318
- }, [flavors, companionType]);
319
- const [selectedFlavors, setSelectedFlavors] = React.useState([]);
320
- const selectFlavor = React.useCallback(
321
- async (flavor, context, forceUpdate) => {
322
- setSelectedFlavors(
323
- (previous) => previous?.includes(flavor) ? [...previous.filter((p) => p !== flavor)] : [...previous ?? [], flavor]
324
- );
325
- if (nozzle?.selectedPourable) {
326
- const { beverage } = nozzle.selectedPourable;
327
- await nozzle.setSelectedPourable(
328
- {
329
- beverage,
330
- additional: selectedFlavors ?? [],
331
- context
332
- },
333
- forceUpdate
334
- );
335
- }
336
- onFlavorSelected?.(flavor, selectedFlavors ?? []);
337
- },
338
- [nozzle, onFlavorSelected, selectedFlavors]
339
- );
340
- const clear = React.useCallback(async () => {
341
- setSelectedFlavors([]);
342
- if (nozzle?.selectedPourable) {
343
- const { beverage } = nozzle.selectedPourable;
344
- nozzle.setSelectedPourable({ beverage });
345
- onFlavorCleared?.();
307
+ const logger$3 = kosUiSdk.KosLog.createLogger({
308
+ group: kosUiSdk.LogGroup.ui,
309
+ name: "HoldToPourStrategy"
310
+ });
311
+ const TapToPourStrategy = {
312
+ name: "TapToPourStrategy",
313
+ async initiate(nozzle) {
314
+ if (nozzle?.isPouring) {
315
+ logger$3.debug(`Nozzle ${nozzle?.id} is already pouring. cancelling pour`);
316
+ await nozzle.cancelPour();
317
+ return;
346
318
  }
347
- }, [nozzle, onFlavorCleared]);
348
- return {
349
- flavors,
350
- flavorCompanions: companions,
351
- selectFlavor,
352
- selectedFlavors,
353
- clearFlavors: clear
354
- };
319
+ if (!nozzle?.canPour) {
320
+ logger$3.debug(`Nozzle ${nozzle?.id} cannot pour. Returning early.`);
321
+ return;
322
+ }
323
+ await nozzle?.pour();
324
+ },
325
+ async initiateEnded(_nozzle) {
326
+ return true;
327
+ }
355
328
  };
356
329
  const DISPENSE_GROUP_BRAND = "brands";
357
330
  const DISPENSE_GROUP_BEVERAGE = "beverages";
358
331
  const DISPENSE_GROUP_FLAVOR = "flavors";
359
- const log$2 = kosUiSdk.KosLog.createLogger({ name: "use-cui-kit" });
332
+ const log$3 = kosUiSdk.KosLog.createLogger({ group: kosUiSdk.LogGroup.ui, name: "use-cui-kit" });
360
333
  const useCuiKit = ({
361
- initialGroup = DISPENSE_GROUP_BRAND,
334
+ initialGroup,
335
+ steps,
362
336
  options = {}
363
337
  }) => {
364
- const [currentGroup, setCurrentGroup] = React.useState(initialGroup);
365
338
  const { model: nozzle } = useNozzleContext();
366
339
  const timersRef = React.useRef([]);
367
- const updatePourContext = React.useRef();
368
- const removeFromPourContext = React.useRef();
369
- const onBrandSelected = React.useCallback(
370
- (model) => {
371
- setCurrentGroup(DISPENSE_GROUP_BEVERAGE);
372
- const topic = `/kos/dispense/${nozzle?.path}/brand/selected/`;
373
- kosUiSdk.EventBus.publish(topic, model);
374
- },
375
- [nozzle?.path]
376
- );
377
- const onBrandCleared = React.useCallback(() => {
378
- const topic = `/kos/dispense/${nozzle?.path}/brand/cleared/`;
379
- kosUiSdk.EventBus.publish(topic, {});
380
- }, [nozzle?.path]);
381
- const onBeverageListUpdated = React.useCallback(
382
- (beverages2) => {
383
- const topic = `/kos/dispense/${nozzle?.path}/beverage/list/updated/`;
384
- kosUiSdk.EventBus.publish(topic, beverages2);
385
- },
386
- [nozzle?.path]
387
- );
388
- const onBeverageSelected = React.useCallback(
389
- (model) => {
390
- setCurrentGroup(DISPENSE_GROUP_FLAVOR);
391
- updatePourContext.current?.("selectedBeverage", model);
392
- const topic = `/kos/dispense/${nozzle?.path}/beverage/selected/`;
393
- kosUiSdk.EventBus.publish(topic, model);
394
- },
395
- [nozzle?.path]
396
- );
397
- const onBeverageCleared = React.useCallback(() => {
398
- const topic = `/kos/dispense/${nozzle?.path}/beverage/cleared/`;
399
- removeFromPourContext.current?.("selectedBeverage");
400
- kosUiSdk.EventBus.publish(topic, {});
401
- }, [nozzle?.path]);
402
- const onFlavorSelected = React.useCallback(
403
- (model) => {
404
- const topic = `/kos/dispense/${nozzle?.path}/flavor/selected/`;
405
- kosUiSdk.EventBus.publish(topic, model);
406
- },
407
- [nozzle?.path]
408
- );
409
- const onFlavorCleared = React.useCallback(() => {
410
- const topic = `/kos/dispense/${nozzle?.path}/flavor/cleared/`;
411
- kosUiSdk.EventBus.publish(topic, {});
412
- }, [nozzle?.path]);
413
- const onPour = React.useCallback(() => {
414
- const topic = `/kos/dispense/${nozzle?.path}/pour/`;
415
- kosUiSdk.EventBus.publish(topic, {});
416
- }, [nozzle?.path]);
417
- const handleBeforePour = React.useCallback(
418
- async (context) => {
419
- const topic = `/kos/dispense/${nozzle?.path}/pre/pour/`;
420
- kosUiSdk.EventBus.publish(topic, {});
421
- return await onBeforePour?.(context) || true;
340
+ const kit = React.useMemo(() => {
341
+ if (!nozzle) return void 0;
342
+ try {
343
+ return dispenseRegistrationManager.CuiKitState.instance(dispenseRegistrationManager.cuiKitId(nozzle.path)).options({
344
+ nozzlePath: nozzle.path,
345
+ initialGroup: steps ? initialGroup : initialGroup ?? DISPENSE_GROUP_BRAND,
346
+ steps,
347
+ companionTypes: options.companionTypes,
348
+ pour: { strategy: options.pour?.strategy ?? HoldToPourStrategy },
349
+ onPourComplete: options.onPourComplete
350
+ }).build();
351
+ } catch (error) {
352
+ throw new Error(
353
+ `The CUI Kit models are not registered: call KosModelRegistry.cuiKit.models() in the app's registration chain (${error.message})`
354
+ );
355
+ }
356
+ }, [nozzle]);
357
+ const [ready, setReady] = React.useState(false);
358
+ const [, setVersion] = React.useState(0);
359
+ React.useEffect(() => {
360
+ if (!kit) return void 0;
361
+ let dispose;
362
+ let cancelled = false;
363
+ let attached = false;
364
+ kosUiSdk.whenReady(kit).then(() => {
365
+ if (cancelled) return;
366
+ attached = true;
367
+ if (kit.attach()) {
368
+ kit.reset();
369
+ }
370
+ setReady(true);
371
+ dispose = kosUiSdk.kosAutoEffect(() => {
372
+ readKitState(kit);
373
+ setVersion((version) => version + 1);
374
+ });
375
+ });
376
+ return () => {
377
+ cancelled = true;
378
+ dispose?.();
379
+ if (attached) kit.detach();
380
+ };
381
+ }, [kit]);
382
+ const updateOnBeforePour = React.useCallback(
383
+ (callback) => {
384
+ kit?.setBeforePour(callback);
422
385
  },
423
- [nozzle?.path]
386
+ [kit]
424
387
  );
425
- const handleBeforePourRejected = React.useCallback(async () => {
426
- const topic = `/kos/dispense/${nozzle?.path}/pre/pour/rejected/`;
427
- kosUiSdk.EventBus.publish(topic, {});
428
- }, [nozzle?.path]);
429
- const onPourCancel = React.useCallback(() => {
430
- const topic = `/kos/dispense/${nozzle?.path}/pour/cancel/`;
431
- kosUiSdk.EventBus.publish(topic, {});
432
- }, [nozzle?.path]);
433
- const { brands, selectBrand, selectedBrand, clearBrand, brandCompanions } = useBrands({
434
- companionType: options.companionTypes?.brand,
435
- onBrandSelected,
436
- onBrandCleared
388
+ const gesture = kosUiSdk.usePressGesture({
389
+ onPressed: () => void kit?.pressPour(),
390
+ onRelease: () => kit?.releasePour()
437
391
  });
438
- const {
439
- beverages,
440
- selectBeverage,
441
- selectedBeverage,
442
- clearBeverage,
443
- beverageCompanions
444
- } = useBeverages({
445
- companionType: options.companionTypes?.beverage,
446
- onBeverageSelected,
447
- onClearBeverage: onBeverageCleared,
448
- onBeverageListUpdated
449
- });
450
- const {
451
- clearFlavors,
452
- flavors,
453
- selectFlavor,
454
- selectedFlavors,
455
- flavorCompanions
456
- } = useFlavors({
457
- companionType: options.companionTypes?.flavor,
458
- onFlavorSelected,
459
- onFlavorCleared
460
- });
461
- const [onBeforePour, setOnBeforePour] = React.useState();
462
- const updateOnBeforePour = React.useCallback((callback) => {
463
- setOnBeforePour(() => callback);
464
- }, []);
465
- const pour = useNozzlePour({
466
- onPour,
467
- onPourCancel,
468
- onBeforePour: handleBeforePour,
469
- onBeforePourRejected: handleBeforePourRejected
470
- });
471
- updatePourContext.current = pour.updatePourContext;
472
- removeFromPourContext.current = pour.removeFromPourContext;
473
- const back = React.useCallback(() => {
474
- log$2.debug(`Navigating back from group: ${currentGroup}`);
475
- switch (currentGroup) {
476
- case DISPENSE_GROUP_BRAND:
477
- clearBeverage();
478
- clearBrand();
479
- break;
480
- case DISPENSE_GROUP_BEVERAGE:
481
- case DISPENSE_GROUP_FLAVOR:
482
- setCurrentGroup(initialGroup);
483
- clearBeverage();
484
- clearBrand();
485
- break;
486
- }
487
- }, [clearBeverage, clearBrand, currentGroup, initialGroup]);
488
- const home = React.useCallback(() => {
489
- const topic = `/kos/dispense/${nozzle?.path}/home/`;
490
- kosUiSdk.EventBus.publish(topic, {});
491
- setCurrentGroup(initialGroup);
492
- if (initialGroup === DISPENSE_GROUP_BRAND) {
493
- clearBeverage();
494
- clearBrand();
495
- }
496
- if (initialGroup === DISPENSE_GROUP_BEVERAGE) {
497
- clearBeverage();
498
- }
499
- }, [clearBeverage, clearBrand, initialGroup]);
392
+ const pour = {
393
+ handlers: gesture.dom,
394
+ cancel: () => void kit?.cancelPour(),
395
+ start: async (pourOptions) => await kit?.startPour(pourOptions) ?? false,
396
+ press: async (pourOptions) => await kit?.pressPour(pourOptions) ?? false,
397
+ release: (pourOptions) => kit?.releasePour(pourOptions),
398
+ updatePourContext: (key, value) => kit?.pourContext.set(key, value),
399
+ removeFromPourContext: (key) => kit?.pourContext.remove(key),
400
+ status: nozzle
401
+ };
500
402
  const pauseTimers = React.useCallback(() => {
501
403
  if (timersRef.current.length === 0) {
502
- log$2.debug("No timers to pause.");
404
+ log$3.debug("No timers to pause.");
503
405
  return;
504
406
  }
505
- log$2.debug(`Pausing ${timersRef.current.length} timers.`);
407
+ log$3.debug(`Pausing ${timersRef.current.length} timers.`);
506
408
  timersRef.current.forEach((timer) => {
507
- log$2.debug(`Pausing timer with id ${timer.id}.`);
409
+ log$3.debug(`Pausing timer with id ${timer.id}.`);
508
410
  timer.pause();
509
411
  });
510
412
  }, []);
511
413
  const restartTimers = React.useCallback(() => {
512
414
  if (timersRef.current.length === 0) {
513
- log$2.debug("No timers to restart.");
415
+ log$3.debug("No timers to restart.");
514
416
  return;
515
417
  }
516
- log$2.debug(`Restarting ${timersRef.current.length} timers.`);
418
+ log$3.debug(`Restarting ${timersRef.current.length} timers.`);
517
419
  timersRef.current.forEach((timer) => {
518
- log$2.debug(`Restarting timer with id ${timer.id}.`);
420
+ log$3.debug(`Restarting timer with id ${timer.id}.`);
519
421
  timer.restart();
520
422
  });
521
423
  }, []);
@@ -524,11 +426,12 @@ const useCuiKit = ({
524
426
  return;
525
427
  }
526
428
  if (timersRef.current.some((t) => t.id === timer.id)) {
527
- log$2.debug(`Timer with id ${timer.id} already exists.`);
429
+ log$3.debug(`Timer with id ${timer.id} already exists.`);
528
430
  return;
529
431
  }
530
432
  timersRef.current.push(timer);
531
433
  }, []);
434
+ const active = ready ? kit : void 0;
532
435
  return {
533
436
  timers: {
534
437
  add: addTimer,
@@ -536,43 +439,70 @@ const useCuiKit = ({
536
439
  restart: restartTimers
537
440
  },
538
441
  nav: {
539
- currentGroup,
540
- back,
541
- home
442
+ currentGroup: active?.currentGroup ?? (steps ? steps.brands ? DISPENSE_GROUP_BRAND : DISPENSE_GROUP_BEVERAGE : initialGroup ?? DISPENSE_GROUP_BRAND),
443
+ back: () => active?.back(),
444
+ home: () => active?.home(),
445
+ steps: active?.enabledSteps,
446
+ canBack: active?.canBack ?? false,
447
+ toPour: (pourOptions) => active?.toPour(pourOptions)
542
448
  },
543
449
  pour,
544
450
  updateOnBeforePour,
545
451
  selections: {
546
- [DISPENSE_GROUP_BRAND]: selectedBrand,
547
- [DISPENSE_GROUP_BEVERAGE]: selectedBeverage,
548
- [DISPENSE_GROUP_FLAVOR]: selectedFlavors
452
+ [DISPENSE_GROUP_BRAND]: active?.selectedBrand ?? null,
453
+ [DISPENSE_GROUP_BEVERAGE]: active?.selectedBeverage ?? null,
454
+ [DISPENSE_GROUP_FLAVOR]: active?.selectedFlavors ?? []
549
455
  },
550
456
  [DISPENSE_GROUP_BRAND]: {
551
- models: brands,
552
- companions: brandCompanions,
553
- clear: clearBrand,
457
+ models: active?.brands ?? [],
458
+ companions: active?.brandCompanions ?? [],
459
+ clear: () => active?.clearBrand(),
554
460
  handlers: {
555
- onSelected: selectBrand
461
+ onSelected: async (model, context, forceUpdate) => {
462
+ if (forceUpdate) {
463
+ log$3.warn(
464
+ `forceUpdate is not currently supported when setting brand`
465
+ );
466
+ }
467
+ active?.selectBrand(model, context);
468
+ }
556
469
  }
557
470
  },
558
471
  [DISPENSE_GROUP_BEVERAGE]: {
559
- models: beverages,
560
- companions: beverageCompanions,
561
- clear: clearBeverage,
472
+ models: active?.beverages ?? [],
473
+ companions: active?.beverageCompanions ?? [],
474
+ clear: () => void active?.clearBeverage(),
562
475
  handlers: {
563
- onSelected: selectBeverage
476
+ onSelected: async (model, context, forceUpdate) => active?.selectBeverage(model, context, forceUpdate)
564
477
  }
565
478
  },
566
479
  [DISPENSE_GROUP_FLAVOR]: {
567
- models: flavors,
568
- companions: flavorCompanions,
569
- clear: clearFlavors,
480
+ models: active?.flavors ?? [],
481
+ companions: active?.flavorCompanions ?? [],
482
+ clear: () => void active?.clearFlavors(),
570
483
  handlers: {
571
- onSelected: selectFlavor
484
+ onSelected: async (model, context, forceUpdate) => active?.selectFlavor(model, context, forceUpdate)
572
485
  }
573
486
  }
574
487
  };
575
488
  };
489
+ const readKitState = (kit) => [
490
+ kit.currentGroup,
491
+ kit.canBack,
492
+ kit.selectedBrand,
493
+ kit.selectedBeverage,
494
+ ...kit.selectedFlavors,
495
+ ...kit.brands,
496
+ ...kit.beverages,
497
+ ...kit.flavors,
498
+ ...kit.brandCompanions,
499
+ ...kit.beverageCompanions,
500
+ ...kit.flavorCompanions
501
+ ];
502
+ const log$2 = kosUiSdk.KosLog.createLogger({
503
+ group: kosUiSdk.LogGroup.ui,
504
+ name: "use-ambient-attract-timers"
505
+ });
576
506
  const useAmbientAttractTimers = (props) => {
577
507
  const { model: nozzle } = useNozzleContext();
578
508
  const [attractTimer, setAttractTimer] = React.useState(null);
@@ -586,13 +516,13 @@ const useAmbientAttractTimers = (props) => {
586
516
  } = props;
587
517
  const handleAmbientTimer = React.useCallback(() => {
588
518
  if (onAmbientTimer) {
589
- kosUiSdk.KosLog.info("Ambient timer expired. Calling callback");
519
+ log$2.info("Ambient timer expired. Calling callback");
590
520
  onAmbientTimer?.();
591
521
  }
592
522
  }, [onAmbientTimer]);
593
523
  const handleAttractTimer = React.useCallback(() => {
594
524
  if (onAttractTimer) {
595
- kosUiSdk.KosLog.info("Attract timer expired. Calling callback");
525
+ log$2.info("Attract timer expired. Calling callback");
596
526
  onAttractTimer?.();
597
527
  }
598
528
  }, [onAttractTimer]);
@@ -616,7 +546,7 @@ const useAmbientAttractTimers = (props) => {
616
546
  }, [attractTimer, onResumeAttractTimer]);
617
547
  React.useEffect(() => {
618
548
  if (nozzle && defaultAttractTime) {
619
- kosUiSdk.KosLog.info("Nozzle is available. Creating timers");
549
+ log$2.info("Nozzle is available. Creating timers");
620
550
  const timer = kosUiSdk.TimerManager.createTimer(
621
551
  "attract-timer-" + nozzle.path,
622
552
  defaultAttractTime
@@ -645,7 +575,7 @@ const useAmbientAttractTimers = (props) => {
645
575
  };
646
576
  }
647
577
  return () => {
648
- kosUiSdk.KosLog.info("Nozzle is not available. No timers to clear");
578
+ log$2.info("Nozzle is not available. No timers to clear");
649
579
  };
650
580
  }, [
651
581
  defaultAmbientTime,
@@ -772,7 +702,10 @@ const useDispenseLifecycle = ({
772
702
  onReturnToHome
773
703
  ]);
774
704
  };
775
- const log$1 = kosUiSdk.KosLog.createLogger({ name: "useCuiKitTimers" });
705
+ const log$1 = kosUiSdk.KosLog.createLogger({
706
+ group: kosUiSdk.LogGroup.ui,
707
+ name: "useCuiKitTimers"
708
+ });
776
709
  const useCuiKitTimers = (props) => {
777
710
  const { model: nozzle } = useNozzleContext();
778
711
  const [idleTimer, setIdleTimer] = React.useState(null);
@@ -786,7 +719,7 @@ const useCuiKitTimers = (props) => {
786
719
  const hasAreYouThereFiredRef = React.useRef(false);
787
720
  const handleAreYouThereTimer = React.useCallback(() => {
788
721
  if (!hasAreYouThereFiredRef.current && onAreYouThereTimer) {
789
- kosUiSdk.KosLog.info("Are you there timer expired. Calling callback");
722
+ log$1.info("Are you there timer expired. Calling callback");
790
723
  hasAreYouThereFiredRef.current = true;
791
724
  onAreYouThereTimer?.();
792
725
  }
@@ -866,7 +799,10 @@ const useCuiKitTimers = (props) => {
866
799
  pause: handlePauseIdleTimer
867
800
  };
868
801
  };
869
- const log = kosUiSdk.KosLog.createLogger({ name: "useDefaultCuiKitLifecycle" });
802
+ const log = kosUiSdk.KosLog.createLogger({
803
+ group: kosUiSdk.LogGroup.ui,
804
+ name: "useDefaultCuiKitLifecycle"
805
+ });
870
806
  const useDefaultCuiKitLifecycle = ({
871
807
  kit,
872
808
  inactivity,
@@ -1122,6 +1058,59 @@ const useDefaultCuiKitLifecycle = ({
1122
1058
  restartScreenTimer: ambientRestart
1123
1059
  };
1124
1060
  };
1061
+ const useFlavors = ({
1062
+ onFlavorSelected,
1063
+ onFlavorCleared,
1064
+ companionType
1065
+ }) => {
1066
+ const { model: nozzle } = useNozzleContext();
1067
+ const flavors = React.useMemo(
1068
+ () => nozzle?.getGroupAvailabilityItems("flavors").filter((f) => f.visible) ?? [],
1069
+ [nozzle]
1070
+ );
1071
+ const companions = React.useMemo(() => {
1072
+ if (!companionType) return [];
1073
+ return flavors.map(
1074
+ (flavor) => kosUiSdk.getKosCompanionModel(flavor, companionType)
1075
+ );
1076
+ }, [flavors, companionType]);
1077
+ const [selectedFlavors, setSelectedFlavors] = React.useState([]);
1078
+ const selectFlavor = React.useCallback(
1079
+ async (flavor, context, forceUpdate) => {
1080
+ setSelectedFlavors(
1081
+ (previous) => previous?.includes(flavor) ? [...previous.filter((p) => p !== flavor)] : [...previous ?? [], flavor]
1082
+ );
1083
+ if (nozzle?.selectedPourable) {
1084
+ const { beverage } = nozzle.selectedPourable;
1085
+ await nozzle.setSelectedPourable(
1086
+ {
1087
+ beverage,
1088
+ additional: selectedFlavors ?? [],
1089
+ context
1090
+ },
1091
+ forceUpdate
1092
+ );
1093
+ }
1094
+ onFlavorSelected?.(flavor, selectedFlavors ?? []);
1095
+ },
1096
+ [nozzle, onFlavorSelected, selectedFlavors]
1097
+ );
1098
+ const clear = React.useCallback(async () => {
1099
+ setSelectedFlavors([]);
1100
+ if (nozzle?.selectedPourable) {
1101
+ const { beverage } = nozzle.selectedPourable;
1102
+ nozzle.setSelectedPourable({ beverage });
1103
+ onFlavorCleared?.();
1104
+ }
1105
+ }, [nozzle, onFlavorCleared]);
1106
+ return {
1107
+ flavors,
1108
+ flavorCompanions: companions,
1109
+ selectFlavor,
1110
+ selectedFlavors,
1111
+ clearFlavors: clear
1112
+ };
1113
+ };
1125
1114
  const useDeviceAssembly = () => {
1126
1115
  const modelId = dispenseRegistrationManager.DeviceAssembly.type;
1127
1116
  const result = kosUiSdk.useKosModel({
@@ -1176,31 +1165,9 @@ const useIngredient = () => {
1176
1165
  });
1177
1166
  return result;
1178
1167
  };
1179
- const logger$5 = kosUiSdk.KosLog.createLogger({
1180
- name: "HoldToPourIntentStrategy",
1181
- group: "kos-hooks"
1182
- });
1183
- const HoldToPourIntentStrategy = {
1184
- name: "HoldToPourIntentStrategy",
1185
- async initiate(model, intent) {
1186
- if (!model?.canPour) {
1187
- logger$5.debug(`${model?.id} cannot pour. Returning early.`);
1188
- return;
1189
- }
1190
- if (intent) {
1191
- logger$5.debug(`performing intent: ${intent}`);
1192
- await model?.performIntent(intent);
1193
- } else {
1194
- logger$5.debug("no intent provided. Returning early.");
1195
- }
1196
- },
1197
- async initiateEnded(nozzle) {
1198
- await nozzle?.cancelPour();
1199
- }
1200
- };
1201
- const logger$4 = kosUiSdk.KosLog.createLogger({
1202
- name: "useNozzlePour",
1203
- group: "kos-hooks"
1168
+ const logger$2 = kosUiSdk.KosLog.createLogger({
1169
+ group: kosUiSdk.LogGroup.ui,
1170
+ name: "useNozzlePour"
1204
1171
  });
1205
1172
  const useIngredientPour = ({
1206
1173
  onPour,
@@ -1209,21 +1176,21 @@ const useIngredientPour = ({
1209
1176
  strategy = HoldToPourIntentStrategy
1210
1177
  }) => {
1211
1178
  const handlePour = React.useCallback(() => {
1212
- logger$4.debug(
1179
+ logger$2.debug(
1213
1180
  `[${strategy?.name}] - Pour initiated for model ${intentContainer?.id}.`
1214
1181
  );
1215
1182
  strategy?.initiate(intentContainer);
1216
1183
  onPour?.();
1217
1184
  }, [onPour, intentContainer, strategy]);
1218
1185
  const handleCancelPour = React.useCallback(() => {
1219
- logger$4.debug(
1186
+ logger$2.debug(
1220
1187
  `[${strategy?.name}] - Pour initiate ended called for nozzle ${intentContainer?.id}.`
1221
1188
  );
1222
1189
  strategy?.initiateEnded?.(intentContainer);
1223
1190
  onPourCancel?.();
1224
1191
  }, [onPourCancel, intentContainer, strategy]);
1225
1192
  const forceCancelPour = React.useCallback(() => {
1226
- logger$4.debug(`Force cancelling pour for nozzle ${intentContainer?.id}.`);
1193
+ logger$2.debug(`Force cancelling pour for nozzle ${intentContainer?.id}.`);
1227
1194
  intentContainer?.cancelPour();
1228
1195
  onPourCancel?.();
1229
1196
  }, [onPourCancel, intentContainer]);
@@ -1264,10 +1231,82 @@ function withNozzle(path, WrappedComponent) {
1264
1231
  return /* @__PURE__ */ jsxRuntime.jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsxRuntime.jsx(WrappedComponent, { ...props, nozzle: model }) });
1265
1232
  };
1266
1233
  }
1267
- const logger$3 = kosUiSdk.KosLog.createLogger({
1268
- name: "usePour",
1269
- group: "kos-hooks"
1234
+ const logger$1 = kosUiSdk.KosLog.createLogger({
1235
+ group: kosUiSdk.LogGroup.ui,
1236
+ name: "useNozzlePour"
1270
1237
  });
1238
+ const useNozzlePour = ({
1239
+ onPour,
1240
+ onPourCancel,
1241
+ onBeforePour,
1242
+ onBeforePourRejected,
1243
+ pourContext,
1244
+ strategy = HoldToPourStrategy
1245
+ }) => {
1246
+ const { model: nozzle } = useNozzleContext();
1247
+ const [context, _setContext] = React.useState(
1248
+ pourContext || new dispenseRegistrationManager.PourContext()
1249
+ );
1250
+ const handlePour = React.useCallback(async () => {
1251
+ const canPour = onBeforePour ? await onBeforePour?.(context) : true;
1252
+ if (canPour) {
1253
+ logger$1.debug(
1254
+ `[${strategy?.name}] - Pour initiated for nozzle ${nozzle?.id}.`
1255
+ );
1256
+ strategy?.initiate(nozzle);
1257
+ onPour?.();
1258
+ } else {
1259
+ logger$1.debug(
1260
+ `[${strategy?.name}] - Did not pass onBeforePour gate for nozzle ${nozzle?.id}. Cancelling pour.`
1261
+ );
1262
+ onBeforePourRejected?.();
1263
+ }
1264
+ }, [
1265
+ onPour,
1266
+ nozzle,
1267
+ strategy,
1268
+ onBeforePour,
1269
+ onPourCancel,
1270
+ context,
1271
+ onBeforePourRejected
1272
+ ]);
1273
+ const handleCancelPour = React.useCallback(() => {
1274
+ logger$1.debug(
1275
+ `[${strategy?.name}] - Pour initiate ended called for nozzle ${nozzle?.id}.`
1276
+ );
1277
+ strategy?.initiateEnded?.(nozzle);
1278
+ onPourCancel?.();
1279
+ }, [onPourCancel, nozzle, strategy]);
1280
+ const forceCancelPour = React.useCallback(() => {
1281
+ logger$1.debug(`Force cancelling pour for nozzle ${nozzle?.id}.`);
1282
+ nozzle?.cancelPour();
1283
+ onPourCancel?.();
1284
+ }, [onPourCancel, nozzle]);
1285
+ const handleUpdateContext = React.useCallback(
1286
+ (key, value) => {
1287
+ context.set(key, value);
1288
+ },
1289
+ [context]
1290
+ );
1291
+ const handleRemoveFromContext = React.useCallback(
1292
+ (key) => {
1293
+ context.remove(key);
1294
+ },
1295
+ [context]
1296
+ );
1297
+ const handlers = kosUiSdk.usePressGesture({
1298
+ onPressed: handlePour,
1299
+ onRelease: handleCancelPour
1300
+ });
1301
+ return {
1302
+ handlers: handlers.dom,
1303
+ cancel: forceCancelPour,
1304
+ updatePourContext: handleUpdateContext,
1305
+ removeFromPourContext: handleRemoveFromContext,
1306
+ status: nozzle
1307
+ };
1308
+ };
1309
+ const logger = kosUiSdk.KosLog.createLogger({ group: kosUiSdk.LogGroup.ui, name: "usePour" });
1271
1310
  const usePourTarget = ({
1272
1311
  onBeforePour,
1273
1312
  onPour,
@@ -1278,15 +1317,15 @@ const usePourTarget = ({
1278
1317
  strategy = HoldToPourStrategy
1279
1318
  }) => {
1280
1319
  const [context, _setContext] = React.useState(
1281
- pourContext || new PourContext()
1320
+ pourContext || new dispenseRegistrationManager.PourContext()
1282
1321
  );
1283
1322
  const handlePour = React.useCallback(async () => {
1284
- logger$3.debug(
1323
+ logger.debug(
1285
1324
  `[${strategy?.name}] - calling before pour for pour target ${pourTarget?.id}.`
1286
1325
  );
1287
1326
  const canPour = onBeforePour ? await onBeforePour?.(context) : true;
1288
1327
  if (canPour) {
1289
- logger$3.debug(
1328
+ logger.debug(
1290
1329
  `[${strategy?.name}] - Pour initiated for pour target ${pourTarget?.id}.`
1291
1330
  );
1292
1331
  await strategy?.initiate(pourTarget);
@@ -1295,14 +1334,14 @@ const usePourTarget = ({
1295
1334
  onPourAbort?.();
1296
1335
  }
1297
1336
  } else {
1298
- logger$3.debug(
1337
+ logger.debug(
1299
1338
  `[${strategy?.name}] - Pour cancelled for pour target ${pourTarget?.id}.`
1300
1339
  );
1301
1340
  onPourCancel?.();
1302
1341
  }
1303
1342
  }, [onPour, onBeforePour, onPourAbort, pourTarget, strategy, context]);
1304
1343
  const handleCancelPour = React.useCallback(async () => {
1305
- logger$3.debug(
1344
+ logger.debug(
1306
1345
  `[${strategy?.name}] - Pour initiate ended called for pour target ${pourTarget?.id}.`
1307
1346
  );
1308
1347
  const ignore = await strategy?.initiateEnded?.(pourTarget);
@@ -1311,7 +1350,7 @@ const usePourTarget = ({
1311
1350
  }
1312
1351
  }, [onPourCancel, pourTarget, strategy]);
1313
1352
  const forceCancelPour = React.useCallback(async () => {
1314
- logger$3.debug(`Force cancelling pour for pour target ${pourTarget?.id}.`);
1353
+ logger.debug(`Force cancelling pour for pour target ${pourTarget?.id}.`);
1315
1354
  await pourTarget?.cancelPour();
1316
1355
  onPourCancel?.();
1317
1356
  }, [onPourCancel, pourTarget]);
@@ -1339,98 +1378,6 @@ const usePourTarget = ({
1339
1378
  status: pourTarget
1340
1379
  };
1341
1380
  };
1342
- const logger$2 = kosUiSdk.KosLog.createLogger({
1343
- name: "TapOrHoldIntentStrategy",
1344
- group: "kos-hooks"
1345
- });
1346
- class TapOrHoldIntentStrategy {
1347
- intent;
1348
- name = "TapOrHoldIntentStrategy";
1349
- isHold = false;
1350
- disposer = null;
1351
- constructor(intent) {
1352
- this.intent = intent;
1353
- }
1354
- async initiate(model, intent) {
1355
- this.disposer = setTimeout(() => {
1356
- this.isHold = true;
1357
- }, 250);
1358
- if (model?.isPouring && !this.isHold) {
1359
- logger$2.debug(`additional tap detected. cancelling pour`);
1360
- await model.cancelPour();
1361
- return;
1362
- }
1363
- if (!model?.canPour) {
1364
- logger$2.debug(`${model?.id} cannot pour. Returning early.`);
1365
- return;
1366
- }
1367
- if (intent) {
1368
- logger$2.debug(`performing intent: ${intent}`);
1369
- await model?.performIntent(intent);
1370
- } else {
1371
- logger$2.debug("no intent provided. Returning early.");
1372
- }
1373
- }
1374
- async initiateEnded(nozzle) {
1375
- if (this.disposer) clearTimeout(this.disposer);
1376
- this.disposer = null;
1377
- if (!this.isHold) {
1378
- logger$2.debug("Tap detected. don't cancel and return.");
1379
- return true;
1380
- }
1381
- await nozzle?.cancelPour();
1382
- return false;
1383
- }
1384
- }
1385
- const logger$1 = kosUiSdk.KosLog.createLogger({
1386
- name: "TapToPourIntentStrategy",
1387
- group: "kos-hooks"
1388
- });
1389
- const TapToPourIntentStrategy = {
1390
- name: "TapToPourIntentStrategy",
1391
- async initiate(model, intent) {
1392
- if (model?.isPouring) {
1393
- logger$1.debug(`Nozzle ${model?.id} is already pouring. cancelling pour`);
1394
- await model.cancelPour();
1395
- return;
1396
- }
1397
- if (!model?.canPour) {
1398
- logger$1.debug(`Nozzle ${model?.id} cannot pour. Returning early.`);
1399
- return;
1400
- }
1401
- if (intent) {
1402
- logger$1.debug(`performing intent: ${intent}`);
1403
- await model?.performIntent(intent);
1404
- } else {
1405
- logger$1.debug("no intent provided. Returning early.");
1406
- }
1407
- },
1408
- async initiateEnded(_nozzle) {
1409
- return true;
1410
- }
1411
- };
1412
- const logger = kosUiSdk.KosLog.createLogger({
1413
- name: "HoldToPourStrategy",
1414
- group: "kos-hooks"
1415
- });
1416
- const TapToPourStrategy = {
1417
- name: "TapToPourStrategy",
1418
- async initiate(nozzle) {
1419
- if (nozzle?.isPouring) {
1420
- logger.debug(`Nozzle ${nozzle?.id} is already pouring. cancelling pour`);
1421
- await nozzle.cancelPour();
1422
- return;
1423
- }
1424
- if (!nozzle?.canPour) {
1425
- logger.debug(`Nozzle ${nozzle?.id} cannot pour. Returning early.`);
1426
- return;
1427
- }
1428
- await nozzle?.pour();
1429
- },
1430
- async initiateEnded(_nozzle) {
1431
- return true;
1432
- }
1433
- };
1434
1381
  const useGenericPour = (id, servicePathFactory, itemId, data) => {
1435
1382
  const modelId = id;
1436
1383
  const result = kosUiSdk.useKosModel({
@@ -1568,7 +1515,19 @@ function createDispenseKitContext() {
1568
1515
  }
1569
1516
  return ctx;
1570
1517
  };
1571
- return [useCuiKitContext, CuiKitContext.Provider];
1518
+ const useCuiPour = (options = {}) => {
1519
+ const kit = React.useContext(CuiKitContext);
1520
+ const gesture = kosUiSdk.usePressGesture({
1521
+ onPressed: () => void kit?.pour.press(options),
1522
+ onRelease: () => kit?.pour.release(options)
1523
+ });
1524
+ return {
1525
+ handlers: gesture.dom,
1526
+ start: async () => await kit?.pour.start(options) ?? false,
1527
+ cancel: () => kit?.pour.cancel()
1528
+ };
1529
+ };
1530
+ return [useCuiKitContext, CuiKitContext.Provider, useCuiPour];
1572
1531
  }
1573
1532
  function CuiKitWrapper({
1574
1533
  children,
@@ -1617,10 +1576,11 @@ function CuiKit({
1617
1576
  ) }) : null;
1618
1577
  }
1619
1578
  function initializeCuiKit(props) {
1620
- const [useCuiKitContext, DispenseKitProvider] = createDispenseKitContext();
1579
+ const [useCuiKitContext, DispenseKitProvider, useCuiPour] = createDispenseKitContext();
1621
1580
  return [
1622
1581
  useCuiKitContext,
1623
- CuiKit({ provider: DispenseKitProvider, props })
1582
+ CuiKit({ provider: DispenseKitProvider, props }),
1583
+ useCuiPour
1624
1584
  ];
1625
1585
  }
1626
1586
  const Holder = React.createContext(void 0);
@@ -1749,7 +1709,6 @@ exports.HolderProvider = HolderProvider;
1749
1709
  exports.IngredientContainerProvider = IngredientContainerProvider;
1750
1710
  exports.IngredientProvider = IngredientProvider;
1751
1711
  exports.NozzleProvider = NozzleProvider;
1752
- exports.PourContext = PourContext;
1753
1712
  exports.PumpProvider = PumpProvider;
1754
1713
  exports.TapOrHoldIntentStrategy = TapOrHoldIntentStrategy;
1755
1714
  exports.TapToPourIntentStrategy = TapToPourIntentStrategy;
@@ -1798,4 +1757,4 @@ exports.withHolderContainer = withHolderContainer;
1798
1757
  exports.withIngredient = withIngredient;
1799
1758
  exports.withIngredientContainer = withIngredientContainer;
1800
1759
  exports.withNozzle = withNozzle;
1801
- //# sourceMappingURL=pump-provider-uNNMh9uh.cjs.map
1760
+ //# sourceMappingURL=pump-provider-B4WR3LiY.cjs.map