@kosdev-code/kos-dispense-sdk 0.1.0-next.970 → 0.1.0-next.975

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 (50) hide show
  1. package/.kos.json +7 -0
  2. package/{dispense-registration-manager-Da9CW_cN.js → dispense-registration-manager-J59_vyyY.js} +584 -184
  3. package/dispense-registration-manager-J59_vyyY.js.map +1 -0
  4. package/{dispense-registration-manager-Dtb31fcI.cjs → dispense-registration-manager-OYGAiIZy.cjs} +551 -151
  5. package/dispense-registration-manager-OYGAiIZy.cjs.map +1 -0
  6. package/{extension-utils-D_dnBLH6.js → extension-utils-DEM1emOY.js} +2 -2
  7. package/{extension-utils-D_dnBLH6.js.map → extension-utils-DEM1emOY.js.map} +1 -1
  8. package/{extension-utils-Cfhe358W.cjs → extension-utils-Pd5ntKtv.cjs} +2 -2
  9. package/{extension-utils-Cfhe358W.cjs.map → extension-utils-Pd5ntKtv.cjs.map} +1 -1
  10. package/index.cjs +6 -4
  11. package/index.cjs.map +1 -1
  12. package/index.js +66 -64
  13. package/models/models/cui-kit-state/cui-kit-state-model.d.ts +131 -0
  14. package/models/models/cui-kit-state/cui-kit-state-model.d.ts.map +1 -0
  15. package/models/models/cui-kit-state/index.d.ts +4 -0
  16. package/models/models/cui-kit-state/index.d.ts.map +1 -0
  17. package/models/models/cui-kit-state/types/index.d.ts +68 -0
  18. package/models/models/index.d.ts +1 -0
  19. package/models/models/index.d.ts.map +1 -1
  20. package/models/utils/dispense-registration-manager.d.ts +13 -0
  21. package/models/utils/dispense-registration-manager.d.ts.map +1 -1
  22. package/models/utils/pour-context.d.ts +8 -0
  23. package/models/utils/pour-context.d.ts.map +1 -0
  24. package/models.cjs +4 -2
  25. package/models.cjs.map +1 -1
  26. package/models.js +17 -15
  27. package/package.json +5 -5
  28. package/{pump-provider-uNNMh9uh.cjs → pump-provider-BSbTT-BC.cjs} +371 -418
  29. package/pump-provider-BSbTT-BC.cjs.map +1 -0
  30. package/{pump-provider-BQmCKz7S.js → pump-provider-Ch7NOeRj.js} +417 -464
  31. package/pump-provider-Ch7NOeRj.js.map +1 -0
  32. package/ui/contexts/cui-kit/cui-kit.d.ts +12 -1
  33. package/ui/contexts/cui-kit/cui-kit.d.ts.map +1 -1
  34. package/ui/hooks/cui-kit/use-cui-kit.d.ts +44 -5
  35. package/ui/hooks/cui-kit/use-cui-kit.d.ts.map +1 -1
  36. package/ui/hooks/utils/pour-strategy/hold-to-pour-intent-strategy.d.ts.map +1 -1
  37. package/ui/hooks/utils/pour-strategy/hold-to-pour-strategy.d.ts.map +1 -1
  38. package/ui/hooks/utils/pour-strategy/pour-strategy.d.ts +2 -0
  39. package/ui/hooks/utils/pour-strategy/pour-strategy.d.ts.map +1 -1
  40. package/ui/hooks/utils/pour-strategy/tap-or-hold-to-pour-intent-strategy.d.ts.map +1 -1
  41. package/ui/utils/pour-context.d.ts +1 -7
  42. package/ui/utils/pour-context.d.ts.map +1 -1
  43. package/ui.cjs +3 -2
  44. package/ui.cjs.map +1 -1
  45. package/ui.js +49 -48
  46. package/ui.js.map +1 -1
  47. package/dispense-registration-manager-Da9CW_cN.js.map +0 -1
  48. package/dispense-registration-manager-Dtb31fcI.cjs.map +0 -1
  49. package/pump-provider-BQmCKz7S.js.map +0 -1
  50. 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-OYGAiIZy.cjs");
6
6
  const useAssembly = () => {
7
7
  const modelId = dispenseRegistrationManager.Assembly.type;
8
8
  const result = kosUiSdk.useKosModel({
@@ -193,30 +193,39 @@ const useBrands = ({
193
193
  clearBrand
194
194
  };
195
195
  };
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
196
  const logger$7 = kosUiSdk.KosLog.createLogger({
197
+ name: "HoldToPourIntentStrategy",
198
+ group: "kos-hooks"
199
+ });
200
+ const HoldToPourIntentStrategy = {
201
+ name: "HoldToPourIntentStrategy",
202
+ requiresHold: true,
203
+ async initiate(model, intent) {
204
+ if (!model?.canPour) {
205
+ logger$7.debug(`${model?.id} cannot pour. Returning early.`);
206
+ return;
207
+ }
208
+ if (intent) {
209
+ logger$7.debug(`performing intent: ${intent}`);
210
+ await model?.performIntent(intent);
211
+ } else {
212
+ logger$7.debug("no intent provided. Returning early.");
213
+ }
214
+ },
215
+ async initiateEnded(nozzle) {
216
+ await nozzle?.cancelPour();
217
+ }
218
+ };
219
+ const logger$6 = kosUiSdk.KosLog.createLogger({
212
220
  name: "HoldToPourStrategy",
213
221
  group: "kos-hooks"
214
222
  });
215
223
  const HoldToPourStrategy = {
216
224
  name: "HoldToPourStrategy",
225
+ requiresHold: true,
217
226
  async initiate(nozzle) {
218
227
  if (!nozzle?.canPour) {
219
- logger$7.debug(`Nozzle ${nozzle?.id} cannot pour. Returning early.`);
228
+ logger$6.debug(`Nozzle ${nozzle?.id} cannot pour. Returning early.`);
220
229
  return;
221
230
  }
222
231
  await nozzle?.pour();
@@ -225,278 +234,172 @@ const HoldToPourStrategy = {
225
234
  await nozzle?.cancelPour();
226
235
  }
227
236
  };
228
- const logger$6 = kosUiSdk.KosLog.createLogger({
229
- name: "useNozzlePour",
237
+ const logger$5 = kosUiSdk.KosLog.createLogger({
238
+ name: "TapOrHoldIntentStrategy",
230
239
  group: "kos-hooks"
231
240
  });
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?.();
241
+ class TapOrHoldIntentStrategy {
242
+ intent;
243
+ name = "TapOrHoldIntentStrategy";
244
+ isHold = false;
245
+ disposer = null;
246
+ constructor(intent) {
247
+ this.intent = intent;
248
+ }
249
+ async initiate(model, intent = this.intent) {
250
+ this.isHold = false;
251
+ this.disposer = setTimeout(() => {
252
+ this.isHold = true;
253
+ }, 250);
254
+ if (model?.isPouring && !this.isHold) {
255
+ logger$5.debug(`additional tap detected. cancelling pour`);
256
+ await model.cancelPour();
257
+ return;
258
+ }
259
+ if (!model?.canPour) {
260
+ logger$5.debug(`${model?.id} cannot pour. Returning early.`);
261
+ return;
262
+ }
263
+ if (intent) {
264
+ logger$5.debug(`performing intent: ${intent}`);
265
+ await model?.performIntent(intent);
252
266
  } else {
253
- logger$6.debug(
254
- `[${strategy?.name}] - Did not pass onBeforePour gate for nozzle ${nozzle?.id}. Cancelling pour.`
255
- );
256
- onBeforePourRejected?.();
267
+ logger$5.debug("no intent provided. Returning early.");
257
268
  }
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
- };
269
+ }
270
+ async initiateEnded(nozzle) {
271
+ if (this.disposer) clearTimeout(this.disposer);
272
+ this.disposer = null;
273
+ if (!this.isHold) {
274
+ logger$5.debug("Tap detected. don't cancel and return.");
275
+ return true;
276
+ }
277
+ await nozzle?.cancelPour();
278
+ return false;
279
+ }
280
+ }
281
+ const logger$4 = kosUiSdk.KosLog.createLogger({
282
+ name: "TapToPourIntentStrategy",
283
+ group: "kos-hooks"
284
+ });
285
+ const TapToPourIntentStrategy = {
286
+ name: "TapToPourIntentStrategy",
287
+ async initiate(model, intent) {
288
+ if (model?.isPouring) {
289
+ logger$4.debug(`Nozzle ${model?.id} is already pouring. cancelling pour`);
290
+ await model.cancelPour();
291
+ return;
292
+ }
293
+ if (!model?.canPour) {
294
+ logger$4.debug(`Nozzle ${model?.id} cannot pour. Returning early.`);
295
+ return;
296
+ }
297
+ if (intent) {
298
+ logger$4.debug(`performing intent: ${intent}`);
299
+ await model?.performIntent(intent);
300
+ } else {
301
+ logger$4.debug("no intent provided. Returning early.");
302
+ }
303
+ },
304
+ async initiateEnded(_nozzle) {
305
+ return true;
306
+ }
302
307
  };
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?.();
308
+ const logger$3 = kosUiSdk.KosLog.createLogger({
309
+ name: "HoldToPourStrategy",
310
+ group: "kos-hooks"
311
+ });
312
+ const TapToPourStrategy = {
313
+ name: "TapToPourStrategy",
314
+ async initiate(nozzle) {
315
+ if (nozzle?.isPouring) {
316
+ logger$3.debug(`Nozzle ${nozzle?.id} is already pouring. cancelling pour`);
317
+ await nozzle.cancelPour();
318
+ return;
346
319
  }
347
- }, [nozzle, onFlavorCleared]);
348
- return {
349
- flavors,
350
- flavorCompanions: companions,
351
- selectFlavor,
352
- selectedFlavors,
353
- clearFlavors: clear
354
- };
320
+ if (!nozzle?.canPour) {
321
+ logger$3.debug(`Nozzle ${nozzle?.id} cannot pour. Returning early.`);
322
+ return;
323
+ }
324
+ await nozzle?.pour();
325
+ },
326
+ async initiateEnded(_nozzle) {
327
+ return true;
328
+ }
355
329
  };
356
330
  const DISPENSE_GROUP_BRAND = "brands";
357
331
  const DISPENSE_GROUP_BEVERAGE = "beverages";
358
332
  const DISPENSE_GROUP_FLAVOR = "flavors";
359
333
  const log$2 = kosUiSdk.KosLog.createLogger({ name: "use-cui-kit" });
360
334
  const useCuiKit = ({
361
- initialGroup = DISPENSE_GROUP_BRAND,
335
+ initialGroup,
336
+ steps,
362
337
  options = {}
363
338
  }) => {
364
- const [currentGroup, setCurrentGroup] = React.useState(initialGroup);
365
339
  const { model: nozzle } = useNozzleContext();
366
340
  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;
341
+ const kit = React.useMemo(() => {
342
+ if (!nozzle) return void 0;
343
+ try {
344
+ return dispenseRegistrationManager.CuiKitState.instance(dispenseRegistrationManager.cuiKitId(nozzle.path)).options({
345
+ nozzlePath: nozzle.path,
346
+ initialGroup: steps ? initialGroup : initialGroup ?? DISPENSE_GROUP_BRAND,
347
+ steps,
348
+ companionTypes: options.companionTypes,
349
+ pour: { strategy: options.pour?.strategy ?? HoldToPourStrategy },
350
+ onPourComplete: options.onPourComplete
351
+ }).build();
352
+ } catch (error) {
353
+ throw new Error(
354
+ `The CUI Kit models are not registered: call KosModelRegistry.cuiKit.models() in the app's registration chain (${error.message})`
355
+ );
356
+ }
357
+ }, [nozzle]);
358
+ const [ready, setReady] = React.useState(false);
359
+ const [, setVersion] = React.useState(0);
360
+ React.useEffect(() => {
361
+ if (!kit) return void 0;
362
+ let dispose;
363
+ let cancelled = false;
364
+ let attached = false;
365
+ kosUiSdk.whenReady(kit).then(() => {
366
+ if (cancelled) return;
367
+ attached = true;
368
+ if (kit.attach()) {
369
+ kit.reset();
370
+ }
371
+ setReady(true);
372
+ dispose = kosUiSdk.kosAutoEffect(() => {
373
+ readKitState(kit);
374
+ setVersion((version) => version + 1);
375
+ });
376
+ });
377
+ return () => {
378
+ cancelled = true;
379
+ dispose?.();
380
+ if (attached) kit.detach();
381
+ };
382
+ }, [kit]);
383
+ const updateOnBeforePour = React.useCallback(
384
+ (callback) => {
385
+ kit?.setBeforePour(callback);
422
386
  },
423
- [nozzle?.path]
387
+ [kit]
424
388
  );
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
437
- });
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
389
+ const gesture = kosUiSdk.usePressGesture({
390
+ onPressed: () => void kit?.pressPour(),
391
+ onRelease: () => kit?.releasePour()
470
392
  });
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]);
393
+ const pour = {
394
+ handlers: gesture.dom,
395
+ cancel: () => void kit?.cancelPour(),
396
+ start: async (pourOptions) => await kit?.startPour(pourOptions) ?? false,
397
+ press: async (pourOptions) => await kit?.pressPour(pourOptions) ?? false,
398
+ release: (pourOptions) => kit?.releasePour(pourOptions),
399
+ updatePourContext: (key, value) => kit?.pourContext.set(key, value),
400
+ removeFromPourContext: (key) => kit?.pourContext.remove(key),
401
+ status: nozzle
402
+ };
500
403
  const pauseTimers = React.useCallback(() => {
501
404
  if (timersRef.current.length === 0) {
502
405
  log$2.debug("No timers to pause.");
@@ -529,6 +432,7 @@ const useCuiKit = ({
529
432
  }
530
433
  timersRef.current.push(timer);
531
434
  }, []);
435
+ const active = ready ? kit : void 0;
532
436
  return {
533
437
  timers: {
534
438
  add: addTimer,
@@ -536,43 +440,66 @@ const useCuiKit = ({
536
440
  restart: restartTimers
537
441
  },
538
442
  nav: {
539
- currentGroup,
540
- back,
541
- home
443
+ currentGroup: active?.currentGroup ?? (steps ? steps.brands ? DISPENSE_GROUP_BRAND : DISPENSE_GROUP_BEVERAGE : initialGroup ?? DISPENSE_GROUP_BRAND),
444
+ back: () => active?.back(),
445
+ home: () => active?.home(),
446
+ steps: active?.enabledSteps,
447
+ canBack: active?.canBack ?? false,
448
+ toPour: (pourOptions) => active?.toPour(pourOptions)
542
449
  },
543
450
  pour,
544
451
  updateOnBeforePour,
545
452
  selections: {
546
- [DISPENSE_GROUP_BRAND]: selectedBrand,
547
- [DISPENSE_GROUP_BEVERAGE]: selectedBeverage,
548
- [DISPENSE_GROUP_FLAVOR]: selectedFlavors
453
+ [DISPENSE_GROUP_BRAND]: active?.selectedBrand ?? null,
454
+ [DISPENSE_GROUP_BEVERAGE]: active?.selectedBeverage ?? null,
455
+ [DISPENSE_GROUP_FLAVOR]: active?.selectedFlavors ?? []
549
456
  },
550
457
  [DISPENSE_GROUP_BRAND]: {
551
- models: brands,
552
- companions: brandCompanions,
553
- clear: clearBrand,
458
+ models: active?.brands ?? [],
459
+ companions: active?.brandCompanions ?? [],
460
+ clear: () => active?.clearBrand(),
554
461
  handlers: {
555
- onSelected: selectBrand
462
+ onSelected: async (model, context, forceUpdate) => {
463
+ if (forceUpdate) {
464
+ kosUiSdk.KosLog.warn(
465
+ `forceUpdate is not currently supported when setting brand`
466
+ );
467
+ }
468
+ active?.selectBrand(model, context);
469
+ }
556
470
  }
557
471
  },
558
472
  [DISPENSE_GROUP_BEVERAGE]: {
559
- models: beverages,
560
- companions: beverageCompanions,
561
- clear: clearBeverage,
473
+ models: active?.beverages ?? [],
474
+ companions: active?.beverageCompanions ?? [],
475
+ clear: () => void active?.clearBeverage(),
562
476
  handlers: {
563
- onSelected: selectBeverage
477
+ onSelected: async (model, context, forceUpdate) => active?.selectBeverage(model, context, forceUpdate)
564
478
  }
565
479
  },
566
480
  [DISPENSE_GROUP_FLAVOR]: {
567
- models: flavors,
568
- companions: flavorCompanions,
569
- clear: clearFlavors,
481
+ models: active?.flavors ?? [],
482
+ companions: active?.flavorCompanions ?? [],
483
+ clear: () => void active?.clearFlavors(),
570
484
  handlers: {
571
- onSelected: selectFlavor
485
+ onSelected: async (model, context, forceUpdate) => active?.selectFlavor(model, context, forceUpdate)
572
486
  }
573
487
  }
574
488
  };
575
489
  };
490
+ const readKitState = (kit) => [
491
+ kit.currentGroup,
492
+ kit.canBack,
493
+ kit.selectedBrand,
494
+ kit.selectedBeverage,
495
+ ...kit.selectedFlavors,
496
+ ...kit.brands,
497
+ ...kit.beverages,
498
+ ...kit.flavors,
499
+ ...kit.brandCompanions,
500
+ ...kit.beverageCompanions,
501
+ ...kit.flavorCompanions
502
+ ];
576
503
  const useAmbientAttractTimers = (props) => {
577
504
  const { model: nozzle } = useNozzleContext();
578
505
  const [attractTimer, setAttractTimer] = React.useState(null);
@@ -1122,6 +1049,59 @@ const useDefaultCuiKitLifecycle = ({
1122
1049
  restartScreenTimer: ambientRestart
1123
1050
  };
1124
1051
  };
1052
+ const useFlavors = ({
1053
+ onFlavorSelected,
1054
+ onFlavorCleared,
1055
+ companionType
1056
+ }) => {
1057
+ const { model: nozzle } = useNozzleContext();
1058
+ const flavors = React.useMemo(
1059
+ () => nozzle?.getGroupAvailabilityItems("flavors").filter((f) => f.visible) ?? [],
1060
+ [nozzle]
1061
+ );
1062
+ const companions = React.useMemo(() => {
1063
+ if (!companionType) return [];
1064
+ return flavors.map(
1065
+ (flavor) => kosUiSdk.getKosCompanionModel(flavor, companionType)
1066
+ );
1067
+ }, [flavors, companionType]);
1068
+ const [selectedFlavors, setSelectedFlavors] = React.useState([]);
1069
+ const selectFlavor = React.useCallback(
1070
+ async (flavor, context, forceUpdate) => {
1071
+ setSelectedFlavors(
1072
+ (previous) => previous?.includes(flavor) ? [...previous.filter((p) => p !== flavor)] : [...previous ?? [], flavor]
1073
+ );
1074
+ if (nozzle?.selectedPourable) {
1075
+ const { beverage } = nozzle.selectedPourable;
1076
+ await nozzle.setSelectedPourable(
1077
+ {
1078
+ beverage,
1079
+ additional: selectedFlavors ?? [],
1080
+ context
1081
+ },
1082
+ forceUpdate
1083
+ );
1084
+ }
1085
+ onFlavorSelected?.(flavor, selectedFlavors ?? []);
1086
+ },
1087
+ [nozzle, onFlavorSelected, selectedFlavors]
1088
+ );
1089
+ const clear = React.useCallback(async () => {
1090
+ setSelectedFlavors([]);
1091
+ if (nozzle?.selectedPourable) {
1092
+ const { beverage } = nozzle.selectedPourable;
1093
+ nozzle.setSelectedPourable({ beverage });
1094
+ onFlavorCleared?.();
1095
+ }
1096
+ }, [nozzle, onFlavorCleared]);
1097
+ return {
1098
+ flavors,
1099
+ flavorCompanions: companions,
1100
+ selectFlavor,
1101
+ selectedFlavors,
1102
+ clearFlavors: clear
1103
+ };
1104
+ };
1125
1105
  const useDeviceAssembly = () => {
1126
1106
  const modelId = dispenseRegistrationManager.DeviceAssembly.type;
1127
1107
  const result = kosUiSdk.useKosModel({
@@ -1176,29 +1156,7 @@ const useIngredient = () => {
1176
1156
  });
1177
1157
  return result;
1178
1158
  };
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({
1159
+ const logger$2 = kosUiSdk.KosLog.createLogger({
1202
1160
  name: "useNozzlePour",
1203
1161
  group: "kos-hooks"
1204
1162
  });
@@ -1209,21 +1167,21 @@ const useIngredientPour = ({
1209
1167
  strategy = HoldToPourIntentStrategy
1210
1168
  }) => {
1211
1169
  const handlePour = React.useCallback(() => {
1212
- logger$4.debug(
1170
+ logger$2.debug(
1213
1171
  `[${strategy?.name}] - Pour initiated for model ${intentContainer?.id}.`
1214
1172
  );
1215
1173
  strategy?.initiate(intentContainer);
1216
1174
  onPour?.();
1217
1175
  }, [onPour, intentContainer, strategy]);
1218
1176
  const handleCancelPour = React.useCallback(() => {
1219
- logger$4.debug(
1177
+ logger$2.debug(
1220
1178
  `[${strategy?.name}] - Pour initiate ended called for nozzle ${intentContainer?.id}.`
1221
1179
  );
1222
1180
  strategy?.initiateEnded?.(intentContainer);
1223
1181
  onPourCancel?.();
1224
1182
  }, [onPourCancel, intentContainer, strategy]);
1225
1183
  const forceCancelPour = React.useCallback(() => {
1226
- logger$4.debug(`Force cancelling pour for nozzle ${intentContainer?.id}.`);
1184
+ logger$2.debug(`Force cancelling pour for nozzle ${intentContainer?.id}.`);
1227
1185
  intentContainer?.cancelPour();
1228
1186
  onPourCancel?.();
1229
1187
  }, [onPourCancel, intentContainer]);
@@ -1264,7 +1222,82 @@ function withNozzle(path, WrappedComponent) {
1264
1222
  return /* @__PURE__ */ jsxRuntime.jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsxRuntime.jsx(WrappedComponent, { ...props, nozzle: model }) });
1265
1223
  };
1266
1224
  }
1267
- const logger$3 = kosUiSdk.KosLog.createLogger({
1225
+ const logger$1 = kosUiSdk.KosLog.createLogger({
1226
+ name: "useNozzlePour",
1227
+ group: "kos-hooks"
1228
+ });
1229
+ const useNozzlePour = ({
1230
+ onPour,
1231
+ onPourCancel,
1232
+ onBeforePour,
1233
+ onBeforePourRejected,
1234
+ pourContext,
1235
+ strategy = HoldToPourStrategy
1236
+ }) => {
1237
+ const { model: nozzle } = useNozzleContext();
1238
+ const [context, _setContext] = React.useState(
1239
+ pourContext || new dispenseRegistrationManager.PourContext()
1240
+ );
1241
+ const handlePour = React.useCallback(async () => {
1242
+ const canPour = onBeforePour ? await onBeforePour?.(context) : true;
1243
+ if (canPour) {
1244
+ logger$1.debug(
1245
+ `[${strategy?.name}] - Pour initiated for nozzle ${nozzle?.id}.`
1246
+ );
1247
+ strategy?.initiate(nozzle);
1248
+ onPour?.();
1249
+ } else {
1250
+ logger$1.debug(
1251
+ `[${strategy?.name}] - Did not pass onBeforePour gate for nozzle ${nozzle?.id}. Cancelling pour.`
1252
+ );
1253
+ onBeforePourRejected?.();
1254
+ }
1255
+ }, [
1256
+ onPour,
1257
+ nozzle,
1258
+ strategy,
1259
+ onBeforePour,
1260
+ onPourCancel,
1261
+ context,
1262
+ onBeforePourRejected
1263
+ ]);
1264
+ const handleCancelPour = React.useCallback(() => {
1265
+ logger$1.debug(
1266
+ `[${strategy?.name}] - Pour initiate ended called for nozzle ${nozzle?.id}.`
1267
+ );
1268
+ strategy?.initiateEnded?.(nozzle);
1269
+ onPourCancel?.();
1270
+ }, [onPourCancel, nozzle, strategy]);
1271
+ const forceCancelPour = React.useCallback(() => {
1272
+ logger$1.debug(`Force cancelling pour for nozzle ${nozzle?.id}.`);
1273
+ nozzle?.cancelPour();
1274
+ onPourCancel?.();
1275
+ }, [onPourCancel, nozzle]);
1276
+ const handleUpdateContext = React.useCallback(
1277
+ (key, value) => {
1278
+ context.set(key, value);
1279
+ },
1280
+ [context]
1281
+ );
1282
+ const handleRemoveFromContext = React.useCallback(
1283
+ (key) => {
1284
+ context.remove(key);
1285
+ },
1286
+ [context]
1287
+ );
1288
+ const handlers = kosUiSdk.usePressGesture({
1289
+ onPressed: handlePour,
1290
+ onRelease: handleCancelPour
1291
+ });
1292
+ return {
1293
+ handlers: handlers.dom,
1294
+ cancel: forceCancelPour,
1295
+ updatePourContext: handleUpdateContext,
1296
+ removeFromPourContext: handleRemoveFromContext,
1297
+ status: nozzle
1298
+ };
1299
+ };
1300
+ const logger = kosUiSdk.KosLog.createLogger({
1268
1301
  name: "usePour",
1269
1302
  group: "kos-hooks"
1270
1303
  });
@@ -1278,15 +1311,15 @@ const usePourTarget = ({
1278
1311
  strategy = HoldToPourStrategy
1279
1312
  }) => {
1280
1313
  const [context, _setContext] = React.useState(
1281
- pourContext || new PourContext()
1314
+ pourContext || new dispenseRegistrationManager.PourContext()
1282
1315
  );
1283
1316
  const handlePour = React.useCallback(async () => {
1284
- logger$3.debug(
1317
+ logger.debug(
1285
1318
  `[${strategy?.name}] - calling before pour for pour target ${pourTarget?.id}.`
1286
1319
  );
1287
1320
  const canPour = onBeforePour ? await onBeforePour?.(context) : true;
1288
1321
  if (canPour) {
1289
- logger$3.debug(
1322
+ logger.debug(
1290
1323
  `[${strategy?.name}] - Pour initiated for pour target ${pourTarget?.id}.`
1291
1324
  );
1292
1325
  await strategy?.initiate(pourTarget);
@@ -1295,14 +1328,14 @@ const usePourTarget = ({
1295
1328
  onPourAbort?.();
1296
1329
  }
1297
1330
  } else {
1298
- logger$3.debug(
1331
+ logger.debug(
1299
1332
  `[${strategy?.name}] - Pour cancelled for pour target ${pourTarget?.id}.`
1300
1333
  );
1301
1334
  onPourCancel?.();
1302
1335
  }
1303
1336
  }, [onPour, onBeforePour, onPourAbort, pourTarget, strategy, context]);
1304
1337
  const handleCancelPour = React.useCallback(async () => {
1305
- logger$3.debug(
1338
+ logger.debug(
1306
1339
  `[${strategy?.name}] - Pour initiate ended called for pour target ${pourTarget?.id}.`
1307
1340
  );
1308
1341
  const ignore = await strategy?.initiateEnded?.(pourTarget);
@@ -1311,7 +1344,7 @@ const usePourTarget = ({
1311
1344
  }
1312
1345
  }, [onPourCancel, pourTarget, strategy]);
1313
1346
  const forceCancelPour = React.useCallback(async () => {
1314
- logger$3.debug(`Force cancelling pour for pour target ${pourTarget?.id}.`);
1347
+ logger.debug(`Force cancelling pour for pour target ${pourTarget?.id}.`);
1315
1348
  await pourTarget?.cancelPour();
1316
1349
  onPourCancel?.();
1317
1350
  }, [onPourCancel, pourTarget]);
@@ -1339,98 +1372,6 @@ const usePourTarget = ({
1339
1372
  status: pourTarget
1340
1373
  };
1341
1374
  };
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
1375
  const useGenericPour = (id, servicePathFactory, itemId, data) => {
1435
1376
  const modelId = id;
1436
1377
  const result = kosUiSdk.useKosModel({
@@ -1568,7 +1509,19 @@ function createDispenseKitContext() {
1568
1509
  }
1569
1510
  return ctx;
1570
1511
  };
1571
- return [useCuiKitContext, CuiKitContext.Provider];
1512
+ const useCuiPour = (options = {}) => {
1513
+ const kit = React.useContext(CuiKitContext);
1514
+ const gesture = kosUiSdk.usePressGesture({
1515
+ onPressed: () => void kit?.pour.press(options),
1516
+ onRelease: () => kit?.pour.release(options)
1517
+ });
1518
+ return {
1519
+ handlers: gesture.dom,
1520
+ start: async () => await kit?.pour.start(options) ?? false,
1521
+ cancel: () => kit?.pour.cancel()
1522
+ };
1523
+ };
1524
+ return [useCuiKitContext, CuiKitContext.Provider, useCuiPour];
1572
1525
  }
1573
1526
  function CuiKitWrapper({
1574
1527
  children,
@@ -1617,10 +1570,11 @@ function CuiKit({
1617
1570
  ) }) : null;
1618
1571
  }
1619
1572
  function initializeCuiKit(props) {
1620
- const [useCuiKitContext, DispenseKitProvider] = createDispenseKitContext();
1573
+ const [useCuiKitContext, DispenseKitProvider, useCuiPour] = createDispenseKitContext();
1621
1574
  return [
1622
1575
  useCuiKitContext,
1623
- CuiKit({ provider: DispenseKitProvider, props })
1576
+ CuiKit({ provider: DispenseKitProvider, props }),
1577
+ useCuiPour
1624
1578
  ];
1625
1579
  }
1626
1580
  const Holder = React.createContext(void 0);
@@ -1749,7 +1703,6 @@ exports.HolderProvider = HolderProvider;
1749
1703
  exports.IngredientContainerProvider = IngredientContainerProvider;
1750
1704
  exports.IngredientProvider = IngredientProvider;
1751
1705
  exports.NozzleProvider = NozzleProvider;
1752
- exports.PourContext = PourContext;
1753
1706
  exports.PumpProvider = PumpProvider;
1754
1707
  exports.TapOrHoldIntentStrategy = TapOrHoldIntentStrategy;
1755
1708
  exports.TapToPourIntentStrategy = TapToPourIntentStrategy;
@@ -1798,4 +1751,4 @@ exports.withHolderContainer = withHolderContainer;
1798
1751
  exports.withIngredient = withIngredient;
1799
1752
  exports.withIngredientContainer = withIngredientContainer;
1800
1753
  exports.withNozzle = withNozzle;
1801
- //# sourceMappingURL=pump-provider-uNNMh9uh.cjs.map
1754
+ //# sourceMappingURL=pump-provider-BSbTT-BC.cjs.map