@escapenavigator/hooks 1.10.101 → 1.10.104
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.
- package/dist/index.d.ts +3 -2
- package/dist/index.js +17 -41
- package/dist/players-and-variation-picker/index.d.ts +94 -0
- package/dist/players-and-variation-picker/index.js +164 -0
- package/dist/use-localstore-state/index.d.ts +2 -0
- package/dist/use-localstore-state/index.js +55 -0
- package/dist/use-players-and-variation-picker/index.d.ts +92 -0
- package/dist/use-players-and-variation-picker/index.js +169 -0
- package/dist/use-players-and-variation-picker/types.d.ts +85 -0
- package/dist/use-players-and-variation-picker/types.js +9 -0
- package/package.json +10 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
1
|
+
export * from './use-localstore-state';
|
|
2
|
+
export * from './use-players-and-variation-picker';
|
|
3
|
+
export * from './players-and-variation-picker';
|
package/dist/index.js
CHANGED
|
@@ -1,43 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const [value, setValue] = (0, react_1.useState)(() => {
|
|
7
|
-
if (typeof window === 'undefined') {
|
|
8
|
-
return defaultValue;
|
|
9
|
-
}
|
|
10
|
-
try {
|
|
11
|
-
const prev = localStorage.getItem(token);
|
|
12
|
-
if (prev != null) {
|
|
13
|
-
return JSON.parse(prev);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
catch (_a) {
|
|
17
|
-
localStorage.removeItem(token);
|
|
18
|
-
}
|
|
19
|
-
return defaultValue;
|
|
20
|
-
});
|
|
21
|
-
const setStoredValue = (0, react_1.useCallback)((update) => {
|
|
22
|
-
setValue((prev) => {
|
|
23
|
-
const next = typeof update === 'function'
|
|
24
|
-
? update(prev)
|
|
25
|
-
: update;
|
|
26
|
-
if (typeof window === 'undefined') {
|
|
27
|
-
return next;
|
|
28
|
-
}
|
|
29
|
-
if (next === prev) {
|
|
30
|
-
return prev;
|
|
31
|
-
}
|
|
32
|
-
if (next) {
|
|
33
|
-
localStorage.setItem(token, JSON.stringify(next));
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
localStorage.removeItem(token);
|
|
37
|
-
}
|
|
38
|
-
return next;
|
|
39
|
-
});
|
|
40
|
-
}, [token]);
|
|
41
|
-
return [value, setStoredValue];
|
|
42
|
-
}
|
|
43
|
-
exports.useLocalstoreState = useLocalstoreState;
|
|
17
|
+
__exportStar(require("./use-localstore-state"), exports);
|
|
18
|
+
__exportStar(require("./use-players-and-variation-picker"), exports);
|
|
19
|
+
__exportStar(require("./players-and-variation-picker"), exports);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ProfileCurrencyEnum } from '@escapenavigator/types/dist/profile/enum/profile-currency';
|
|
3
|
+
import { usePlayersAndVariationPicker } from '../use-players-and-variation-picker';
|
|
4
|
+
import { PickerSlotDetails, PickerSlotInfo, PickerSlotVariation, PickerVariationChange } from '../use-players-and-variation-picker/types';
|
|
5
|
+
type LoadSlotDetailsApi = Parameters<typeof usePlayersAndVariationPicker>[0]['loadSlotDetails'];
|
|
6
|
+
export type PlayersAndVariationPickerProps = {
|
|
7
|
+
/**
|
|
8
|
+
* Minimal slot identity used to fetch enriched details. Pass
|
|
9
|
+
* `null`/`undefined` to disable the variation row entirely.
|
|
10
|
+
*/
|
|
11
|
+
slot: PickerSlotInfo | null | undefined;
|
|
12
|
+
/** Currently selected tariff id (typically `order.slot.tariffId`). */
|
|
13
|
+
currentTariffId?: number;
|
|
14
|
+
/** Currently selected duration in minutes (flex slots only). */
|
|
15
|
+
currentDuration?: number;
|
|
16
|
+
/** Slot details api method (`slots.slotDetails` or `openapiWidget.slotDetails`). */
|
|
17
|
+
loadSlotDetails: LoadSlotDetailsApi;
|
|
18
|
+
/**
|
|
19
|
+
* Called when the user picks a different variation. Receives the
|
|
20
|
+
* coordinate-based change payload that can be forwarded to the backend
|
|
21
|
+
* without a local cache lookup.
|
|
22
|
+
*/
|
|
23
|
+
onVariationChange?: (change: PickerVariationChange) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Notifies the host whenever the embedded picker resolves the currently
|
|
26
|
+
* highlighted variation (initial load or user click). Useful when the
|
|
27
|
+
* host needs the variation's tariff/duration outside of the picker UI
|
|
28
|
+
* (e.g. to render a price list or seed Formik initial values).
|
|
29
|
+
*/
|
|
30
|
+
onVariationResolved?: (variation: PickerSlotVariation | undefined) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Notifies the host once `/slots/details` resolves. Exposes the slot
|
|
33
|
+
* coordinates and `isFlex` flag so callers can decide whether to send a
|
|
34
|
+
* persisted `slotId` (fix) or rely on coordinate-based booking (flex).
|
|
35
|
+
*/
|
|
36
|
+
onDetailsLoaded?: (details: PickerSlotDetails | null | undefined) => void;
|
|
37
|
+
/** Players form field value. */
|
|
38
|
+
players: number;
|
|
39
|
+
/** Children form field value (defaults to 0). */
|
|
40
|
+
child?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Override for the price map used to render player buttons. Defaults to
|
|
43
|
+
* the selected variation's tariff; pass an explicit value when the host
|
|
44
|
+
* already maintains its own tariff state (e.g. legacy flows).
|
|
45
|
+
*/
|
|
46
|
+
tariff?: Record<string, number>;
|
|
47
|
+
currency: ProfileCurrencyEnum;
|
|
48
|
+
/** Minimum players for save validation. */
|
|
49
|
+
minPlayers?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Capacity cap (questroom max, ticket-system `numSeatsAvailable`, etc.).
|
|
52
|
+
* Player/children buttons exceeding `min(maxFromTariff, maxPlayersLimit)`
|
|
53
|
+
* are filtered out (not just disabled).
|
|
54
|
+
*/
|
|
55
|
+
maxPlayersLimit?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Slot discount in basis points (1% = 100). Applied to the team price
|
|
58
|
+
* shown in the hint, mirroring the widget behaviour.
|
|
59
|
+
*/
|
|
60
|
+
slotDiscount?: number;
|
|
61
|
+
/** External validation error label (controlled by the host form). */
|
|
62
|
+
error?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Translator. Required for the embedded `usePlayersAndVariationPicker`
|
|
65
|
+
* (it composes the default flex duration label).
|
|
66
|
+
*/
|
|
67
|
+
t: (key: string, options?: Record<string, unknown>) => string;
|
|
68
|
+
/** Fires on every player/children change. */
|
|
69
|
+
onChange?: (field: 'players' | 'children', value: number) => void;
|
|
70
|
+
/**
|
|
71
|
+
* When provided, renders a Save button inside the picker. The default
|
|
72
|
+
* `players`/`children` state is buffered locally until the user saves.
|
|
73
|
+
*/
|
|
74
|
+
onSave?: (data: {
|
|
75
|
+
players: number;
|
|
76
|
+
children: number;
|
|
77
|
+
}) => void;
|
|
78
|
+
/**
|
|
79
|
+
* When editing an existing order, pass the order id here so the backend
|
|
80
|
+
* excludes the current booking from occupancy calculations.
|
|
81
|
+
*/
|
|
82
|
+
orderId?: number;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Single shared component that renders the "Variation + Players" picker used
|
|
86
|
+
* by the admin order modals, the widget order flow and the orders package.
|
|
87
|
+
*
|
|
88
|
+
* Rationale: the variation-picker logic lives behind
|
|
89
|
+
* `usePlayersAndVariationPicker`, but the surrounding UI (Tag row, player
|
|
90
|
+
* buttons, kids row, price hint, save button) was reimplemented in three
|
|
91
|
+
* places with subtle drift. This component is the single source of truth.
|
|
92
|
+
*/
|
|
93
|
+
export declare const PlayersAndVariationPicker: React.FC<PlayersAndVariationPickerProps>;
|
|
94
|
+
export {};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.PlayersAndVariationPicker = void 0;
|
|
27
|
+
/* eslint-disable complexity */
|
|
28
|
+
/* eslint-disable no-underscore-dangle */
|
|
29
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
30
|
+
const react_1 = __importStar(require("react"));
|
|
31
|
+
const icons_1 = require("@alphakits/icons");
|
|
32
|
+
const dist_1 = require("@alphakits/ui/dist");
|
|
33
|
+
const format_amount_1 = require("@escapenavigator/utils/dist/format-amount");
|
|
34
|
+
const get_players_price_1 = require("@escapenavigator/utils/dist/get-players-price");
|
|
35
|
+
const get_prices_1 = require("@escapenavigator/utils/dist/get-prices");
|
|
36
|
+
const use_players_and_variation_picker_1 = require("../use-players-and-variation-picker");
|
|
37
|
+
/**
|
|
38
|
+
* Single shared component that renders the "Variation + Players" picker used
|
|
39
|
+
* by the admin order modals, the widget order flow and the orders package.
|
|
40
|
+
*
|
|
41
|
+
* Rationale: the variation-picker logic lives behind
|
|
42
|
+
* `usePlayersAndVariationPicker`, but the surrounding UI (Tag row, player
|
|
43
|
+
* buttons, kids row, price hint, save button) was reimplemented in three
|
|
44
|
+
* places with subtle drift. This component is the single source of truth.
|
|
45
|
+
*/
|
|
46
|
+
const PlayersAndVariationPicker = ({ slot, currentTariffId, currentDuration, loadSlotDetails, onVariationChange, onVariationResolved, onDetailsLoaded, players = 0, child = 0, tariff: tariffOverride, currency, minPlayers, maxPlayersLimit, slotDiscount, error, t, onChange, onSave, orderId, }) => {
|
|
47
|
+
var _a, _b;
|
|
48
|
+
const { loading, options: pickerOptions, selectedOptionId, selectedVariation, buildVariationChange, selectVariation, details, } = (0, use_players_and_variation_picker_1.usePlayersAndVariationPicker)({
|
|
49
|
+
slot,
|
|
50
|
+
currentTariffId,
|
|
51
|
+
currentDuration,
|
|
52
|
+
loadSlotDetails,
|
|
53
|
+
t: t,
|
|
54
|
+
orderId,
|
|
55
|
+
});
|
|
56
|
+
(0, react_1.useEffect)(() => {
|
|
57
|
+
onDetailsLoaded === null || onDetailsLoaded === void 0 ? void 0 : onDetailsLoaded(details);
|
|
58
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
59
|
+
}, [details === null || details === void 0 ? void 0 : details.slotId, details === null || details === void 0 ? void 0 : details.isFlex, (_a = details === null || details === void 0 ? void 0 : details.variations) === null || _a === void 0 ? void 0 : _a.length]);
|
|
60
|
+
const tariff = (0, react_1.useMemo)(() => (tariffOverride || (selectedVariation === null || selectedVariation === void 0 ? void 0 : selectedVariation.tariff) || {}), [tariffOverride, selectedVariation === null || selectedVariation === void 0 ? void 0 : selectedVariation.tariff]);
|
|
61
|
+
(0, react_1.useEffect)(() => {
|
|
62
|
+
onVariationResolved === null || onVariationResolved === void 0 ? void 0 : onVariationResolved(selectedVariation);
|
|
63
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
64
|
+
}, [selectedVariation === null || selectedVariation === void 0 ? void 0 : selectedVariation.id, selectedVariation === null || selectedVariation === void 0 ? void 0 : selectedVariation.tariffId, selectedVariation === null || selectedVariation === void 0 ? void 0 : selectedVariation.duration]);
|
|
65
|
+
const [_players, setPlayers] = (0, react_1.useState)(players);
|
|
66
|
+
const [_children, setChildren] = (0, react_1.useState)(child);
|
|
67
|
+
(0, react_1.useEffect)(() => {
|
|
68
|
+
setPlayers(players);
|
|
69
|
+
}, [players]);
|
|
70
|
+
(0, react_1.useEffect)(() => {
|
|
71
|
+
setChildren(child);
|
|
72
|
+
}, [child]);
|
|
73
|
+
const handleChangePlayers = (value) => {
|
|
74
|
+
setPlayers(value);
|
|
75
|
+
onChange === null || onChange === void 0 ? void 0 : onChange('players', value);
|
|
76
|
+
};
|
|
77
|
+
const handleChangeChildren = (value) => {
|
|
78
|
+
setChildren(value);
|
|
79
|
+
onChange === null || onChange === void 0 ? void 0 : onChange('children', value);
|
|
80
|
+
};
|
|
81
|
+
const playersOptions = (0, react_1.useMemo)(() => Object.entries(tariff)
|
|
82
|
+
.filter(([key]) => key !== 'children' && !Number.isNaN(+key))
|
|
83
|
+
.map(([key, price]) => ({
|
|
84
|
+
key: +key,
|
|
85
|
+
price,
|
|
86
|
+
})), [tariff]);
|
|
87
|
+
const playersArray = (0, get_prices_1.getPricesPlayersArray)(tariff);
|
|
88
|
+
const maxFromTariff = playersArray.length ? +playersArray[playersArray.length - 1] : 0;
|
|
89
|
+
const effectiveMax = typeof maxPlayersLimit === 'number' && Number.isFinite(maxPlayersLimit)
|
|
90
|
+
? Math.min(maxFromTariff, maxPlayersLimit)
|
|
91
|
+
: maxFromTariff;
|
|
92
|
+
const childrenOptions = (0, react_1.useMemo)(() => {
|
|
93
|
+
if (!tariff.child || !maxFromTariff)
|
|
94
|
+
return [];
|
|
95
|
+
const maxChildren = maxFromTariff + 1;
|
|
96
|
+
return Array.from({ length: maxChildren }, (_, i) => i);
|
|
97
|
+
}, [tariff, maxFromTariff]);
|
|
98
|
+
const teamPriceBase = (0, get_players_price_1.getPlayersPrice)({
|
|
99
|
+
players: _players,
|
|
100
|
+
children: _children,
|
|
101
|
+
price: tariff,
|
|
102
|
+
});
|
|
103
|
+
const teamPrice = slotDiscount
|
|
104
|
+
? teamPriceBase - Math.floor((teamPriceBase / 10000) * slotDiscount)
|
|
105
|
+
: teamPriceBase;
|
|
106
|
+
const totalHeads = _players + (_children || 0);
|
|
107
|
+
const personPrice = totalHeads > 0 ? Math.floor(teamPrice / totalHeads) : 0;
|
|
108
|
+
const showVariations = pickerOptions.length > 1;
|
|
109
|
+
const variationDescription = (_b = selectedVariation === null || selectedVariation === void 0 ? void 0 : selectedVariation.description) !== null && _b !== void 0 ? _b : null;
|
|
110
|
+
const handleVariationClick = (optionId, isFree) => {
|
|
111
|
+
if (!isFree)
|
|
112
|
+
return;
|
|
113
|
+
selectVariation(optionId);
|
|
114
|
+
const change = buildVariationChange(optionId);
|
|
115
|
+
if (!change)
|
|
116
|
+
return;
|
|
117
|
+
onVariationChange === null || onVariationChange === void 0 ? void 0 : onVariationChange(change);
|
|
118
|
+
};
|
|
119
|
+
if (loading && !details) {
|
|
120
|
+
return (react_1.default.createElement(dist_1.FlexColumns, { columns: 1, gr: 16 },
|
|
121
|
+
react_1.default.createElement(dist_1.Skeleton, { visible: true, animate: true },
|
|
122
|
+
react_1.default.createElement("div", { style: { height: 80 } })),
|
|
123
|
+
react_1.default.createElement(dist_1.Skeleton, { visible: true, animate: true },
|
|
124
|
+
react_1.default.createElement("div", { style: { height: 60 } }))));
|
|
125
|
+
}
|
|
126
|
+
return (react_1.default.createElement(dist_1.FlexColumns, { columns: 1, gr: 16 },
|
|
127
|
+
showVariations && (react_1.default.createElement(dist_1.FlexColumns, { columns: 1, gr: 8 },
|
|
128
|
+
react_1.default.createElement(dist_1.Typography.Text, { view: "title", color: "secondary" }, t('prices:variation')),
|
|
129
|
+
react_1.default.createElement(dist_1.Flex, { gap: "xs", wrap: true, justify: "start" }, pickerOptions.map((option) => (react_1.default.createElement("div", { key: option.id, style: option.isFree
|
|
130
|
+
? undefined
|
|
131
|
+
: { opacity: 0.4, pointerEvents: 'none' } },
|
|
132
|
+
react_1.default.createElement(dist_1.Tag, { view: selectedOptionId === option.id
|
|
133
|
+
? 'primary-inverted'
|
|
134
|
+
: 'primary', text: option.label, onClick: () => handleVariationClick(option.id, option.isFree) }))))),
|
|
135
|
+
!!variationDescription && (react_1.default.createElement(dist_1.Typography.Text, { view: "caps", color: "secondary" }, variationDescription)))),
|
|
136
|
+
react_1.default.createElement(dist_1.FlexColumns, { columns: 1, gr: 8 },
|
|
137
|
+
react_1.default.createElement(dist_1.Typography.Text, { view: "title", color: "secondary" },
|
|
138
|
+
tariff.child ? t('prices:adults') : t('prices:choosePlayersAmount'),
|
|
139
|
+
' ',
|
|
140
|
+
!!_players && tariff[_players] != null && (`(${(0, format_amount_1.formatAmount)(tariff[_players], currency)})`)),
|
|
141
|
+
react_1.default.createElement(dist_1.Flex, { gap: "xs", wrap: true, justify: "start" }, playersOptions
|
|
142
|
+
.filter((p) => p.key + (_children || 0) <= effectiveMax)
|
|
143
|
+
.map((p) => (react_1.default.createElement(dist_1.Button, { key: `adult-${p.key}`, size: "xs", style: { width: 40, minWidth: 40 }, onClick: () => handleChangePlayers(p.key), view: _players === p.key ? 'primary' : 'outlined' }, p.key))))),
|
|
144
|
+
!!childrenOptions.length && (react_1.default.createElement(dist_1.FlexColumns, { columns: 1, gr: 8 },
|
|
145
|
+
react_1.default.createElement(dist_1.Typography.Text, { view: "title", color: "secondary" },
|
|
146
|
+
t('prices:kids'),
|
|
147
|
+
' ',
|
|
148
|
+
!!_children && tariff.child != null && (`(${(0, format_amount_1.formatAmount)(_children * tariff.child, currency)})`)),
|
|
149
|
+
react_1.default.createElement(dist_1.Flex, { gap: "xs", wrap: true, justify: "start" }, childrenOptions
|
|
150
|
+
.filter((count) => _players + count <= effectiveMax)
|
|
151
|
+
.map((count) => {
|
|
152
|
+
const isActive = _children === count;
|
|
153
|
+
return (react_1.default.createElement(dist_1.Button, { key: `child-${count}`, size: "xs", style: { width: 40, minWidth: 40 }, onClick: () => handleChangeChildren(isActive ? 0 : count), view: isActive ? 'primary' : 'outlined' }, count));
|
|
154
|
+
})))),
|
|
155
|
+
!!totalHeads && (react_1.default.createElement(dist_1.Flex, { justify: "start", gap: "xs" },
|
|
156
|
+
react_1.default.createElement(icons_1.InfoMarkS, { style: { fill: 'var(--color-text-secondary)' } }),
|
|
157
|
+
react_1.default.createElement(dist_1.Typography.Text, { view: "caps", color: "secondary" }, t('prices:totalPriceDescription', {
|
|
158
|
+
teamPrice: (0, format_amount_1.formatAmount)(teamPrice, currency),
|
|
159
|
+
personPrice: (0, format_amount_1.formatAmount)(personPrice, currency),
|
|
160
|
+
})))),
|
|
161
|
+
!!error && (react_1.default.createElement(dist_1.ToastPlate, { view: "negative" }, error || t('prices:playersError', { minPlayers, maxPlayers: effectiveMax }))),
|
|
162
|
+
!!onSave && (react_1.default.createElement(dist_1.Button, { onClick: () => onSave({ players: _players, children: _children }), view: "primary", size: "xs" }, t('common:save')))));
|
|
163
|
+
};
|
|
164
|
+
exports.PlayersAndVariationPicker = PlayersAndVariationPicker;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useLocalstoreState = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
function readFromLocalstore(token, defaultValue) {
|
|
6
|
+
if (typeof window === 'undefined') {
|
|
7
|
+
return defaultValue;
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
const prev = localStorage.getItem(token);
|
|
11
|
+
if (prev != null) {
|
|
12
|
+
return JSON.parse(prev);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
catch (_a) {
|
|
16
|
+
localStorage.removeItem(token);
|
|
17
|
+
}
|
|
18
|
+
return defaultValue;
|
|
19
|
+
}
|
|
20
|
+
function useLocalstoreState(token, defaultValue) {
|
|
21
|
+
// We track defaultValue via ref so token changes don't pull in stale closures
|
|
22
|
+
// while also avoiding extra effect runs when consumers pass an inline default.
|
|
23
|
+
const defaultValueRef = (0, react_1.useRef)(defaultValue);
|
|
24
|
+
defaultValueRef.current = defaultValue;
|
|
25
|
+
const [value, setValue] = (0, react_1.useState)(() => readFromLocalstore(token, defaultValue));
|
|
26
|
+
const prevTokenRef = (0, react_1.useRef)(token);
|
|
27
|
+
(0, react_1.useEffect)(() => {
|
|
28
|
+
if (prevTokenRef.current === token)
|
|
29
|
+
return;
|
|
30
|
+
prevTokenRef.current = token;
|
|
31
|
+
setValue(readFromLocalstore(token, defaultValueRef.current));
|
|
32
|
+
}, [token]);
|
|
33
|
+
const setStoredValue = (0, react_1.useCallback)((update) => {
|
|
34
|
+
setValue((prev) => {
|
|
35
|
+
const next = typeof update === 'function'
|
|
36
|
+
? update(prev)
|
|
37
|
+
: update;
|
|
38
|
+
if (typeof window === 'undefined') {
|
|
39
|
+
return next;
|
|
40
|
+
}
|
|
41
|
+
if (next === prev) {
|
|
42
|
+
return prev;
|
|
43
|
+
}
|
|
44
|
+
if (next) {
|
|
45
|
+
localStorage.setItem(token, JSON.stringify(next));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
localStorage.removeItem(token);
|
|
49
|
+
}
|
|
50
|
+
return next;
|
|
51
|
+
});
|
|
52
|
+
}, [token]);
|
|
53
|
+
return [value, setStoredValue];
|
|
54
|
+
}
|
|
55
|
+
exports.useLocalstoreState = useLocalstoreState;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { PickerOption, PickerSlotDetails, PickerSlotInfo, PickerSlotVariation, PickerVariationChange } from './types';
|
|
2
|
+
export * from './types';
|
|
3
|
+
type LoadSlotDetailsApi = {
|
|
4
|
+
(params: {
|
|
5
|
+
slotId?: number;
|
|
6
|
+
questroomId: number;
|
|
7
|
+
date: string;
|
|
8
|
+
start: string;
|
|
9
|
+
orderId?: number;
|
|
10
|
+
}, transportConfig?: any): Promise<{
|
|
11
|
+
data: PickerSlotDetails;
|
|
12
|
+
}>;
|
|
13
|
+
displayName: string;
|
|
14
|
+
};
|
|
15
|
+
type Params = {
|
|
16
|
+
/**
|
|
17
|
+
* Top-level slot record fetched from the listing. Used to identify the
|
|
18
|
+
* slot for the `/details` request and to seed the booking payload.
|
|
19
|
+
*/
|
|
20
|
+
slot: PickerSlotInfo | null | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Currently selected tariff id (typically `order.slot.tariffId`). Used to
|
|
23
|
+
* highlight the active variation. For flex slots also pass
|
|
24
|
+
* `currentDuration` so the picker can disambiguate between options that
|
|
25
|
+
* share a tariff.
|
|
26
|
+
*/
|
|
27
|
+
currentTariffId?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Currently selected game duration in minutes. Optional, only relevant
|
|
30
|
+
* for flex slots; ignored for fix slots.
|
|
31
|
+
*/
|
|
32
|
+
currentDuration?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Service-layer API method that returns enriched slot details.
|
|
35
|
+
* Pass `slots.slotDetails` (admin) or `openapiWidget.slotDetails` (widget).
|
|
36
|
+
*/
|
|
37
|
+
loadSlotDetails: LoadSlotDetailsApi;
|
|
38
|
+
/**
|
|
39
|
+
* Translator. Only used for the default flex duration label suffix.
|
|
40
|
+
*/
|
|
41
|
+
t: (key: string) => string;
|
|
42
|
+
/**
|
|
43
|
+
* When editing an existing order, pass the order id here so the backend
|
|
44
|
+
* excludes the current booking from occupancy calculations.
|
|
45
|
+
* This prevents the edited order from blocking its own slot/duration.
|
|
46
|
+
*/
|
|
47
|
+
orderId?: number;
|
|
48
|
+
};
|
|
49
|
+
type Result = {
|
|
50
|
+
loading: boolean;
|
|
51
|
+
isFlex: boolean;
|
|
52
|
+
options: PickerOption[];
|
|
53
|
+
selectedVariation: PickerSlotVariation | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Stable id of the highlighted picker option. Use this (and not
|
|
56
|
+
* `tariffId`) when comparing against `option.id` in the UI — flex
|
|
57
|
+
* variations may share a tariff across durations.
|
|
58
|
+
*/
|
|
59
|
+
selectedOptionId: string | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Variation hint text. For fix slots returns the selected non-default
|
|
62
|
+
* variation title; for flex returns null (caller may compose its own
|
|
63
|
+
* duration label from `selectedVariation`).
|
|
64
|
+
*/
|
|
65
|
+
hint: string | null;
|
|
66
|
+
/**
|
|
67
|
+
* Translate a clicked picker option into a coordinate-based booking
|
|
68
|
+
* payload that can be forwarded to the create-order / update-slot
|
|
69
|
+
* endpoints without any local cache lookup.
|
|
70
|
+
*/
|
|
71
|
+
buildVariationChange: (optionId: string) => PickerVariationChange | null;
|
|
72
|
+
/**
|
|
73
|
+
* Force-update the internal selected option (used by the picker UI on
|
|
74
|
+
* click, before the host has had a chance to push back updated
|
|
75
|
+
* `currentTariffId`/`currentDuration` props).
|
|
76
|
+
*/
|
|
77
|
+
selectVariation: (optionId: string) => void;
|
|
78
|
+
details: PickerSlotDetails | null | undefined;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Single source of truth for the variation picker shared between admin order
|
|
82
|
+
* modals, widget order flow and the orders package.
|
|
83
|
+
*
|
|
84
|
+
* Internally fetches `/slots/details` via the supplied api method and exposes
|
|
85
|
+
* a normalised contract over the unified `variations[]` payload:
|
|
86
|
+
* - `options` and `selectedOptionId` for rendering tag/button rows
|
|
87
|
+
* - `selectedVariation` for callers that need the underlying variation
|
|
88
|
+
* (e.g. to compute prices)
|
|
89
|
+
* - `buildVariationChange(id)` for translating a tap to a coordinate-based
|
|
90
|
+
* booking payload `{ questroomId, date, start, tariffId, duration, slotId? }`
|
|
91
|
+
*/
|
|
92
|
+
export declare const usePlayersAndVariationPicker: ({ slot, currentTariffId, currentDuration, loadSlotDetails, t, orderId, }: Params) => Result;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.usePlayersAndVariationPicker = void 0;
|
|
18
|
+
/* eslint-disable no-nested-ternary */
|
|
19
|
+
const react_1 = require("react");
|
|
20
|
+
const use_api_method_1 = require("@escapenavigator/services/dist/hooks/use-api-method");
|
|
21
|
+
__exportStar(require("./types"), exports);
|
|
22
|
+
const variationKey = (variation) => { var _a; return (_a = variation.id) !== null && _a !== void 0 ? _a : `${variation.tariffId}-${variation.duration}`; };
|
|
23
|
+
/**
|
|
24
|
+
* Single source of truth for the variation picker shared between admin order
|
|
25
|
+
* modals, widget order flow and the orders package.
|
|
26
|
+
*
|
|
27
|
+
* Internally fetches `/slots/details` via the supplied api method and exposes
|
|
28
|
+
* a normalised contract over the unified `variations[]` payload:
|
|
29
|
+
* - `options` and `selectedOptionId` for rendering tag/button rows
|
|
30
|
+
* - `selectedVariation` for callers that need the underlying variation
|
|
31
|
+
* (e.g. to compute prices)
|
|
32
|
+
* - `buildVariationChange(id)` for translating a tap to a coordinate-based
|
|
33
|
+
* booking payload `{ questroomId, date, start, tariffId, duration, slotId? }`
|
|
34
|
+
*/
|
|
35
|
+
const usePlayersAndVariationPicker = ({ slot, currentTariffId, currentDuration, loadSlotDetails, t, orderId, }) => {
|
|
36
|
+
const api = (0, use_api_method_1.useApiMethod)({ api: loadSlotDetails });
|
|
37
|
+
const data = api[`${loadSlotDetails.displayName}Data`];
|
|
38
|
+
const loading = !!api[`${loadSlotDetails.displayName}Loading`];
|
|
39
|
+
const fetch = api[`${loadSlotDetails.displayName}Fetch`];
|
|
40
|
+
(0, react_1.useEffect)(() => {
|
|
41
|
+
if (!slot)
|
|
42
|
+
return;
|
|
43
|
+
fetch({
|
|
44
|
+
slotId: slot.id,
|
|
45
|
+
questroomId: slot.questroomId,
|
|
46
|
+
date: slot.date,
|
|
47
|
+
start: slot.start,
|
|
48
|
+
orderId,
|
|
49
|
+
});
|
|
50
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
|
+
}, [slot === null || slot === void 0 ? void 0 : slot.id, slot === null || slot === void 0 ? void 0 : slot.questroomId, slot === null || slot === void 0 ? void 0 : slot.date, slot === null || slot === void 0 ? void 0 : slot.start, orderId]);
|
|
52
|
+
const variations = (0, react_1.useMemo)(() => (data === null || data === void 0 ? void 0 : data.variations) || [], [data === null || data === void 0 ? void 0 : data.variations]);
|
|
53
|
+
const isFlex = !!(data === null || data === void 0 ? void 0 : data.isFlex);
|
|
54
|
+
const findCurrentVariation = (rows) => {
|
|
55
|
+
if (!rows.length)
|
|
56
|
+
return undefined;
|
|
57
|
+
if (isFlex) {
|
|
58
|
+
// Match by (tariffId, duration) when both are known; fall back to
|
|
59
|
+
// duration-only or tariff-only when one is missing.
|
|
60
|
+
if (currentTariffId != null && currentDuration != null) {
|
|
61
|
+
const exact = rows.find((row) => row.tariffId === currentTariffId
|
|
62
|
+
&& row.duration === currentDuration);
|
|
63
|
+
if (exact)
|
|
64
|
+
return exact;
|
|
65
|
+
}
|
|
66
|
+
if (currentDuration != null) {
|
|
67
|
+
const byDuration = rows.find((row) => row.duration === currentDuration);
|
|
68
|
+
if (byDuration)
|
|
69
|
+
return byDuration;
|
|
70
|
+
}
|
|
71
|
+
if (currentTariffId != null) {
|
|
72
|
+
const byTariff = rows.find((row) => row.tariffId === currentTariffId);
|
|
73
|
+
if (byTariff)
|
|
74
|
+
return byTariff;
|
|
75
|
+
}
|
|
76
|
+
return rows.find((row) => row.isDefault) || rows[0];
|
|
77
|
+
}
|
|
78
|
+
if (currentTariffId != null) {
|
|
79
|
+
const byTariff = rows.find((row) => row.tariffId === currentTariffId);
|
|
80
|
+
if (byTariff)
|
|
81
|
+
return byTariff;
|
|
82
|
+
}
|
|
83
|
+
return rows.find((row) => row.isDefault) || rows[0];
|
|
84
|
+
};
|
|
85
|
+
const propsSelectedVariation = (0, react_1.useMemo)(() => findCurrentVariation(variations),
|
|
86
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
|
+
[variations, isFlex, currentTariffId, currentDuration]);
|
|
88
|
+
const propsSelectedOptionId = propsSelectedVariation
|
|
89
|
+
? variationKey(propsSelectedVariation)
|
|
90
|
+
: undefined;
|
|
91
|
+
// Internal click state — lets the picker switch its highlighted option
|
|
92
|
+
// immediately, even if the host doesn't push back updated
|
|
93
|
+
// `currentTariffId`/`currentDuration` props. We re-seed it whenever the
|
|
94
|
+
// prop-derived option changes (initial load, host explicitly changing
|
|
95
|
+
// the order's tariff, etc.).
|
|
96
|
+
const [clickedOptionId, setClickedOptionId] = (0, react_1.useState)(undefined);
|
|
97
|
+
(0, react_1.useEffect)(() => {
|
|
98
|
+
setClickedOptionId(undefined);
|
|
99
|
+
}, [propsSelectedOptionId, data === null || data === void 0 ? void 0 : data.slotId]);
|
|
100
|
+
const selectedOptionId = clickedOptionId !== null && clickedOptionId !== void 0 ? clickedOptionId : propsSelectedOptionId;
|
|
101
|
+
const selectedVariation = (0, react_1.useMemo)(() => {
|
|
102
|
+
var _a;
|
|
103
|
+
return (_a = variations.find((variation) => variationKey(variation) === selectedOptionId)) !== null && _a !== void 0 ? _a : propsSelectedVariation;
|
|
104
|
+
}, [variations, selectedOptionId, propsSelectedVariation]);
|
|
105
|
+
const options = (0, react_1.useMemo)(() => {
|
|
106
|
+
if (variations.length < 2)
|
|
107
|
+
return [];
|
|
108
|
+
return variations.map((variation) => {
|
|
109
|
+
var _a;
|
|
110
|
+
const id = variationKey(variation);
|
|
111
|
+
const isCurrent = id === selectedOptionId;
|
|
112
|
+
const label = isFlex
|
|
113
|
+
? `${variation.duration} ${t('common:минут')}`
|
|
114
|
+
: (variation.isDefault
|
|
115
|
+
? 'Default'
|
|
116
|
+
: variation.title || `Tariff ${variation.tariffId}`);
|
|
117
|
+
return {
|
|
118
|
+
id,
|
|
119
|
+
tariffId: variation.tariffId,
|
|
120
|
+
duration: variation.duration,
|
|
121
|
+
label,
|
|
122
|
+
description: !isFlex ? (_a = variation.description) !== null && _a !== void 0 ? _a : null : null,
|
|
123
|
+
isCurrent,
|
|
124
|
+
isFree: !!variation.isFree,
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
}, [variations, isFlex, selectedOptionId, t]);
|
|
128
|
+
const hint = (0, react_1.useMemo)(() => {
|
|
129
|
+
if (!isFlex && selectedVariation && !selectedVariation.isDefault) {
|
|
130
|
+
return selectedVariation.title || null;
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}, [isFlex, selectedVariation]);
|
|
134
|
+
const buildVariationChange = (optionId) => {
|
|
135
|
+
if (!data)
|
|
136
|
+
return null;
|
|
137
|
+
const variation = variations.find((row) => variationKey(row) === optionId);
|
|
138
|
+
if (!variation)
|
|
139
|
+
return null;
|
|
140
|
+
return {
|
|
141
|
+
questroomId: data.questroomId,
|
|
142
|
+
date: data.date,
|
|
143
|
+
start: data.start,
|
|
144
|
+
slotId: data.slotId,
|
|
145
|
+
tariffId: variation.tariffId,
|
|
146
|
+
duration: variation.duration,
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Update internal click state. Call from the UI before notifying the
|
|
151
|
+
* host so the highlighted Tag updates without round-tripping through
|
|
152
|
+
* controlled props.
|
|
153
|
+
*/
|
|
154
|
+
const selectVariation = (optionId) => {
|
|
155
|
+
setClickedOptionId(optionId);
|
|
156
|
+
};
|
|
157
|
+
return {
|
|
158
|
+
loading,
|
|
159
|
+
isFlex,
|
|
160
|
+
options,
|
|
161
|
+
selectedVariation,
|
|
162
|
+
selectedOptionId,
|
|
163
|
+
hint,
|
|
164
|
+
buildVariationChange,
|
|
165
|
+
selectVariation,
|
|
166
|
+
details: data,
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
exports.usePlayersAndVariationPicker = usePlayersAndVariationPicker;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared shapes used by `usePlayersAndVariationPicker`.
|
|
3
|
+
*
|
|
4
|
+
* They intentionally mirror both admin (`SlotRO`/`SlotEnrichedRO`) and widget
|
|
5
|
+
* (`OpenapiSlotRO`/`OpenapiSlotEnrichedRO`) contracts so a single picker can
|
|
6
|
+
* be plugged into either context.
|
|
7
|
+
*/
|
|
8
|
+
export type PickerSlotVariation = {
|
|
9
|
+
/**
|
|
10
|
+
* Stable picker key returned by the backend (`${tariffId}-${duration}`).
|
|
11
|
+
* Optional only for backwards compatibility while older hosts roll out
|
|
12
|
+
* the new field; once everyone is on the new contract this becomes the
|
|
13
|
+
* authoritative picker option id.
|
|
14
|
+
*/
|
|
15
|
+
id?: string;
|
|
16
|
+
tariffId: number;
|
|
17
|
+
duration: number;
|
|
18
|
+
title: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
isDefault: boolean;
|
|
21
|
+
isFree: boolean;
|
|
22
|
+
tariff: {
|
|
23
|
+
[k: string]: number;
|
|
24
|
+
};
|
|
25
|
+
minPlayers: number;
|
|
26
|
+
maxPlayers: number;
|
|
27
|
+
numSeatsAvailable: number;
|
|
28
|
+
};
|
|
29
|
+
export type PickerSlotDetails = {
|
|
30
|
+
questroomId: number;
|
|
31
|
+
date: string;
|
|
32
|
+
start: string;
|
|
33
|
+
/** Persisted parent slot id; absent for flex slots. */
|
|
34
|
+
slotId?: number;
|
|
35
|
+
isFlex: boolean;
|
|
36
|
+
variations: PickerSlotVariation[];
|
|
37
|
+
numSeatsAvailable: number;
|
|
38
|
+
minPlayers: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Minimal slot identity needed to fetch enriched details. Everything else
|
|
42
|
+
* (tariff, ruleId, discount, ...) lives in the host's order/slot record;
|
|
43
|
+
* the picker reads its own copy from `/slots/details`.
|
|
44
|
+
*/
|
|
45
|
+
export type PickerSlotInfo = {
|
|
46
|
+
id: number;
|
|
47
|
+
questroomId: number;
|
|
48
|
+
date: string;
|
|
49
|
+
start: string;
|
|
50
|
+
};
|
|
51
|
+
export type PickerOption = {
|
|
52
|
+
/**
|
|
53
|
+
* Stable picker option key. Mirrors `PickerSlotVariation.id`
|
|
54
|
+
* (`${tariffId}-${duration}`) so that flex variations sharing a tariff
|
|
55
|
+
* across durations stay distinguishable.
|
|
56
|
+
*/
|
|
57
|
+
id: string;
|
|
58
|
+
tariffId: number;
|
|
59
|
+
duration: number;
|
|
60
|
+
label: string;
|
|
61
|
+
description?: string | null;
|
|
62
|
+
isCurrent: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* True when the variation is currently bookable. Unbookable variations
|
|
65
|
+
* are still rendered (greyed out) so the user sees the full duration
|
|
66
|
+
* list returned by `/slots/details`.
|
|
67
|
+
*/
|
|
68
|
+
isFree: boolean;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Coordinate-based booking payload produced by the picker on user change.
|
|
72
|
+
*
|
|
73
|
+
* Frontend forwards these fields to the backend without any local cache
|
|
74
|
+
* lookup. Backend resolves the actual slot via `(slotId)` for fix slots or
|
|
75
|
+
* via `(questroomId, date, start, duration, tariffId)` for flex slots.
|
|
76
|
+
*/
|
|
77
|
+
export type PickerVariationChange = {
|
|
78
|
+
questroomId: number;
|
|
79
|
+
date: string;
|
|
80
|
+
start: string;
|
|
81
|
+
tariffId: number;
|
|
82
|
+
duration: number;
|
|
83
|
+
/** Persisted parent slot id; only set for fix slots. */
|
|
84
|
+
slotId?: number;
|
|
85
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared shapes used by `usePlayersAndVariationPicker`.
|
|
4
|
+
*
|
|
5
|
+
* They intentionally mirror both admin (`SlotRO`/`SlotEnrichedRO`) and widget
|
|
6
|
+
* (`OpenapiSlotRO`/`OpenapiSlotEnrichedRO`) contracts so a single picker can
|
|
7
|
+
* be plugged into either context.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@escapenavigator/hooks",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.104",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -14,9 +14,16 @@
|
|
|
14
14
|
"test": "jest"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@escapenavigator/
|
|
17
|
+
"@escapenavigator/services": "^1.10.112",
|
|
18
|
+
"@escapenavigator/types": "^1.10.103",
|
|
19
|
+
"@escapenavigator/utils": "^1.10.107",
|
|
18
20
|
"react": "^18.3.1"
|
|
19
21
|
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"@alphakits/icons": "*",
|
|
24
|
+
"@alphakits/ui": "*",
|
|
25
|
+
"react-i18next": "*"
|
|
26
|
+
},
|
|
20
27
|
"devDependencies": {
|
|
21
28
|
"@rollup/plugin-node-resolve": "^13.0.0",
|
|
22
29
|
"@rollup/plugin-replace": "^2.4.2",
|
|
@@ -41,5 +48,5 @@
|
|
|
41
48
|
"react": "^18.3.1",
|
|
42
49
|
"axios": "^0.21.1"
|
|
43
50
|
},
|
|
44
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "0e41f6e541edd14685f9dd242e17207d1b8f6660"
|
|
45
52
|
}
|