ublo-lib 1.50.2 → 1.50.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../src/future/components/msem-package/components/config.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,KAAK,KAAK,MAAM,UAAU,CAAC;AAIvC,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC/D,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,2CA+EpE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../src/future/components/msem-package/components/config.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,KAAK,KAAK,MAAM,UAAU,CAAC;AAIvC,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC/D,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,2CA0FpE"}
@@ -4,10 +4,9 @@ import { useMsemRuntime } from "../context";
4
4
  import styles from "./config.module.css";
5
5
  export default function Config({ idPrefix, config, setConfig }) {
6
6
  const ref = React.useRef(null);
7
- const { menuPath, lang, path, Zone, cmsMode } = useMsemRuntime();
7
+ const { menuPath, lang, path, Zone } = useMsemRuntime();
8
8
  const initializedRef = React.useRef(false);
9
9
  const prevRouteRef = React.useRef(`/${lang}${path}`);
10
- const prevModeRef = React.useRef(cmsMode);
11
10
  const originalConfigRef = React.useRef(null);
12
11
  const parseZone = React.useCallback(() => {
13
12
  const container = ref.current;
@@ -45,15 +44,19 @@ export default function Config({ idPrefix, config, setConfig }) {
45
44
  }
46
45
  }, [lang, path, parseZone, setConfig]);
47
46
  React.useEffect(() => {
48
- const prev = prevModeRef.current;
49
- prevModeRef.current = cmsMode;
50
- if (prev === "editing" && cmsMode && cmsMode !== "editing") {
47
+ const reloadIfChanged = () => {
51
48
  const original = originalConfigRef.current;
52
49
  const changed = !original || JSON.stringify(config) !== JSON.stringify(original);
53
50
  if (changed)
54
51
  window.location.reload();
55
- }
56
- }, [cmsMode, config]);
52
+ };
53
+ document.addEventListener("ublo-content-saved", reloadIfChanged);
54
+ document.addEventListener("ublo-content-discarded", reloadIfChanged);
55
+ return () => {
56
+ document.removeEventListener("ublo-content-saved", reloadIfChanged);
57
+ document.removeEventListener("ublo-content-discarded", reloadIfChanged);
58
+ };
59
+ }, [config]);
57
60
  React.useEffect(() => {
58
61
  const container = ref.current;
59
62
  if (initializedRef.current && container) {
@@ -1 +1 @@
1
- {"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../../../../../src/future/components/msem-package/components/widget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,KAAK,KAAK,MAAM,UAAU,CAAC;AAIvC,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACnE,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAuBF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,GAAG,EACH,MAAM,EACN,cAAc,EACd,iBAAiB,EACjB,SAAS,GACV,EAAE,KAAK,2CAkQP"}
1
+ {"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../../../../../src/future/components/msem-package/components/widget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,KAAK,KAAK,MAAM,UAAU,CAAC;AAIvC,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACnE,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAuBF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,GAAG,EACH,MAAM,EACN,cAAc,EACd,iBAAiB,EACjB,SAAS,GACV,EAAE,KAAK,2CAqQP"}
@@ -54,6 +54,15 @@ export default function Widget({ index, config, widget, step, setStep, stay, pax
54
54
  needsStay ||
55
55
  needsPax ||
56
56
  (optional ? otherStepOpen : !completedSteps.includes(index - 1));
57
+ React.useEffect(() => {
58
+ if (!isStarted)
59
+ return;
60
+ window.requestAnimationFrame(() => {
61
+ ref.current
62
+ ?.closest("[data-msem-reserve]")
63
+ ?.scrollIntoView({ behavior: "smooth", block: "start" });
64
+ });
65
+ }, [isStarted, count]);
57
66
  const startWidget = (force) => {
58
67
  if (!force && (isDisabled || isStarted || done))
59
68
  return;
@@ -61,12 +70,6 @@ export default function Widget({ index, config, widget, step, setStep, stay, pax
61
70
  setOptionalRepeat(optionalRepeat + 1);
62
71
  }
63
72
  setStep(id);
64
- const container = ref.current;
65
- if (container) {
66
- setTimeout(() => {
67
- container.scrollIntoView({ behavior: "smooth" });
68
- }, 600);
69
- }
70
73
  };
71
74
  const addPerson = (e) => {
72
75
  e.stopPropagation();
@@ -80,8 +83,6 @@ export default function Widget({ index, config, widget, step, setStep, stay, pax
80
83
  setStep(null);
81
84
  };
82
85
  const handleCartChange = () => {
83
- if (widgetContainerRef.current)
84
- widgetContainerRef.current.scrollIntoView();
85
86
  if (!repeatable) {
86
87
  setAddedToCart(true);
87
88
  setCompletedSteps([...completedSteps, index]);
@@ -1 +1 @@
1
- {"version":3,"file":"widgets.d.ts","sourceRoot":"","sources":["../../../../../src/future/components/msem-package/components/widgets.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,KAAK,KAAK,MAAM,UAAU,CAAC;AAKvC,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAC9B,OAAO,EACP,MAAM,EACN,IAAI,EACJ,GAAG,EACH,SAAS,GACV,EAAE,KAAK,2CAgJP"}
1
+ {"version":3,"file":"widgets.d.ts","sourceRoot":"","sources":["../../../../../src/future/components/msem-package/components/widgets.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,KAAK,KAAK,MAAM,UAAU,CAAC;AAKvC,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAC9B,OAAO,EACP,MAAM,EACN,IAAI,EACJ,GAAG,EACH,SAAS,GACV,EAAE,KAAK,2CAmKP"}
@@ -9,7 +9,7 @@ import T from "../i18n/translations";
9
9
  import * as Api from "../utils/api";
10
10
  import styles from "./widgets.module.css";
11
11
  export default function Widgets({ cartUrl, config, stay, pax, validated, }) {
12
- const { lang, langPrefixLinks: hasLangPrefix, esfplusUrl } = useMsemRuntime();
12
+ const { esfplusUrl } = useMsemRuntime();
13
13
  const { widgets, optionalWidgets, id } = config;
14
14
  const [step, setStep] = React.useState(null);
15
15
  const [completedSteps, setCompletedSteps] = React.useState([-1]);
@@ -19,8 +19,18 @@ export default function Widgets({ cartUrl, config, stay, pax, validated, }) {
19
19
  const packageUUID = React.useMemo(() => {
20
20
  return new Date().getTime().toString(36);
21
21
  }, [flowKey]);
22
+ const rootRef = React.useRef(null);
22
23
  const packageId = `${id}-${packageUUID}`;
23
24
  const packageUncompleted = completedSteps.length - 1 !== widgets?.length;
25
+ React.useEffect(() => {
26
+ if (!packageUncompleted && step === null) {
27
+ window.requestAnimationFrame(() => {
28
+ rootRef.current
29
+ ?.closest("[data-msem-reserve]")
30
+ ?.scrollIntoView({ behavior: "smooth", block: "start" });
31
+ });
32
+ }
33
+ }, [packageUncompleted, step]);
24
34
  const currentPackageInfo = React.useRef(null);
25
35
  React.useEffect(() => {
26
36
  currentPackageInfo.current = { packageId, uncompleted: packageUncompleted };
@@ -55,18 +65,24 @@ export default function Widgets({ cartUrl, config, stay, pax, validated, }) {
55
65
  setCompletedOptionalSteps([-1]);
56
66
  setFlowKey((k) => k + 1);
57
67
  }
68
+ else if (!prev && validated && widgets?.length) {
69
+ const datedPack = config.stay?.dated ?? Boolean(config.stay?.from || config.stay?.to);
70
+ const requiresChoice = (datedPack && !config.stay?.forced) ||
71
+ (config.pax?.mode === "range" && !config.pax?.hidden);
72
+ if (requiresChoice)
73
+ setStep(widgets[0].id);
74
+ }
58
75
  }, [validated]);
59
76
  if (!widgets?.length)
60
77
  return null;
61
78
  const submit = () => {
62
- const prefix = hasLangPrefix ? `/${lang}` : "";
63
- window.location.href = `${prefix}${cartUrl}`;
79
+ window.location.href = cartUrl;
64
80
  };
65
81
  const dated = config.stay?.dated ?? Boolean(config.stay?.from || config.stay?.to);
66
82
  const paxRangeVisible = config.pax?.mode === "range" && !config.pax?.hidden;
67
83
  const missingStay = dated && (!stay?.from || !stay?.to);
68
84
  const missingPax = paxRangeVisible && pax == null;
69
- return (_jsxs("div", { className: styles.widgets, children: [validated && missingStay && (_jsx(Information, { type: "warning", className: styles.warning, children: _jsx(T, { id: "widgets.missing-stay" }) })), validated && !missingStay && missingPax && (_jsx(Information, { type: "warning", className: styles.warning, children: _jsx(T, { id: "widgets.missing-pax" }) })), widgets.map((widget, i) => {
85
+ return (_jsxs("div", { ref: rootRef, className: styles.widgets, children: [validated && missingStay && (_jsx(Information, { type: "warning", className: styles.warning, children: _jsx(T, { id: "widgets.missing-stay" }) })), validated && !missingStay && missingPax && (_jsx(Information, { type: "warning", className: styles.warning, children: _jsx(T, { id: "widgets.missing-pax" }) })), widgets.map((widget, i) => {
70
86
  return (_jsx(Widget, { index: i, config: config, widget: widget, step: step, setStep: setStep, stay: stay, pax: pax, locked: !validated, completedSteps: completedSteps, setCompletedSteps: setCompletedSteps, packageId: packageId }, `${flowKey}-${widget.id}`));
71
87
  }), optionalWidgets?.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.title, children: _jsx(T, { id: "widgets.options" }) }), optionalWidgets.map((widget, i) => (_jsx(Widget, { index: i, config: config, widget: widget, stay: stay, pax: pax, locked: !validated || packageUncompleted, step: optionalStep, setStep: setOptionalStep, completedSteps: completedOptionalSteps, setCompletedSteps: setCompletedOptionalSteps, packageId: packageId }, `${flowKey}-${widget.id}`)))] })), !packageUncompleted && (_jsx("div", { className: styles.buttons, children: _jsxs(Button, { className: styles.submit, onClick: submit, children: [_jsx(Icons.ShoppingCart, {}), _jsx(T, { id: "widgets.submit" })] }) }))] }));
72
88
  }
@@ -6,7 +6,6 @@ export type MsemRuntime = {
6
6
  menuPath?: {
7
7
  id?: number | string;
8
8
  } | null;
9
- langPrefixLinks: boolean;
10
9
  esfplusUrl: string;
11
10
  Zone: React.ComponentType<any>;
12
11
  DatePicker: React.ComponentType<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/future/components/msem-package/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3C,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC/B,UAAU,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;CACnD,CAAC;AAGF,eAAO,MAAM,mBAAmB,6BAA8B,CAAC;AAE/D,wBAAgB,cAAc,IAAI,WAAW,CAI5C"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/future/components/msem-package/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC/B,UAAU,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;CACnD,CAAC;AAGF,eAAO,MAAM,mBAAmB,6BAA8B,CAAC;AAE/D,wBAAgB,cAAc,IAAI,WAAW,CAK5C"}
@@ -24,5 +24,5 @@ export default function MseMPackage({ idPrefix, editorOptions, cartUrl, runtime,
24
24
  if (configLoaded && !requiresChoice)
25
25
  setValidated(true);
26
26
  }, [configLoaded, requiresChoice]);
27
- return (_jsx(MsemRuntimeProvider, { value: runtime, children: _jsxs("div", { className: styles.container, children: [_jsx(Config, { idPrefix: idPrefix, config: config, setConfig: setConfig }), isEditing && (_jsxs("div", { className: styles.editor, children: [_jsx("h2", { className: styles.editorTitle, children: "Param\u00E9trage du pack" }), _jsx(GlobalSettings, { config: config, setConfig: setConfig }), _jsx(StaySettings, { config: config, setConfig: setConfig }), _jsx(PaxSettings, { config: config, setConfig: setConfig }), _jsx(WidgetsSettings, { config: config, setConfig: setConfig, editorOptions: editorOptions })] })), !isEditing && (_jsxs("div", { className: styles.reserve, children: [_jsx(Filters, { config: config, stay: stay, setStay: setStay, pax: pax, setPax: setPax, validated: validated, setValidated: setValidated }), _jsx(Widgets, { cartUrl: cartUrl, config: config, stay: stay, pax: pax, validated: validated })] }))] }) }));
27
+ return (_jsx(MsemRuntimeProvider, { value: runtime, children: _jsxs("div", { className: styles.container, children: [_jsx(Config, { idPrefix: idPrefix, config: config, setConfig: setConfig }), isEditing && (_jsxs("div", { className: styles.editor, children: [_jsx("h2", { className: styles.editorTitle, children: "Param\u00E9trage du pack" }), _jsx(GlobalSettings, { config: config, setConfig: setConfig }), _jsx(StaySettings, { config: config, setConfig: setConfig }), _jsx(PaxSettings, { config: config, setConfig: setConfig }), _jsx(WidgetsSettings, { config: config, setConfig: setConfig, editorOptions: editorOptions })] })), !isEditing && (_jsxs("div", { className: styles.reserve, "data-msem-reserve": true, children: [_jsx(Filters, { config: config, stay: stay, setStay: setStay, pax: pax, setPax: setPax, validated: validated, setValidated: setValidated }), _jsx(Widgets, { cartUrl: cartUrl, config: config, stay: stay, pax: pax, validated: validated })] }))] }) }));
28
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/future/components/msem-package/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,KAAK,KAAK,MAAM,SAAS,CAAC;AAEtC,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,cAAc,WAAW,CAAC;AAE1B,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,KAAK,EAAE,KAAK,2CAe/C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/future/components/msem-package/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,KAAK,KAAK,MAAM,SAAS,CAAC;AAEtC,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,cAAc,WAAW,CAAC;AAE1B,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,KAAK,EAAE,KAAK,2CAc/C"}
@@ -9,14 +9,13 @@ export * from "./types";
9
9
  export { default as Core } from "./core";
10
10
  export * from "./context";
11
11
  export default function MseMPackage(props) {
12
- const { cmsMode, lang, path, menuPath, config } = useUbloContext();
12
+ const { cmsMode, lang, path, menuPath } = useUbloContext();
13
13
  const { publicRuntimeConfig } = getConfig();
14
14
  const runtime = {
15
15
  cmsMode,
16
16
  lang,
17
17
  path,
18
18
  menuPath,
19
- langPrefixLinks: config.langPrefix.links,
20
19
  esfplusUrl: publicRuntimeConfig.esfplusUrl,
21
20
  Zone,
22
21
  DatePicker,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ublo-lib",
3
- "version": "1.50.2",
3
+ "version": "1.50.4",
4
4
  "peerDependencies": {
5
5
  "classnames": "^2.5.1",
6
6
  "dt-design-system": "^3.12.0",