@kosdev-code/kos-dispense-sdk 2.1.38 → 2.1.40

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 (38) hide show
  1. package/dispense-registration-manager-C6k10ipu.cjs +2698 -0
  2. package/dispense-registration-manager-C6k10ipu.cjs.map +1 -0
  3. package/dispense-registration-manager-lJlcyq5G.js +2700 -0
  4. package/dispense-registration-manager-lJlcyq5G.js.map +1 -0
  5. package/{extension-utils-DrsPfQWC.js → extension-utils-AS0Z5eod.js} +194 -157
  6. package/{extension-utils-DrsPfQWC.js.map → extension-utils-AS0Z5eod.js.map} +1 -1
  7. package/extension-utils-DNbm2KRk.cjs +500 -0
  8. package/{extension-utils-BDyaRwRN.cjs.map → extension-utils-DNbm2KRk.cjs.map} +1 -1
  9. package/index.cjs +142 -1
  10. package/index.cjs.map +1 -1
  11. package/index.js +124 -121
  12. package/index.js.map +1 -1
  13. package/kos-models.json +1 -1
  14. package/models/models/assembly/holder-utils.d.ts.map +1 -1
  15. package/models/models/holder/holder-model.d.ts.map +1 -1
  16. package/models/models/holder/types/index.d.ts +2 -0
  17. package/models/models/nozzle/nozzle-model.d.ts +1 -0
  18. package/models/models/nozzle/nozzle-model.d.ts.map +1 -1
  19. package/models/models/types/assembly.d.ts +1 -0
  20. package/models/models/types/assembly.d.ts.map +1 -1
  21. package/models.cjs +47 -1
  22. package/models.cjs.map +1 -1
  23. package/models.js +40 -40
  24. package/package.json +14 -2
  25. package/pump-provider-BSEusYig.js +1825 -0
  26. package/{pump-provider-Bytd6qXc.js.map → pump-provider-BSEusYig.js.map} +1 -1
  27. package/pump-provider-D4Ed_gH6.cjs +1824 -0
  28. package/{pump-provider-CTELJBW5.cjs.map → pump-provider-D4Ed_gH6.cjs.map} +1 -1
  29. package/ui.cjs +73 -1
  30. package/ui.cjs.map +1 -1
  31. package/ui.js +67 -67
  32. package/dispense-registration-manager-Cj0565Ze.cjs +0 -2
  33. package/dispense-registration-manager-Cj0565Ze.cjs.map +0 -1
  34. package/dispense-registration-manager-CzAqcL8D.js +0 -2044
  35. package/dispense-registration-manager-CzAqcL8D.js.map +0 -1
  36. package/extension-utils-BDyaRwRN.cjs +0 -2
  37. package/pump-provider-Bytd6qXc.js +0 -1308
  38. package/pump-provider-CTELJBW5.cjs +0 -2
@@ -0,0 +1,1825 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ import { jsx } from "@emotion/react/jsx-runtime";
8
+ import { useKosModel, getKosCompanionModel, kosAutoEffect, KosLog, usePressGesture, EventBus, TimerManager } from "@kosdev-code/kos-ui-sdk";
9
+ import { A as Assembly$1, b as Availability$1, e as Board$1, d as BoardContainer$1, N as Nozzle$1, f as DeviceAssembly, H as Holder$1, j as HolderContainer$1, I as Ingredient$1, k as IngredientContainer$1, G as GenericPour, P as Pump$1 } from "./dispense-registration-manager-lJlcyq5G.js";
10
+ import React, { createContext, useMemo, useContext, useState, useCallback, useEffect, useRef } from "react";
11
+ const useAssembly = () => {
12
+ const modelId = Assembly$1.type;
13
+ const result = useKosModel({
14
+ modelId,
15
+ modelType: Assembly$1.type,
16
+ options: {}
17
+ });
18
+ return result;
19
+ };
20
+ function withAssembly(WrappedComponent) {
21
+ return (props) => {
22
+ const { model, status, KosModelLoader } = useAssembly();
23
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, assembly: model }) });
24
+ };
25
+ }
26
+ const useAvailability = () => {
27
+ const modelId = Availability$1.type;
28
+ const result = useKosModel({
29
+ modelId,
30
+ modelType: Availability$1.type,
31
+ options: {}
32
+ });
33
+ return result;
34
+ };
35
+ function withBeverage(WrappedComponent) {
36
+ return (props) => {
37
+ const { model, status, KosModelLoader } = useAvailability();
38
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, beverage: model }) });
39
+ };
40
+ }
41
+ const useBoard = (id) => {
42
+ const modelId = id;
43
+ const result = useKosModel({
44
+ modelId,
45
+ modelType: Board$1.type,
46
+ options: {}
47
+ });
48
+ return result;
49
+ };
50
+ function withBoard(WrappedComponent) {
51
+ return (id) => (props) => {
52
+ const { model, status, KosModelLoader } = useBoard(id);
53
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, board: model }) });
54
+ };
55
+ }
56
+ const useBoardContainer = () => {
57
+ const modelId = BoardContainer$1.type;
58
+ const result = useKosModel({
59
+ modelId,
60
+ modelType: BoardContainer$1.type,
61
+ options: {}
62
+ });
63
+ return result;
64
+ };
65
+ function withBoardContainer(WrappedComponent) {
66
+ return (props) => {
67
+ const { model, status, KosModelLoader } = useBoardContainer();
68
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, boardContainer: model }) });
69
+ };
70
+ }
71
+ const useNozzle = (path) => {
72
+ const modelId = path;
73
+ const result = useKosModel({
74
+ modelId,
75
+ modelType: Nozzle$1.type,
76
+ options: {
77
+ path
78
+ }
79
+ });
80
+ return result;
81
+ };
82
+ const Nozzle = createContext(void 0);
83
+ const NozzleProvider = ({ children, path }) => {
84
+ const { model, ready } = useNozzle(path);
85
+ const value = useMemo(() => {
86
+ if (ready && model) {
87
+ return { model };
88
+ }
89
+ return {};
90
+ }, [ready, model]);
91
+ return /* @__PURE__ */ jsx(Nozzle.Provider, { value, children });
92
+ };
93
+ const useNozzleContext = () => {
94
+ const context = useContext(Nozzle);
95
+ if (!context) {
96
+ throw new Error("useNozzleContext must be used within a NozzleProvider");
97
+ }
98
+ return context;
99
+ };
100
+ const useBeverages = ({
101
+ onBeverageSelected,
102
+ onBeverageListUpdated,
103
+ onClearBeverage,
104
+ companionType
105
+ }) => {
106
+ const { model: nozzle } = useNozzleContext();
107
+ const [beverages, setBeverages] = useState([]);
108
+ const [selectedBeverage, setSelectedBeverage] = useState(null);
109
+ const companions = useMemo(() => {
110
+ if (!companionType)
111
+ return [];
112
+ return beverages.map(
113
+ (brand) => getKosCompanionModel(brand, companionType)
114
+ );
115
+ }, [beverages, companionType]);
116
+ const selectBeverage = useCallback(
117
+ async (beverage, context, forceUpdate) => {
118
+ setSelectedBeverage(beverage);
119
+ await (nozzle == null ? void 0 : nozzle.setSelectedPourable({ beverage, context }, forceUpdate));
120
+ onBeverageSelected == null ? void 0 : onBeverageSelected(beverage);
121
+ },
122
+ [nozzle, onBeverageSelected]
123
+ );
124
+ const clearBeverage = useCallback(async () => {
125
+ setSelectedBeverage(null);
126
+ await (nozzle == null ? void 0 : nozzle.setSelectedPourable({ beverage: void 0 }));
127
+ onClearBeverage == null ? void 0 : onClearBeverage();
128
+ }, [nozzle, onClearBeverage]);
129
+ useEffect(() => {
130
+ const disposer = kosAutoEffect(() => {
131
+ if (!nozzle)
132
+ return;
133
+ const selectedBrand = nozzle.selectedBrand;
134
+ if (!selectedBrand) {
135
+ const allBeverages = nozzle.getGroupAvailabilityItems("beverages").filter((beverage) => beverage.visible);
136
+ setBeverages(allBeverages ?? []);
137
+ onBeverageListUpdated == null ? void 0 : onBeverageListUpdated(allBeverages);
138
+ return;
139
+ }
140
+ const beverages2 = nozzle.getAvailabilityByParent(selectedBrand.id).filter((b) => b.visible);
141
+ setBeverages(beverages2 ?? []);
142
+ onBeverageListUpdated == null ? void 0 : onBeverageListUpdated(beverages2);
143
+ });
144
+ return () => {
145
+ disposer();
146
+ };
147
+ }, [nozzle]);
148
+ return {
149
+ beverages,
150
+ beverageCompanions: companions,
151
+ selectBeverage,
152
+ selectedBeverage,
153
+ clearBeverage
154
+ };
155
+ };
156
+ const useBrands = ({
157
+ onBrandSelected,
158
+ onBrandCleared,
159
+ companionType
160
+ }) => {
161
+ const { model: nozzle } = useNozzleContext();
162
+ const [selectedBrand, setSelectedBrand] = useState(null);
163
+ const [brands, setBrands] = useState([]);
164
+ const companions = useMemo(() => {
165
+ if (!companionType)
166
+ return [];
167
+ return brands.map((brand) => getKosCompanionModel(brand, companionType));
168
+ }, [brands, companionType]);
169
+ const selectBrand = useCallback(
170
+ async (brand, context, forceUpdate) => {
171
+ setSelectedBrand(brand);
172
+ if (forceUpdate) {
173
+ KosLog.warn(
174
+ `forceUpdate is not currently supported when setting brand`
175
+ );
176
+ }
177
+ nozzle == null ? void 0 : nozzle.setSelectedBrand(brand, context);
178
+ onBrandSelected == null ? void 0 : onBrandSelected(brand);
179
+ },
180
+ [nozzle, onBrandSelected]
181
+ );
182
+ const clearBrand = useCallback(() => {
183
+ setSelectedBrand(null);
184
+ nozzle == null ? void 0 : nozzle.setSelectedBrand(void 0);
185
+ onBrandCleared == null ? void 0 : onBrandCleared();
186
+ }, [nozzle, onBrandCleared]);
187
+ useEffect(() => {
188
+ const disposer = kosAutoEffect(() => {
189
+ if (!nozzle)
190
+ return;
191
+ setBrands(nozzle.visibleBrands);
192
+ });
193
+ return () => {
194
+ disposer();
195
+ };
196
+ }, [nozzle]);
197
+ return {
198
+ brands,
199
+ brandCompanions: companions,
200
+ selectedBrand,
201
+ selectBrand,
202
+ clearBrand
203
+ };
204
+ };
205
+ class PourContext {
206
+ constructor() {
207
+ __publicField(this, "_data", /* @__PURE__ */ new Map());
208
+ }
209
+ get(key) {
210
+ return this._data.get(key);
211
+ }
212
+ set(key, value) {
213
+ this._data.set(key, value);
214
+ }
215
+ remove(key) {
216
+ this._data.delete(key);
217
+ }
218
+ has(key) {
219
+ return this._data.has(key);
220
+ }
221
+ }
222
+ const logger$7 = KosLog.createLogger({
223
+ name: "HoldToPourStrategy",
224
+ group: "kos-hooks"
225
+ });
226
+ const HoldToPourStrategy = {
227
+ name: "HoldToPourStrategy",
228
+ async initiate(nozzle) {
229
+ if (!(nozzle == null ? void 0 : nozzle.canPour)) {
230
+ logger$7.debug(`Nozzle ${nozzle == null ? void 0 : nozzle.id} cannot pour. Returning early.`);
231
+ return;
232
+ }
233
+ await (nozzle == null ? void 0 : nozzle.pour());
234
+ },
235
+ async initiateEnded(nozzle) {
236
+ await (nozzle == null ? void 0 : nozzle.cancelPour());
237
+ }
238
+ };
239
+ const logger$6 = KosLog.createLogger({
240
+ name: "useNozzlePour",
241
+ group: "kos-hooks"
242
+ });
243
+ const useNozzlePour = ({
244
+ onPour,
245
+ onPourCancel,
246
+ onBeforePour,
247
+ onBeforePourRejected,
248
+ pourContext,
249
+ strategy = HoldToPourStrategy
250
+ }) => {
251
+ const { model: nozzle } = useNozzleContext();
252
+ const [context, _setContext] = useState(
253
+ pourContext || new PourContext()
254
+ );
255
+ const handlePour = useCallback(async () => {
256
+ const canPour = onBeforePour ? await (onBeforePour == null ? void 0 : onBeforePour(context)) : true;
257
+ if (canPour) {
258
+ logger$6.debug(
259
+ `[${strategy == null ? void 0 : strategy.name}] - Pour initiated for nozzle ${nozzle == null ? void 0 : nozzle.id}.`
260
+ );
261
+ strategy == null ? void 0 : strategy.initiate(nozzle);
262
+ onPour == null ? void 0 : onPour();
263
+ } else {
264
+ logger$6.debug(
265
+ `[${strategy == null ? void 0 : strategy.name}] - Did not pass onBeforePour gate for nozzle ${nozzle == null ? void 0 : nozzle.id}. Cancelling pour.`
266
+ );
267
+ onBeforePourRejected == null ? void 0 : onBeforePourRejected();
268
+ }
269
+ }, [
270
+ onPour,
271
+ nozzle,
272
+ strategy,
273
+ onBeforePour,
274
+ onPourCancel,
275
+ context,
276
+ onBeforePourRejected
277
+ ]);
278
+ const handleCancelPour = useCallback(() => {
279
+ var _a;
280
+ logger$6.debug(
281
+ `[${strategy == null ? void 0 : strategy.name}] - Pour initiate ended called for nozzle ${nozzle == null ? void 0 : nozzle.id}.`
282
+ );
283
+ (_a = strategy == null ? void 0 : strategy.initiateEnded) == null ? void 0 : _a.call(strategy, nozzle);
284
+ onPourCancel == null ? void 0 : onPourCancel();
285
+ }, [onPourCancel, nozzle, strategy]);
286
+ const forceCancelPour = useCallback(() => {
287
+ logger$6.debug(`Force cancelling pour for nozzle ${nozzle == null ? void 0 : nozzle.id}.`);
288
+ nozzle == null ? void 0 : nozzle.cancelPour();
289
+ onPourCancel == null ? void 0 : onPourCancel();
290
+ }, [onPourCancel, nozzle]);
291
+ const handleUpdateContext = useCallback(
292
+ (key, value) => {
293
+ context.set(key, value);
294
+ },
295
+ [context]
296
+ );
297
+ const handleRemoveFromContext = useCallback(
298
+ (key) => {
299
+ context.remove(key);
300
+ },
301
+ [context]
302
+ );
303
+ const handlers = usePressGesture({
304
+ onPressed: handlePour,
305
+ onRelease: handleCancelPour
306
+ });
307
+ return {
308
+ handlers: handlers.dom,
309
+ cancel: forceCancelPour,
310
+ updatePourContext: handleUpdateContext,
311
+ removeFromPourContext: handleRemoveFromContext,
312
+ status: nozzle
313
+ };
314
+ };
315
+ const useFlavors = ({
316
+ onFlavorSelected,
317
+ onFlavorCleared,
318
+ companionType
319
+ }) => {
320
+ const { model: nozzle } = useNozzleContext();
321
+ const flavors = useMemo(
322
+ () => (nozzle == null ? void 0 : nozzle.getGroupAvailabilityItems("flavors").filter((f) => f.visible)) ?? [],
323
+ [nozzle]
324
+ );
325
+ const companions = useMemo(() => {
326
+ if (!companionType)
327
+ return [];
328
+ return flavors.map(
329
+ (flavor) => getKosCompanionModel(flavor, companionType)
330
+ );
331
+ }, [flavors, companionType]);
332
+ const [selectedFlavors, setSelectedFlavors] = useState([]);
333
+ const selectFlavor = useCallback(
334
+ async (flavor, context, forceUpdate) => {
335
+ setSelectedFlavors(
336
+ (previous) => (previous == null ? void 0 : previous.includes(flavor)) ? [...previous.filter((p) => p !== flavor)] : [...previous ?? [], flavor]
337
+ );
338
+ if (nozzle == null ? void 0 : nozzle.selectedPourable) {
339
+ const { beverage } = nozzle.selectedPourable;
340
+ await nozzle.setSelectedPourable(
341
+ {
342
+ beverage,
343
+ additional: selectedFlavors ?? [],
344
+ context
345
+ },
346
+ forceUpdate
347
+ );
348
+ }
349
+ onFlavorSelected == null ? void 0 : onFlavorSelected(flavor, selectedFlavors ?? []);
350
+ },
351
+ [nozzle, onFlavorSelected, selectedFlavors]
352
+ );
353
+ const clear = useCallback(async () => {
354
+ setSelectedFlavors([]);
355
+ if (nozzle == null ? void 0 : nozzle.selectedPourable) {
356
+ const { beverage } = nozzle.selectedPourable;
357
+ nozzle.setSelectedPourable({ beverage });
358
+ onFlavorCleared == null ? void 0 : onFlavorCleared();
359
+ }
360
+ }, [nozzle, onFlavorCleared]);
361
+ return {
362
+ flavors,
363
+ flavorCompanions: companions,
364
+ selectFlavor,
365
+ selectedFlavors,
366
+ clearFlavors: clear
367
+ };
368
+ };
369
+ const DISPENSE_GROUP_BRAND = "brands";
370
+ const DISPENSE_GROUP_BEVERAGE = "beverages";
371
+ const DISPENSE_GROUP_FLAVOR = "flavors";
372
+ const log$2 = KosLog.createLogger({ name: "use-cui-kit" });
373
+ const useCuiKit = ({
374
+ initialGroup = DISPENSE_GROUP_BRAND,
375
+ options = {}
376
+ }) => {
377
+ var _a, _b, _c;
378
+ const [currentGroup, setCurrentGroup] = useState(initialGroup);
379
+ const { model: nozzle } = useNozzleContext();
380
+ const timersRef = useRef([]);
381
+ const updatePourContext = useRef();
382
+ const removeFromPourContext = useRef();
383
+ const onBrandSelected = useCallback(
384
+ (model) => {
385
+ setCurrentGroup(DISPENSE_GROUP_BEVERAGE);
386
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/brand/selected/`;
387
+ EventBus.publish(topic, model);
388
+ },
389
+ [nozzle == null ? void 0 : nozzle.path]
390
+ );
391
+ const onBrandCleared = useCallback(() => {
392
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/brand/cleared/`;
393
+ EventBus.publish(topic, {});
394
+ }, [nozzle == null ? void 0 : nozzle.path]);
395
+ const onBeverageListUpdated = useCallback(
396
+ (beverages2) => {
397
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/beverage/list/updated/`;
398
+ EventBus.publish(topic, beverages2);
399
+ },
400
+ [nozzle == null ? void 0 : nozzle.path]
401
+ );
402
+ const onBeverageSelected = useCallback(
403
+ (model) => {
404
+ var _a2;
405
+ setCurrentGroup(DISPENSE_GROUP_FLAVOR);
406
+ (_a2 = updatePourContext.current) == null ? void 0 : _a2.call(updatePourContext, "selectedBeverage", model);
407
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/beverage/selected/`;
408
+ EventBus.publish(topic, model);
409
+ },
410
+ [nozzle == null ? void 0 : nozzle.path]
411
+ );
412
+ const onBeverageCleared = useCallback(() => {
413
+ var _a2;
414
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/beverage/cleared/`;
415
+ (_a2 = removeFromPourContext.current) == null ? void 0 : _a2.call(removeFromPourContext, "selectedBeverage");
416
+ EventBus.publish(topic, {});
417
+ }, [nozzle == null ? void 0 : nozzle.path]);
418
+ const onFlavorSelected = useCallback(
419
+ (model) => {
420
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/flavor/selected/`;
421
+ EventBus.publish(topic, model);
422
+ },
423
+ [nozzle == null ? void 0 : nozzle.path]
424
+ );
425
+ const onFlavorCleared = useCallback(() => {
426
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/flavor/cleared/`;
427
+ EventBus.publish(topic, {});
428
+ }, [nozzle == null ? void 0 : nozzle.path]);
429
+ const onPour = useCallback(() => {
430
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/pour/`;
431
+ EventBus.publish(topic, {});
432
+ }, [nozzle == null ? void 0 : nozzle.path]);
433
+ const handleBeforePour = useCallback(
434
+ async (context) => {
435
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/pre/pour/`;
436
+ EventBus.publish(topic, {});
437
+ return await (onBeforePour == null ? void 0 : onBeforePour(context)) || true;
438
+ },
439
+ [nozzle == null ? void 0 : nozzle.path]
440
+ );
441
+ const handleBeforePourRejected = useCallback(async () => {
442
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/pre/pour/rejected/`;
443
+ EventBus.publish(topic, {});
444
+ }, [nozzle == null ? void 0 : nozzle.path]);
445
+ const onPourCancel = useCallback(() => {
446
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/pour/cancel/`;
447
+ EventBus.publish(topic, {});
448
+ }, [nozzle == null ? void 0 : nozzle.path]);
449
+ const { brands, selectBrand, selectedBrand, clearBrand, brandCompanions } = useBrands({
450
+ companionType: (_a = options.companionTypes) == null ? void 0 : _a.brand,
451
+ onBrandSelected,
452
+ onBrandCleared
453
+ });
454
+ const {
455
+ beverages,
456
+ selectBeverage,
457
+ selectedBeverage,
458
+ clearBeverage,
459
+ beverageCompanions
460
+ } = useBeverages({
461
+ companionType: (_b = options.companionTypes) == null ? void 0 : _b.beverage,
462
+ onBeverageSelected,
463
+ onClearBeverage: onBeverageCleared,
464
+ onBeverageListUpdated
465
+ });
466
+ const {
467
+ clearFlavors,
468
+ flavors,
469
+ selectFlavor,
470
+ selectedFlavors,
471
+ flavorCompanions
472
+ } = useFlavors({
473
+ companionType: (_c = options.companionTypes) == null ? void 0 : _c.flavor,
474
+ onFlavorSelected,
475
+ onFlavorCleared
476
+ });
477
+ const [onBeforePour, setOnBeforePour] = useState();
478
+ const updateOnBeforePour = useCallback((callback) => {
479
+ setOnBeforePour(() => callback);
480
+ }, []);
481
+ const pour = useNozzlePour({
482
+ onPour,
483
+ onPourCancel,
484
+ onBeforePour: handleBeforePour,
485
+ onBeforePourRejected: handleBeforePourRejected
486
+ });
487
+ updatePourContext.current = pour.updatePourContext;
488
+ removeFromPourContext.current = pour.removeFromPourContext;
489
+ const back = useCallback(() => {
490
+ log$2.debug(`Navigating back from group: ${currentGroup}`);
491
+ switch (currentGroup) {
492
+ case DISPENSE_GROUP_BRAND:
493
+ clearBeverage();
494
+ clearBrand();
495
+ break;
496
+ case DISPENSE_GROUP_BEVERAGE:
497
+ case DISPENSE_GROUP_FLAVOR:
498
+ setCurrentGroup(initialGroup);
499
+ clearBeverage();
500
+ clearBrand();
501
+ break;
502
+ }
503
+ }, [clearBeverage, clearBrand, currentGroup, initialGroup]);
504
+ const home = useCallback(() => {
505
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/home/`;
506
+ EventBus.publish(topic, {});
507
+ setCurrentGroup(initialGroup);
508
+ if (initialGroup === DISPENSE_GROUP_BRAND) {
509
+ clearBeverage();
510
+ clearBrand();
511
+ }
512
+ if (initialGroup === DISPENSE_GROUP_BEVERAGE) {
513
+ clearBeverage();
514
+ }
515
+ }, [clearBeverage, clearBrand, initialGroup]);
516
+ const pauseTimers = useCallback(() => {
517
+ if (timersRef.current.length === 0) {
518
+ log$2.debug("No timers to pause.");
519
+ return;
520
+ }
521
+ log$2.debug(`Pausing ${timersRef.current.length} timers.`);
522
+ timersRef.current.forEach((timer) => {
523
+ log$2.debug(`Pausing timer with id ${timer.id}.`);
524
+ timer.pause();
525
+ });
526
+ }, []);
527
+ const restartTimers = useCallback(() => {
528
+ if (timersRef.current.length === 0) {
529
+ log$2.debug("No timers to restart.");
530
+ return;
531
+ }
532
+ log$2.debug(`Restarting ${timersRef.current.length} timers.`);
533
+ timersRef.current.forEach((timer) => {
534
+ log$2.debug(`Restarting timer with id ${timer.id}.`);
535
+ timer.restart();
536
+ });
537
+ }, []);
538
+ const addTimer = useCallback((timer) => {
539
+ if (!timer) {
540
+ return;
541
+ }
542
+ if (timersRef.current.some((t) => t.id === timer.id)) {
543
+ log$2.debug(`Timer with id ${timer.id} already exists.`);
544
+ return;
545
+ }
546
+ timersRef.current.push(timer);
547
+ }, []);
548
+ return {
549
+ timers: {
550
+ add: addTimer,
551
+ pause: pauseTimers,
552
+ restart: restartTimers
553
+ },
554
+ nav: {
555
+ currentGroup,
556
+ back,
557
+ home
558
+ },
559
+ pour,
560
+ updateOnBeforePour,
561
+ selections: {
562
+ [DISPENSE_GROUP_BRAND]: selectedBrand,
563
+ [DISPENSE_GROUP_BEVERAGE]: selectedBeverage,
564
+ [DISPENSE_GROUP_FLAVOR]: selectedFlavors
565
+ },
566
+ [DISPENSE_GROUP_BRAND]: {
567
+ models: brands,
568
+ companions: brandCompanions,
569
+ clear: clearBrand,
570
+ handlers: {
571
+ onSelected: selectBrand
572
+ }
573
+ },
574
+ [DISPENSE_GROUP_BEVERAGE]: {
575
+ models: beverages,
576
+ companions: beverageCompanions,
577
+ clear: clearBeverage,
578
+ handlers: {
579
+ onSelected: selectBeverage
580
+ }
581
+ },
582
+ [DISPENSE_GROUP_FLAVOR]: {
583
+ models: flavors,
584
+ companions: flavorCompanions,
585
+ clear: clearFlavors,
586
+ handlers: {
587
+ onSelected: selectFlavor
588
+ }
589
+ }
590
+ };
591
+ };
592
+ const useAmbientAttractTimers = (props) => {
593
+ const { model: nozzle } = useNozzleContext();
594
+ const [attractTimer, setAttractTimer] = useState(null);
595
+ const {
596
+ onAmbientTimer,
597
+ onAttractTimer,
598
+ onResetAttractTimer,
599
+ onResumeAttractTimer,
600
+ defaultAttractTime,
601
+ defaultAmbientTime
602
+ } = props;
603
+ const handleAmbientTimer = useCallback(() => {
604
+ if (onAmbientTimer) {
605
+ KosLog.info("Ambient timer expired. Calling callback");
606
+ onAmbientTimer == null ? void 0 : onAmbientTimer();
607
+ }
608
+ }, [onAmbientTimer]);
609
+ const handleAttractTimer = useCallback(() => {
610
+ if (onAttractTimer) {
611
+ KosLog.info("Attract timer expired. Calling callback");
612
+ onAttractTimer == null ? void 0 : onAttractTimer();
613
+ }
614
+ }, [onAttractTimer]);
615
+ const handleResetAttractTimer = useCallback(() => {
616
+ if (attractTimer) {
617
+ attractTimer.restart();
618
+ onResetAttractTimer == null ? void 0 : onResetAttractTimer();
619
+ }
620
+ }, [attractTimer, onResetAttractTimer]);
621
+ const handlePauseAttractTimer = useCallback(() => {
622
+ if (attractTimer) {
623
+ attractTimer.reset();
624
+ onResetAttractTimer == null ? void 0 : onResetAttractTimer();
625
+ }
626
+ }, [attractTimer, onResetAttractTimer]);
627
+ const handleResume = useCallback(() => {
628
+ if (attractTimer) {
629
+ attractTimer.pause();
630
+ onResumeAttractTimer == null ? void 0 : onResumeAttractTimer();
631
+ }
632
+ }, [attractTimer, onResumeAttractTimer]);
633
+ useEffect(() => {
634
+ if (nozzle && defaultAttractTime) {
635
+ KosLog.info("Nozzle is available. Creating timers");
636
+ const timer = TimerManager.createTimer(
637
+ "attract-timer-" + nozzle.path,
638
+ defaultAttractTime
639
+ );
640
+ if (defaultAttractTime) {
641
+ timer == null ? void 0 : timer.addTimeoutAction({
642
+ name: "attract-timer",
643
+ remainingTime: 0,
644
+ action: handleAttractTimer
645
+ });
646
+ }
647
+ if (defaultAmbientTime) {
648
+ timer == null ? void 0 : timer.addTimeoutAction({
649
+ name: "ambient-timer",
650
+ remainingTime: defaultAmbientTime,
651
+ action: handleAmbientTimer
652
+ });
653
+ }
654
+ if (defaultAttractTime) {
655
+ timer == null ? void 0 : timer.start();
656
+ }
657
+ setAttractTimer(timer ?? null);
658
+ return () => {
659
+ timer == null ? void 0 : timer.reset();
660
+ setAttractTimer(null);
661
+ };
662
+ }
663
+ return () => {
664
+ KosLog.info("Nozzle is not available. No timers to clear");
665
+ };
666
+ }, [
667
+ defaultAmbientTime,
668
+ defaultAttractTime,
669
+ handleAmbientTimer,
670
+ handleAttractTimer,
671
+ nozzle
672
+ ]);
673
+ return {
674
+ attractTimer,
675
+ restart: handleResetAttractTimer,
676
+ pause: handlePauseAttractTimer,
677
+ resume: handleResume
678
+ };
679
+ };
680
+ const DISPENSE_EVENT_CONFIGS = [
681
+ { path: "brand/selected", callbackKey: "onBrandSelected" },
682
+ { path: "brand/cleared", callbackKey: "onBrandCleared" },
683
+ { path: "beverage/list/updated", callbackKey: "onBeverageListUpdated" },
684
+ { path: "beverage/selected", callbackKey: "onBeverageSelected" },
685
+ { path: "beverage/cleared", callbackKey: "onBeverageCleared" },
686
+ { path: "flavor/selected", callbackKey: "onFlavorSelected" },
687
+ { path: "flavor/cleared", callbackKey: "onFlavorCleared" },
688
+ { path: "pour", callbackKey: "onPour" },
689
+ { path: "pour/cancel", callbackKey: "onPourCancel" },
690
+ { path: "pre/pour/rejected", callbackKey: "onBeforePourRejected" },
691
+ { path: "ambient/start", callbackKey: "onAmbientTimer" },
692
+ { path: "attract/start", callbackKey: "onAttractTimer" },
693
+ { path: "attract/resume", callbackKey: "onResumeAttractTimer" },
694
+ { path: "idle/timeout", callbackKey: "onIdleTimeout" },
695
+ { path: "are-you-there/timeout", callbackKey: "onAreYouThereTimeout" },
696
+ { path: "init", callbackKey: "onInit" },
697
+ { path: "home", callbackKey: "onReturnToHome" }
698
+ ];
699
+ function buildDispenseTopics(nozzlePath, callbacks) {
700
+ if (!nozzlePath) {
701
+ return [];
702
+ }
703
+ return DISPENSE_EVENT_CONFIGS.filter(
704
+ (config) => callbacks[config.callbackKey] !== void 0
705
+ ).map((config) => {
706
+ return {
707
+ topic: `/kos/dispense/${nozzlePath}/${config.path}/`,
708
+ callback: callbacks[config.callbackKey]
709
+ };
710
+ });
711
+ }
712
+ const subscribe = (topic, callback) => {
713
+ if (callback) {
714
+ const callbackWrapper = (args) => {
715
+ if (args && args.body) {
716
+ callback(args.body);
717
+ }
718
+ };
719
+ const result = EventBus.subscribe(topic, callbackWrapper);
720
+ return result.unsubscribe;
721
+ }
722
+ return void 0;
723
+ };
724
+ const useDispenseLifecycle = ({
725
+ onInit,
726
+ onBrandSelected,
727
+ onBrandCleared,
728
+ onBeverageCleared,
729
+ onBeverageSelected,
730
+ onBeverageListUpdated,
731
+ onFlavorCleared,
732
+ onFlavorSelected,
733
+ onReturnToHome,
734
+ onPour,
735
+ onPourCancel,
736
+ onBeforePourRejected,
737
+ onAmbientTimer,
738
+ onAttractTimer,
739
+ onResumeAttractTimer,
740
+ onIdleTimeout,
741
+ onAreYouThereTimeout
742
+ }) => {
743
+ const { model: nozzle } = useNozzleContext();
744
+ useEffect(() => {
745
+ const topics = buildDispenseTopics(nozzle == null ? void 0 : nozzle.path, {
746
+ onBrandSelected,
747
+ onBrandCleared,
748
+ onBeverageListUpdated,
749
+ onBeverageSelected,
750
+ onBeverageCleared,
751
+ onFlavorSelected,
752
+ onFlavorCleared,
753
+ onPour,
754
+ onPourCancel,
755
+ onBeforePourRejected,
756
+ onAmbientTimer,
757
+ onAttractTimer,
758
+ onResumeAttractTimer,
759
+ onIdleTimeout,
760
+ onAreYouThereTimeout,
761
+ onInit,
762
+ onReturnToHome
763
+ });
764
+ const disposers = topics.map(
765
+ ({ topic, callback }) => subscribe(topic, callback)
766
+ );
767
+ return () => {
768
+ disposers.forEach((disposer) => disposer == null ? void 0 : disposer());
769
+ };
770
+ }, [
771
+ nozzle == null ? void 0 : nozzle.path,
772
+ onAmbientTimer,
773
+ onAttractTimer,
774
+ onBeverageCleared,
775
+ onBeverageSelected,
776
+ onBeverageListUpdated,
777
+ onBrandCleared,
778
+ onBrandSelected,
779
+ onFlavorCleared,
780
+ onFlavorSelected,
781
+ onPour,
782
+ onPourCancel,
783
+ onBeforePourRejected,
784
+ onResumeAttractTimer,
785
+ onIdleTimeout,
786
+ onAreYouThereTimeout,
787
+ onInit,
788
+ onReturnToHome
789
+ ]);
790
+ };
791
+ const log$1 = KosLog.createLogger({ name: "useCuiKitTimers" });
792
+ const useCuiKitTimers = (props) => {
793
+ const { model: nozzle } = useNozzleContext();
794
+ const [idleTimer, setIdleTimer] = useState(null);
795
+ const {
796
+ onAreYouThereTimer,
797
+ onIdleTimer,
798
+ onResetIdleTimer,
799
+ defaultAreYouThereTime = 10,
800
+ defaultIdleTime = 20
801
+ } = props;
802
+ const hasAreYouThereFiredRef = useRef(false);
803
+ const handleAreYouThereTimer = useCallback(() => {
804
+ if (!hasAreYouThereFiredRef.current && onAreYouThereTimer) {
805
+ KosLog.info("Are you there timer expired. Calling callback");
806
+ hasAreYouThereFiredRef.current = true;
807
+ onAreYouThereTimer == null ? void 0 : onAreYouThereTimer();
808
+ }
809
+ }, [onAreYouThereTimer]);
810
+ const handleIdleTimer = useCallback(() => {
811
+ log$1.debug(
812
+ "handleIdleTimer called in useCuiKitTimers, onIdleTimer exists:",
813
+ !!onIdleTimer
814
+ );
815
+ if (onIdleTimer) {
816
+ log$1.debug("Idle timer expired. Calling callback");
817
+ onIdleTimer == null ? void 0 : onIdleTimer();
818
+ } else {
819
+ log$1.debug("No onIdleTimer callback provided!");
820
+ }
821
+ }, [onIdleTimer]);
822
+ const handleRestartIdleTimer = useCallback(() => {
823
+ log$1.debug(`TIMER RESTART called for ${props.prefix ?? ""}timer`);
824
+ if (idleTimer) {
825
+ idleTimer.restart();
826
+ hasAreYouThereFiredRef.current = false;
827
+ onResetIdleTimer == null ? void 0 : onResetIdleTimer();
828
+ }
829
+ }, [idleTimer, onResetIdleTimer, props.prefix]);
830
+ const handlePauseIdleTimer = useCallback(() => {
831
+ log$1.debug(`TIMER PAUSE/RESET called for ${props.prefix ?? ""}timer`);
832
+ if (idleTimer) {
833
+ idleTimer.reset();
834
+ hasAreYouThereFiredRef.current = false;
835
+ onResetIdleTimer == null ? void 0 : onResetIdleTimer();
836
+ }
837
+ }, [idleTimer, onResetIdleTimer, props.prefix]);
838
+ useEffect(() => {
839
+ log$1.debug(
840
+ `useCuiKitTimers effect triggered - nozzle: ${!!nozzle}, path: ${nozzle == null ? void 0 : nozzle.path}, callbacks: handleIdle=${!!handleIdleTimer}, handleAreYouThere=${!!handleAreYouThereTimer}`
841
+ );
842
+ if (nozzle) {
843
+ log$1.info("Nozzle is available. Creating timers");
844
+ const timer = TimerManager.createTimer(
845
+ `${props.prefix ?? ""}idle-timer-${nozzle.path}`,
846
+ defaultIdleTime
847
+ );
848
+ log$1.debug(
849
+ `Adding idle timer action for ${props.prefix ?? ""}idle-timer-${nozzle.path} with callback:`,
850
+ !!handleIdleTimer
851
+ );
852
+ timer == null ? void 0 : timer.addTimeoutAction({
853
+ name: "idle-timer",
854
+ remainingTime: 0,
855
+ action: handleIdleTimer
856
+ });
857
+ timer == null ? void 0 : timer.addTimeoutAction({
858
+ name: "are-you-there-timer",
859
+ remainingTime: defaultAreYouThereTime,
860
+ action: handleAreYouThereTimer
861
+ });
862
+ setIdleTimer(timer ?? null);
863
+ return () => {
864
+ timer == null ? void 0 : timer.reset();
865
+ setIdleTimer(null);
866
+ };
867
+ }
868
+ return () => {
869
+ log$1.info("Nozzle is not available. No timers to clear");
870
+ };
871
+ }, [
872
+ defaultAreYouThereTime,
873
+ defaultIdleTime,
874
+ handleAreYouThereTimer,
875
+ handleIdleTimer,
876
+ nozzle,
877
+ props.prefix
878
+ ]);
879
+ return {
880
+ idleTimer,
881
+ restart: handleRestartIdleTimer,
882
+ pause: handlePauseIdleTimer
883
+ };
884
+ };
885
+ const log = KosLog.createLogger({ name: "useDefaultCuiKitLifecycle" });
886
+ const useDefaultCuiKitLifecycle = ({
887
+ kit,
888
+ inactivity,
889
+ pour,
890
+ screens,
891
+ onBeforeAreYouThereTimer,
892
+ areYouThereRejectionPolicy = "pause"
893
+ }) => {
894
+ var _a, _b, _c, _d;
895
+ const [showAmbientScreen, setShowAmbientScreen] = useState(false);
896
+ const [showAttractScreen, setShowAttractScreen] = useState(false);
897
+ const { model: nozzle } = useNozzleContext();
898
+ const [hasPoured, setHasPoured] = useState(false);
899
+ const idleTimeout = (inactivity == null ? void 0 : inactivity.idleTimeout) ?? 15;
900
+ const areYouThereTimeout = (inactivity == null ? void 0 : inactivity.areYouThereTimeoutOffset) ?? 10;
901
+ const idlePourTimeout = (pour == null ? void 0 : pour.idleTimeout) ?? (inactivity == null ? void 0 : inactivity.idleTimeout) ?? 10;
902
+ const areYouTherePourTimeout = (pour == null ? void 0 : pour.areYouThereTimeoutOffset) ?? (inactivity == null ? void 0 : inactivity.areYouThereTimeoutOffset) ?? 5;
903
+ const ambientTimeout = screens == null ? void 0 : screens.ambientTimeoutOffset;
904
+ const attractTimeout = screens == null ? void 0 : screens.attractTimeout;
905
+ const handleIdleTimeout = useCallback(() => {
906
+ log.info("handleIdleTimeout called - navigating home and publishing event");
907
+ setShowAreYouThere(false);
908
+ kit == null ? void 0 : kit.nav.home();
909
+ if (nozzle) {
910
+ const topic = `/kos/dispense/${nozzle.path}/idle/timeout/`;
911
+ EventBus.publish(topic, {});
912
+ }
913
+ }, [(_a = kit == null ? void 0 : kit.nav) == null ? void 0 : _a.home, nozzle]);
914
+ const handleResetIdleTimer = useCallback(() => {
915
+ log.info("handleResetIdleTimer called - resetting idle timer");
916
+ setShowAreYouThere(false);
917
+ }, []);
918
+ const handleAmbientTimer = useCallback(() => {
919
+ if (ambientTimeout) {
920
+ setShowAmbientScreen(true);
921
+ setShowAttractScreen(false);
922
+ if (nozzle) {
923
+ const topic = `/kos/dispense/${nozzle.path}/ambient/start/`;
924
+ EventBus.publish(topic, {});
925
+ }
926
+ }
927
+ }, [ambientTimeout, nozzle]);
928
+ const handleAttractTimer = useCallback(() => {
929
+ if (attractTimeout) {
930
+ setShowAttractScreen(true);
931
+ setShowAmbientScreen(false);
932
+ if (nozzle) {
933
+ const topic = `/kos/dispense/${nozzle.path}/attract/start/`;
934
+ EventBus.publish(topic, {});
935
+ }
936
+ }
937
+ }, [attractTimeout, nozzle]);
938
+ const handleAttractResume = useCallback(() => {
939
+ if (attractTimeout) {
940
+ setShowAttractScreen(false);
941
+ setShowAmbientScreen(false);
942
+ kit == null ? void 0 : kit.nav.home();
943
+ if (nozzle) {
944
+ const topic = `/kos/dispense/${nozzle.path}/attract/resume/`;
945
+ EventBus.publish(topic, {});
946
+ }
947
+ }
948
+ }, [kit == null ? void 0 : kit.nav, attractTimeout, nozzle]);
949
+ const {
950
+ pause: ambientPause,
951
+ restart: ambientRestart,
952
+ attractTimer
953
+ } = useAmbientAttractTimers({
954
+ defaultAmbientTime: ambientTimeout,
955
+ defaultAttractTime: attractTimeout,
956
+ onAmbientTimer: handleAmbientTimer,
957
+ onAttractTimer: handleAttractTimer,
958
+ onResumeAttractTimer: handleAttractResume
959
+ });
960
+ (_b = kit == null ? void 0 : kit.timers) == null ? void 0 : _b.add(attractTimer);
961
+ const [showAreYouThere, setShowAreYouThere] = useState(false);
962
+ log.info(
963
+ "Creating idle timer with timeout:",
964
+ idleTimeout,
965
+ "seconds and callback:",
966
+ !!handleIdleTimeout
967
+ );
968
+ const { pause, restart, idleTimer } = useCuiKitTimers({
969
+ defaultAreYouThereTime: areYouThereTimeout,
970
+ defaultIdleTime: idleTimeout,
971
+ onIdleTimer: handleIdleTimeout,
972
+ onResetIdleTimer: handleResetIdleTimer
973
+ });
974
+ log.info(
975
+ `Creating pour timer with timeout: ${idlePourTimeout} seconds and callback: ${!!handleIdleTimeout}`
976
+ );
977
+ const {
978
+ pause: pausePourTimer,
979
+ restart: restartPourTimer,
980
+ idleTimer: pourIdleTimer
981
+ } = useCuiKitTimers({
982
+ defaultAreYouThereTime: areYouTherePourTimeout,
983
+ defaultIdleTime: idlePourTimeout,
984
+ onIdleTimer: handleIdleTimeout,
985
+ prefix: "pour-"
986
+ });
987
+ const handleAreYouThereTimer = useCallback(async () => {
988
+ let shouldShowAreYouThere = true;
989
+ if (onBeforeAreYouThereTimer) {
990
+ try {
991
+ shouldShowAreYouThere = await onBeforeAreYouThereTimer();
992
+ } catch (error) {
993
+ log.error(`onBeforeAreYouThereTimer callback failed: ${error}`);
994
+ shouldShowAreYouThere = false;
995
+ }
996
+ }
997
+ if (shouldShowAreYouThere) {
998
+ if (nozzle) {
999
+ const topic = `/kos/dispense/${nozzle.path}/are-you-there/timeout/`;
1000
+ EventBus.publish(topic, {});
1001
+ }
1002
+ setShowAreYouThere(true);
1003
+ if (hasPoured) {
1004
+ pausePourTimer();
1005
+ } else {
1006
+ pause();
1007
+ }
1008
+ } else {
1009
+ switch (areYouThereRejectionPolicy) {
1010
+ case "pause":
1011
+ if (hasPoured) {
1012
+ pausePourTimer();
1013
+ } else {
1014
+ pause();
1015
+ }
1016
+ break;
1017
+ case "restart":
1018
+ if (hasPoured) {
1019
+ restartPourTimer();
1020
+ } else {
1021
+ restart();
1022
+ }
1023
+ break;
1024
+ }
1025
+ }
1026
+ }, [onBeforeAreYouThereTimer, nozzle, areYouThereRejectionPolicy, hasPoured]);
1027
+ const clearAreYouThere = useCallback(() => {
1028
+ setShowAreYouThere(false);
1029
+ ambientPause();
1030
+ if (hasPoured) {
1031
+ restartPourTimer();
1032
+ pause();
1033
+ } else {
1034
+ restart();
1035
+ pausePourTimer();
1036
+ }
1037
+ }, [hasPoured, pause, pausePourTimer, restart, restartPourTimer]);
1038
+ useEffect(() => {
1039
+ if (idleTimer) {
1040
+ idleTimer.addTimeoutAction({
1041
+ name: "are-you-there-timer",
1042
+ remainingTime: areYouThereTimeout,
1043
+ action: handleAreYouThereTimer
1044
+ });
1045
+ }
1046
+ }, [idleTimer, areYouThereTimeout, handleAreYouThereTimer]);
1047
+ useEffect(() => {
1048
+ if (pourIdleTimer) {
1049
+ pourIdleTimer.addTimeoutAction({
1050
+ name: "pour-are-you-there-timer",
1051
+ remainingTime: areYouTherePourTimeout,
1052
+ action: handleAreYouThereTimer
1053
+ });
1054
+ }
1055
+ }, [pourIdleTimer, areYouTherePourTimeout, handleAreYouThereTimer]);
1056
+ (_c = kit == null ? void 0 : kit.timers) == null ? void 0 : _c.add(idleTimer);
1057
+ (_d = kit == null ? void 0 : kit.timers) == null ? void 0 : _d.add(pourIdleTimer);
1058
+ const handlePour = useCallback(() => {
1059
+ setHasPoured(false);
1060
+ pausePourTimer();
1061
+ pause();
1062
+ ambientPause();
1063
+ }, [pause, pausePourTimer]);
1064
+ const handlePourCancel = useCallback(() => {
1065
+ setHasPoured(true);
1066
+ log.info("restarting pour timer");
1067
+ restartPourTimer();
1068
+ ambientPause();
1069
+ pause();
1070
+ }, [pause, restartPourTimer]);
1071
+ const handleBeforePourRejected = useCallback(() => {
1072
+ setHasPoured(false);
1073
+ log.info("restarting pour timer on before pour rejected");
1074
+ pausePourTimer();
1075
+ restart();
1076
+ }, []);
1077
+ const handleBrandSelected = useCallback(() => {
1078
+ ambientPause();
1079
+ setShowAttractScreen(false);
1080
+ setShowAmbientScreen(false);
1081
+ restart();
1082
+ }, [ambientPause, restart]);
1083
+ const handleBrandCleared = useCallback(() => {
1084
+ setShowAttractScreen(false);
1085
+ setShowAmbientScreen(false);
1086
+ setHasPoured(false);
1087
+ pausePourTimer();
1088
+ ambientRestart();
1089
+ }, [ambientRestart, pausePourTimer]);
1090
+ const handleBeverageSelected = useCallback(() => {
1091
+ setShowAttractScreen(false);
1092
+ setShowAmbientScreen(false);
1093
+ setHasPoured(false);
1094
+ ambientPause();
1095
+ restart();
1096
+ }, [ambientPause, restart]);
1097
+ const handleBeverageCleared = useCallback(() => {
1098
+ setShowAttractScreen(false);
1099
+ setShowAmbientScreen(false);
1100
+ setHasPoured(false);
1101
+ ambientRestart();
1102
+ pause();
1103
+ pausePourTimer();
1104
+ }, [ambientRestart, pause, pausePourTimer]);
1105
+ const handleInit = useCallback(() => {
1106
+ setShowAttractScreen(false);
1107
+ setShowAmbientScreen(false);
1108
+ ambientRestart();
1109
+ pause();
1110
+ }, [ambientRestart, pause]);
1111
+ useDispenseLifecycle({
1112
+ onBrandSelected: handleBrandSelected,
1113
+ onBrandCleared: handleBrandCleared,
1114
+ onBeverageSelected: handleBeverageSelected,
1115
+ onBeverageCleared: handleBeverageCleared,
1116
+ onPour: handlePour,
1117
+ onPourCancel: handlePourCancel,
1118
+ onBeforePourRejected: handleBeforePourRejected,
1119
+ onInit: handleInit
1120
+ // Note: Timer-related handlers (onIdleTimeout, onAmbientTimer, onAttractTimer,
1121
+ // onResumeAttractTimer, onAreYouThereTimeout) are NOT included here since this
1122
+ // component's own timer hooks call those handlers directly. Including them would
1123
+ // create circular event loops.
1124
+ });
1125
+ const areYouThereCountdown = hasPoured ? areYouTherePourTimeout : areYouThereTimeout;
1126
+ useEffect(() => {
1127
+ if (nozzle && attractTimer) {
1128
+ const topic = `/kos/dispense/${nozzle == null ? void 0 : nozzle.path}/init/`;
1129
+ EventBus.publish(topic, {});
1130
+ }
1131
+ }, [nozzle, attractTimer]);
1132
+ return {
1133
+ showAreYouThere,
1134
+ clearAreYouThere,
1135
+ pauseIdleTimer: pause,
1136
+ restartIdleTimer: restart,
1137
+ areYouThereCountdown,
1138
+ showAmbientScreen,
1139
+ showAttractScreen,
1140
+ pauseScreenTimer: ambientPause,
1141
+ restartScreenTimer: ambientRestart
1142
+ };
1143
+ };
1144
+ const useDeviceAssembly = () => {
1145
+ const modelId = DeviceAssembly.type;
1146
+ const result = useKosModel({
1147
+ modelId,
1148
+ modelType: DeviceAssembly.type,
1149
+ options: {}
1150
+ });
1151
+ return result;
1152
+ };
1153
+ function withDeviceAssembly(WrappedComponent) {
1154
+ return (props) => {
1155
+ const { model, status, KosModelLoader } = useDeviceAssembly();
1156
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, deviceAssembly: model }) });
1157
+ };
1158
+ }
1159
+ const useHolder = (id) => {
1160
+ const modelId = id;
1161
+ const result = useKosModel({
1162
+ modelId,
1163
+ modelType: Holder$1.type,
1164
+ options: {}
1165
+ });
1166
+ return result;
1167
+ };
1168
+ function withHolder(id, WrappedComponent) {
1169
+ return (props) => {
1170
+ const { model, status, KosModelLoader } = useHolder(id);
1171
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, holder: model }) });
1172
+ };
1173
+ }
1174
+ const useHolderContainer = () => {
1175
+ const modelId = HolderContainer$1.type;
1176
+ const result = useKosModel({
1177
+ modelId,
1178
+ modelType: HolderContainer$1.type,
1179
+ options: {}
1180
+ });
1181
+ return result;
1182
+ };
1183
+ function withHolderContainer(WrappedComponent) {
1184
+ return (props) => {
1185
+ const { model, status, KosModelLoader } = useHolderContainer();
1186
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, holderContainer: model }) });
1187
+ };
1188
+ }
1189
+ const useIngredient = () => {
1190
+ const modelId = Ingredient$1.type;
1191
+ const result = useKosModel({
1192
+ modelId,
1193
+ modelType: Ingredient$1.type,
1194
+ options: {}
1195
+ });
1196
+ return result;
1197
+ };
1198
+ const logger$5 = KosLog.createLogger({
1199
+ name: "HoldToPourIntentStrategy",
1200
+ group: "kos-hooks"
1201
+ });
1202
+ const HoldToPourIntentStrategy = {
1203
+ name: "HoldToPourIntentStrategy",
1204
+ async initiate(model, intent) {
1205
+ if (!(model == null ? void 0 : model.canPour)) {
1206
+ logger$5.debug(`${model == null ? void 0 : model.id} cannot pour. Returning early.`);
1207
+ return;
1208
+ }
1209
+ if (intent) {
1210
+ logger$5.debug(`performing intent: ${intent}`);
1211
+ await (model == null ? void 0 : model.performIntent(intent));
1212
+ } else {
1213
+ logger$5.debug("no intent provided. Returning early.");
1214
+ }
1215
+ },
1216
+ async initiateEnded(nozzle) {
1217
+ await (nozzle == null ? void 0 : nozzle.cancelPour());
1218
+ }
1219
+ };
1220
+ const logger$4 = KosLog.createLogger({
1221
+ name: "useNozzlePour",
1222
+ group: "kos-hooks"
1223
+ });
1224
+ const useIngredientPour = ({
1225
+ onPour,
1226
+ onPourCancel,
1227
+ intentContainer,
1228
+ strategy = HoldToPourIntentStrategy
1229
+ }) => {
1230
+ const handlePour = useCallback(() => {
1231
+ logger$4.debug(
1232
+ `[${strategy == null ? void 0 : strategy.name}] - Pour initiated for model ${intentContainer == null ? void 0 : intentContainer.id}.`
1233
+ );
1234
+ strategy == null ? void 0 : strategy.initiate(intentContainer);
1235
+ onPour == null ? void 0 : onPour();
1236
+ }, [onPour, intentContainer, strategy]);
1237
+ const handleCancelPour = useCallback(() => {
1238
+ var _a;
1239
+ logger$4.debug(
1240
+ `[${strategy == null ? void 0 : strategy.name}] - Pour initiate ended called for nozzle ${intentContainer == null ? void 0 : intentContainer.id}.`
1241
+ );
1242
+ (_a = strategy == null ? void 0 : strategy.initiateEnded) == null ? void 0 : _a.call(strategy, intentContainer);
1243
+ onPourCancel == null ? void 0 : onPourCancel();
1244
+ }, [onPourCancel, intentContainer, strategy]);
1245
+ const forceCancelPour = useCallback(() => {
1246
+ logger$4.debug(`Force cancelling pour for nozzle ${intentContainer == null ? void 0 : intentContainer.id}.`);
1247
+ intentContainer == null ? void 0 : intentContainer.cancelPour();
1248
+ onPourCancel == null ? void 0 : onPourCancel();
1249
+ }, [onPourCancel, intentContainer]);
1250
+ const handlers = usePressGesture({
1251
+ onPressed: handlePour,
1252
+ onRelease: handleCancelPour
1253
+ });
1254
+ return {
1255
+ handlers: handlers.dom,
1256
+ cancel: forceCancelPour,
1257
+ status: intentContainer
1258
+ };
1259
+ };
1260
+ function withIngredient(WrappedComponent) {
1261
+ return (props) => {
1262
+ const { model, status, KosModelLoader } = useIngredient();
1263
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, ingredient: model }) });
1264
+ };
1265
+ }
1266
+ const useIngredientContainer = () => {
1267
+ const modelId = IngredientContainer$1.type;
1268
+ const result = useKosModel({
1269
+ modelId,
1270
+ modelType: IngredientContainer$1.type,
1271
+ options: {}
1272
+ });
1273
+ return result;
1274
+ };
1275
+ function withIngredientContainer(WrappedComponent) {
1276
+ return (props) => {
1277
+ const { model, status, KosModelLoader } = useIngredientContainer();
1278
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, ingredientContainer: model }) });
1279
+ };
1280
+ }
1281
+ function withNozzle(path, WrappedComponent) {
1282
+ return (props) => {
1283
+ const { model, status, KosModelLoader } = useNozzle(path);
1284
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, nozzle: model }) });
1285
+ };
1286
+ }
1287
+ const logger$3 = KosLog.createLogger({
1288
+ name: "usePour",
1289
+ group: "kos-hooks"
1290
+ });
1291
+ const usePourTarget = ({
1292
+ onBeforePour,
1293
+ onPour,
1294
+ onPourCancel,
1295
+ onPourAbort,
1296
+ pourTarget,
1297
+ pourContext,
1298
+ strategy = HoldToPourStrategy
1299
+ }) => {
1300
+ const [context, _setContext] = useState(
1301
+ pourContext || new PourContext()
1302
+ );
1303
+ const handlePour = useCallback(async () => {
1304
+ logger$3.debug(
1305
+ `[${strategy == null ? void 0 : strategy.name}] - calling before pour for pour target ${pourTarget == null ? void 0 : pourTarget.id}.`
1306
+ );
1307
+ const canPour = onBeforePour ? await (onBeforePour == null ? void 0 : onBeforePour(context)) : true;
1308
+ if (canPour) {
1309
+ logger$3.debug(
1310
+ `[${strategy == null ? void 0 : strategy.name}] - Pour initiated for pour target ${pourTarget == null ? void 0 : pourTarget.id}.`
1311
+ );
1312
+ await (strategy == null ? void 0 : strategy.initiate(pourTarget));
1313
+ onPour == null ? void 0 : onPour();
1314
+ if (!(pourTarget == null ? void 0 : pourTarget.isPouring)) {
1315
+ onPourAbort == null ? void 0 : onPourAbort();
1316
+ }
1317
+ } else {
1318
+ logger$3.debug(
1319
+ `[${strategy == null ? void 0 : strategy.name}] - Pour cancelled for pour target ${pourTarget == null ? void 0 : pourTarget.id}.`
1320
+ );
1321
+ onPourCancel == null ? void 0 : onPourCancel();
1322
+ }
1323
+ }, [onPour, onBeforePour, onPourAbort, pourTarget, strategy, context]);
1324
+ const handleCancelPour = useCallback(async () => {
1325
+ var _a;
1326
+ logger$3.debug(
1327
+ `[${strategy == null ? void 0 : strategy.name}] - Pour initiate ended called for pour target ${pourTarget == null ? void 0 : pourTarget.id}.`
1328
+ );
1329
+ const ignore = await ((_a = strategy == null ? void 0 : strategy.initiateEnded) == null ? void 0 : _a.call(strategy, pourTarget));
1330
+ if (!ignore) {
1331
+ onPourCancel == null ? void 0 : onPourCancel();
1332
+ }
1333
+ }, [onPourCancel, pourTarget, strategy]);
1334
+ const forceCancelPour = useCallback(async () => {
1335
+ logger$3.debug(`Force cancelling pour for pour target ${pourTarget == null ? void 0 : pourTarget.id}.`);
1336
+ await (pourTarget == null ? void 0 : pourTarget.cancelPour());
1337
+ onPourCancel == null ? void 0 : onPourCancel();
1338
+ }, [onPourCancel, pourTarget]);
1339
+ const handleUpdateContext = useCallback(
1340
+ (key, value) => {
1341
+ context.set(key, value);
1342
+ },
1343
+ [context]
1344
+ );
1345
+ const handleRemoveFromContext = useCallback(
1346
+ (key) => {
1347
+ context.remove(key);
1348
+ },
1349
+ [context]
1350
+ );
1351
+ const handlers = usePressGesture({
1352
+ onPressed: handlePour,
1353
+ onRelease: handleCancelPour
1354
+ });
1355
+ return {
1356
+ handlers: handlers.dom,
1357
+ cancel: forceCancelPour,
1358
+ updatePourContext: handleUpdateContext,
1359
+ removeFromPourContext: handleRemoveFromContext,
1360
+ status: pourTarget
1361
+ };
1362
+ };
1363
+ const logger$2 = KosLog.createLogger({
1364
+ name: "TapOrHoldIntentStrategy",
1365
+ group: "kos-hooks"
1366
+ });
1367
+ class TapOrHoldIntentStrategy {
1368
+ constructor(intent) {
1369
+ __publicField(this, "intent");
1370
+ __publicField(this, "name", "TapOrHoldIntentStrategy");
1371
+ __publicField(this, "isHold", false);
1372
+ __publicField(this, "disposer", null);
1373
+ this.intent = intent;
1374
+ }
1375
+ async initiate(model, intent) {
1376
+ this.disposer = setTimeout(() => {
1377
+ this.isHold = true;
1378
+ }, 250);
1379
+ if ((model == null ? void 0 : model.isPouring) && !this.isHold) {
1380
+ logger$2.debug(`additional tap detected. cancelling pour`);
1381
+ await model.cancelPour();
1382
+ return;
1383
+ }
1384
+ if (!(model == null ? void 0 : model.canPour)) {
1385
+ logger$2.debug(`${model == null ? void 0 : model.id} cannot pour. Returning early.`);
1386
+ return;
1387
+ }
1388
+ if (intent) {
1389
+ logger$2.debug(`performing intent: ${intent}`);
1390
+ await (model == null ? void 0 : model.performIntent(intent));
1391
+ } else {
1392
+ logger$2.debug("no intent provided. Returning early.");
1393
+ }
1394
+ }
1395
+ async initiateEnded(nozzle) {
1396
+ if (this.disposer)
1397
+ clearTimeout(this.disposer);
1398
+ this.disposer = null;
1399
+ if (!this.isHold) {
1400
+ logger$2.debug("Tap detected. don't cancel and return.");
1401
+ return true;
1402
+ }
1403
+ await (nozzle == null ? void 0 : nozzle.cancelPour());
1404
+ return false;
1405
+ }
1406
+ }
1407
+ const logger$1 = KosLog.createLogger({
1408
+ name: "TapToPourIntentStrategy",
1409
+ group: "kos-hooks"
1410
+ });
1411
+ const TapToPourIntentStrategy = {
1412
+ name: "TapToPourIntentStrategy",
1413
+ async initiate(model, intent) {
1414
+ if (model == null ? void 0 : model.isPouring) {
1415
+ logger$1.debug(`Nozzle ${model == null ? void 0 : model.id} is already pouring. cancelling pour`);
1416
+ await model.cancelPour();
1417
+ return;
1418
+ }
1419
+ if (!(model == null ? void 0 : model.canPour)) {
1420
+ logger$1.debug(`Nozzle ${model == null ? void 0 : model.id} cannot pour. Returning early.`);
1421
+ return;
1422
+ }
1423
+ if (intent) {
1424
+ logger$1.debug(`performing intent: ${intent}`);
1425
+ await (model == null ? void 0 : model.performIntent(intent));
1426
+ } else {
1427
+ logger$1.debug("no intent provided. Returning early.");
1428
+ }
1429
+ },
1430
+ async initiateEnded(_nozzle) {
1431
+ return true;
1432
+ }
1433
+ };
1434
+ const logger = KosLog.createLogger({
1435
+ name: "HoldToPourStrategy",
1436
+ group: "kos-hooks"
1437
+ });
1438
+ const TapToPourStrategy = {
1439
+ name: "TapToPourStrategy",
1440
+ async initiate(nozzle) {
1441
+ if (nozzle == null ? void 0 : nozzle.isPouring) {
1442
+ logger.debug(`Nozzle ${nozzle == null ? void 0 : nozzle.id} is already pouring. cancelling pour`);
1443
+ await nozzle.cancelPour();
1444
+ return;
1445
+ }
1446
+ if (!(nozzle == null ? void 0 : nozzle.canPour)) {
1447
+ logger.debug(`Nozzle ${nozzle == null ? void 0 : nozzle.id} cannot pour. Returning early.`);
1448
+ return;
1449
+ }
1450
+ await (nozzle == null ? void 0 : nozzle.pour());
1451
+ },
1452
+ async initiateEnded(_nozzle) {
1453
+ return true;
1454
+ }
1455
+ };
1456
+ const useGenericPour = (id, servicePathFactory, itemId, data) => {
1457
+ const modelId = id;
1458
+ const result = useKosModel({
1459
+ modelId,
1460
+ modelType: GenericPour.type,
1461
+ forceUpdate: true,
1462
+ options: {
1463
+ servicePathFactory,
1464
+ selectedId: itemId,
1465
+ initialData: data
1466
+ }
1467
+ });
1468
+ return result;
1469
+ };
1470
+ function withGenericPour(WrappedComponent) {
1471
+ return (props) => {
1472
+ const { model, status, KosModelLoader } = useGenericPour(
1473
+ props.id,
1474
+ props.servicePathFactory,
1475
+ props.itemId
1476
+ );
1477
+ return /* @__PURE__ */ jsx(KosModelLoader, { ...status, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props, genericPour: model }) });
1478
+ };
1479
+ }
1480
+ const Assembly = createContext(void 0);
1481
+ const AssemblyProvider = ({ children }) => {
1482
+ const { model, ready } = useAssembly();
1483
+ const value = useMemo(() => {
1484
+ if (ready && model) {
1485
+ return { model };
1486
+ }
1487
+ return {};
1488
+ }, [ready, model]);
1489
+ return /* @__PURE__ */ jsx(Assembly.Provider, { value, children });
1490
+ };
1491
+ const useAssemblyContext = () => {
1492
+ const context = useContext(
1493
+ Assembly
1494
+ );
1495
+ if (!context) {
1496
+ throw new Error(
1497
+ "useAssemblyContext must be used within a AssemblyProvider"
1498
+ );
1499
+ }
1500
+ return context;
1501
+ };
1502
+ const Availability = createContext(void 0);
1503
+ const AvailabilityProvider = ({ children }) => {
1504
+ const { model, ready } = useAvailability();
1505
+ const value = useMemo(() => {
1506
+ if (ready && model) {
1507
+ return { model };
1508
+ }
1509
+ return {};
1510
+ }, [ready, model]);
1511
+ return /* @__PURE__ */ jsx(Availability.Provider, { value, children });
1512
+ };
1513
+ const useAvailabilityContext = () => {
1514
+ const context = useContext(Availability);
1515
+ if (!context) {
1516
+ throw new Error(
1517
+ "useAvailabilityContext must be used within a AvailabilityProvider"
1518
+ );
1519
+ }
1520
+ return context;
1521
+ };
1522
+ const Board = createContext(void 0);
1523
+ const BoardProvider = ({ children, id }) => {
1524
+ const { model, ready } = useBoard(id);
1525
+ const value = useMemo(() => {
1526
+ if (ready && model) {
1527
+ return { model };
1528
+ }
1529
+ return {};
1530
+ }, [ready, model]);
1531
+ return /* @__PURE__ */ jsx(Board.Provider, { value, children });
1532
+ };
1533
+ const useBoardContext = () => {
1534
+ const context = useContext(Board);
1535
+ if (!context) {
1536
+ throw new Error("useBoardContext must be used within a BoardProvider");
1537
+ }
1538
+ return context;
1539
+ };
1540
+ const BoardContainer = createContext(void 0);
1541
+ const BoardContainerProvider = ({ children }) => {
1542
+ const { model, ready } = useBoardContainer();
1543
+ const value = useMemo(() => {
1544
+ if (ready && model) {
1545
+ return { model };
1546
+ }
1547
+ return {};
1548
+ }, [ready, model]);
1549
+ return /* @__PURE__ */ jsx(BoardContainer.Provider, { value, children });
1550
+ };
1551
+ const useBoardContainerContext = () => {
1552
+ const context = useContext(BoardContainer);
1553
+ if (!context) {
1554
+ throw new Error(
1555
+ "useBoardContainerContext must be used within a BoardContainerProvider"
1556
+ );
1557
+ }
1558
+ return context;
1559
+ };
1560
+ const DeviceAssemblyContext = createContext(
1561
+ void 0
1562
+ );
1563
+ const DeviceAssemblyProvider = ({ children }) => {
1564
+ const { model, ready } = useDeviceAssembly();
1565
+ const value = useMemo(() => {
1566
+ if (ready && model) {
1567
+ const nozzlePaths = model.nozzlePaths;
1568
+ return { model, nozzlePaths };
1569
+ }
1570
+ return {};
1571
+ }, [ready, model]);
1572
+ const content = ready && model ? children : null;
1573
+ return /* @__PURE__ */ jsx(DeviceAssemblyContext.Provider, { value, children: content });
1574
+ };
1575
+ const useDeviceAssemblyContext = () => {
1576
+ const context = useContext(DeviceAssemblyContext);
1577
+ if (!context) {
1578
+ throw new Error(
1579
+ "useDeviceAssemblyContext must be used within a DeviceAssemblyProvider"
1580
+ );
1581
+ }
1582
+ return context;
1583
+ };
1584
+ function createDispenseKitContext() {
1585
+ const CuiKitContext = React.createContext(null);
1586
+ const useCuiKitContext = () => {
1587
+ const ctx = useContext(CuiKitContext);
1588
+ if (ctx === void 0) {
1589
+ throw new Error("useDispenseKitContext must be used within a Provider");
1590
+ }
1591
+ return ctx;
1592
+ };
1593
+ return [useCuiKitContext, CuiKitContext.Provider];
1594
+ }
1595
+ function CuiKitWrapper({
1596
+ children,
1597
+ provider: CuiKitProvider,
1598
+ props,
1599
+ nozzleProps
1600
+ }) {
1601
+ const result = useCuiKit(props);
1602
+ return /* @__PURE__ */ jsx(CuiKitProvider, { value: result, children: children(nozzleProps || {}) });
1603
+ }
1604
+ function DispenseView({
1605
+ children,
1606
+ provider,
1607
+ props
1608
+ }) {
1609
+ const { nozzlePaths } = useDeviceAssemblyContext();
1610
+ const totalNozzles = (nozzlePaths == null ? void 0 : nozzlePaths.length) || 0;
1611
+ const nozzles = (nozzlePaths == null ? void 0 : nozzlePaths.map((path, index) => /* @__PURE__ */ jsx(NozzleProvider, { path, children: /* @__PURE__ */ jsx(
1612
+ CuiKitWrapper,
1613
+ {
1614
+ provider,
1615
+ props,
1616
+ nozzleProps: {
1617
+ nozzleIndex: index,
1618
+ nozzlePath: path,
1619
+ totalNozzles,
1620
+ isFirstNozzle: index === 0,
1621
+ isLastNozzle: index === totalNozzles - 1
1622
+ },
1623
+ children
1624
+ }
1625
+ ) }, path))) || [];
1626
+ return nozzles;
1627
+ }
1628
+ function CuiKit({
1629
+ provider,
1630
+ props
1631
+ }) {
1632
+ return ({ children }) => provider ? /* @__PURE__ */ jsx(DeviceAssemblyProvider, { children: /* @__PURE__ */ jsx(
1633
+ DispenseView,
1634
+ {
1635
+ provider,
1636
+ props,
1637
+ children
1638
+ }
1639
+ ) }) : null;
1640
+ }
1641
+ function initializeCuiKit(props) {
1642
+ const [useCuiKitContext, DispenseKitProvider] = createDispenseKitContext();
1643
+ return [
1644
+ useCuiKitContext,
1645
+ CuiKit({ provider: DispenseKitProvider, props })
1646
+ ];
1647
+ }
1648
+ const Holder = createContext(void 0);
1649
+ const HolderProvider = ({ children, id }) => {
1650
+ const { model, ready } = useHolder(id || "");
1651
+ const value = useMemo(() => {
1652
+ if (ready && model) {
1653
+ return { model };
1654
+ }
1655
+ return {};
1656
+ }, [ready, model]);
1657
+ return /* @__PURE__ */ jsx(Holder.Provider, { value, children });
1658
+ };
1659
+ const useHolderContext = () => {
1660
+ const context = useContext(Holder);
1661
+ if (!context) {
1662
+ throw new Error("useHolderContext must be used within a HolderProvider");
1663
+ }
1664
+ return context;
1665
+ };
1666
+ const HolderContainer = createContext(
1667
+ void 0
1668
+ );
1669
+ const HolderContainerProvider = ({ children }) => {
1670
+ const { model, ready } = useHolderContainer();
1671
+ const value = useMemo(() => {
1672
+ if (ready && model) {
1673
+ return { model };
1674
+ }
1675
+ return {};
1676
+ }, [ready, model]);
1677
+ return /* @__PURE__ */ jsx(HolderContainer.Provider, { value, children });
1678
+ };
1679
+ const useHolderContainerContext = () => {
1680
+ const context = useContext(HolderContainer);
1681
+ if (!context) {
1682
+ throw new Error(
1683
+ "useHolderContainerContext must be used within a HolderContainerProvider"
1684
+ );
1685
+ }
1686
+ return context;
1687
+ };
1688
+ const Ingredient = createContext(void 0);
1689
+ const IngredientProvider = ({ children }) => {
1690
+ const { model, ready } = useIngredient();
1691
+ const value = useMemo(() => {
1692
+ if (ready && model) {
1693
+ return { model };
1694
+ }
1695
+ return {};
1696
+ }, [ready, model]);
1697
+ return /* @__PURE__ */ jsx(Ingredient.Provider, { value, children });
1698
+ };
1699
+ const useIngredientContext = () => {
1700
+ const context = useContext(Ingredient);
1701
+ if (!context) {
1702
+ throw new Error(
1703
+ "useIngredientContext must be used within a IngredientProvider"
1704
+ );
1705
+ }
1706
+ return context;
1707
+ };
1708
+ const IngredientContainer = createContext(
1709
+ void 0
1710
+ );
1711
+ const IngredientContainerProvider = ({ children }) => {
1712
+ const { model, ready } = useIngredientContainer();
1713
+ const value = useMemo(() => {
1714
+ if (ready && model) {
1715
+ return { model };
1716
+ }
1717
+ return {};
1718
+ }, [ready, model]);
1719
+ return /* @__PURE__ */ jsx(IngredientContainer.Provider, { value, children });
1720
+ };
1721
+ const useIngredientContainerContext = () => {
1722
+ const context = useContext(IngredientContainer);
1723
+ if (!context) {
1724
+ throw new Error(
1725
+ "useIngredientContainerContext must be used within a IngredientContainerProvider"
1726
+ );
1727
+ }
1728
+ return context;
1729
+ };
1730
+ const usePump = () => {
1731
+ const modelId = Pump$1.type;
1732
+ const result = useKosModel({
1733
+ modelId,
1734
+ modelType: Pump$1.type,
1735
+ options: {}
1736
+ });
1737
+ return result;
1738
+ };
1739
+ const Pump = createContext(void 0);
1740
+ const PumpProvider = ({ children }) => {
1741
+ const { model, ready } = usePump();
1742
+ const value = useMemo(() => {
1743
+ if (ready && model) {
1744
+ return { model };
1745
+ }
1746
+ return {};
1747
+ }, [ready, model]);
1748
+ return /* @__PURE__ */ jsx(Pump.Provider, { value, children });
1749
+ };
1750
+ const usePumpContext = () => {
1751
+ const context = useContext(Pump);
1752
+ if (!context) {
1753
+ throw new Error("usePumpContext must be used within a PumpProvider");
1754
+ }
1755
+ return context;
1756
+ };
1757
+ export {
1758
+ withIngredientContainer as $,
1759
+ AssemblyProvider as A,
1760
+ BoardProvider as B,
1761
+ CuiKitWrapper as C,
1762
+ DeviceAssemblyProvider as D,
1763
+ useBrands as E,
1764
+ DISPENSE_GROUP_BRAND as F,
1765
+ DISPENSE_GROUP_BEVERAGE as G,
1766
+ HolderProvider as H,
1767
+ IngredientProvider as I,
1768
+ DISPENSE_GROUP_FLAVOR as J,
1769
+ useCuiKit as K,
1770
+ useDefaultCuiKitLifecycle as L,
1771
+ useDispenseLifecycle as M,
1772
+ NozzleProvider as N,
1773
+ useCuiKitTimers as O,
1774
+ PumpProvider as P,
1775
+ useFlavors as Q,
1776
+ useDeviceAssembly as R,
1777
+ withDeviceAssembly as S,
1778
+ useHolder as T,
1779
+ withHolder as U,
1780
+ useHolderContainer as V,
1781
+ withHolderContainer as W,
1782
+ useIngredient as X,
1783
+ useIngredientPour as Y,
1784
+ withIngredient as Z,
1785
+ useIngredientContainer as _,
1786
+ AvailabilityProvider as a,
1787
+ useNozzle as a0,
1788
+ withNozzle as a1,
1789
+ useNozzlePour as a2,
1790
+ usePourTarget as a3,
1791
+ HoldToPourIntentStrategy as a4,
1792
+ HoldToPourStrategy as a5,
1793
+ TapOrHoldIntentStrategy as a6,
1794
+ TapToPourIntentStrategy as a7,
1795
+ TapToPourStrategy as a8,
1796
+ useGenericPour as a9,
1797
+ withGenericPour as aa,
1798
+ PourContext as ab,
1799
+ useAvailabilityContext as b,
1800
+ useBoardContext as c,
1801
+ BoardContainerProvider as d,
1802
+ useBoardContainerContext as e,
1803
+ CuiKit as f,
1804
+ useDeviceAssemblyContext as g,
1805
+ useHolderContext as h,
1806
+ initializeCuiKit as i,
1807
+ HolderContainerProvider as j,
1808
+ useHolderContainerContext as k,
1809
+ useIngredientContext as l,
1810
+ IngredientContainerProvider as m,
1811
+ useIngredientContainerContext as n,
1812
+ useNozzleContext as o,
1813
+ usePumpContext as p,
1814
+ useAssembly as q,
1815
+ useAvailability as r,
1816
+ withBeverage as s,
1817
+ useBoard as t,
1818
+ useAssemblyContext as u,
1819
+ withBoard as v,
1820
+ withAssembly as w,
1821
+ useBoardContainer as x,
1822
+ withBoardContainer as y,
1823
+ useBeverages as z
1824
+ };
1825
+ //# sourceMappingURL=pump-provider-BSEusYig.js.map