UNPKG

laif-ds

Version:

Design System di Laif con componenti React basati su principi di Atomic Design

735 lines (734 loc) 22.8 kB
"use client"; import { createSelector as l } from "../../../../reselect/dist/reselect.js"; import U from "../../../../../_virtual/range.js"; import * as x from "../../../../victory-vendor/es/d3-scale.js"; import { selectChartLayout as h } from "../../context/chartLayoutContext.js"; import { checkDomainOfScale as be, getValueByDataKey as C, isCategoricalAxis as y, getDomainOfStackGroups as De, getStackedData as we } from "../../util/ChartUtils.js"; import { selectChartDataWithIndexesIfNotInPanorama as ke, selectChartDataWithIndexes as xe } from "./dataSelectors.js"; import { isWellFormedNumberDomain as Z, numericalDomainSpecifiedWithoutRequiringData as Ce, parseNumericalUserDomain as Oe } from "../../util/isDomainSpecifiedByUser.js"; import { upperFirst as q, hasDuplicate as J, isNumOrStr as Q, isNan as z, getPercentValue as Ie, mathSign as ee } from "../../util/DataUtils.js"; import { isWellBehavedNumber as F } from "../../util/isWellBehavedNumber.js"; import { selectChartHeight as Ne, selectChartWidth as Pe } from "./containerSelectors.js"; import { selectAllXAxes as re, selectAllYAxes as te } from "./selectAllAxes.js"; import { selectChartOffset as A } from "./selectChartOffset.js"; import { selectBrushDimensions as ne, selectBrushSettings as ie } from "./brushSelectors.js"; import { selectBarCategoryGap as Be, selectStackOffsetType as ae, selectChartName as Ee } from "./rootPropsSelectors.js"; import { selectRadiusAxis as ue, selectAngleAxis as le, selectRadiusAxisRange as Ke, selectAngleAxisRange as Me } from "./polarAxisSelectors.js"; import { pickAxisType as f } from "./pickAxisType.js"; import { pickAxisId as P } from "./pickAxisId.js"; import { combineAxisRangeWithReverse as _e } from "./combiners/combineAxisRangeWithReverse.js"; import { DEFAULT_Y_AXIS_WIDTH as W } from "../../util/Constants.js"; import { getNiceTickValues as Ge, getTickValuesFixedDomain as je } from "../../util/scale/getNiceTickValues.js"; function T(r, e) { var t = Object.keys(r); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(r); e && (n = n.filter(function(i) { return Object.getOwnPropertyDescriptor(r, i).enumerable; })), t.push.apply(t, n); } return t; } function N(r) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e] != null ? arguments[e] : {}; e % 2 ? T(Object(t), !0).forEach(function(n) { Fe(r, n, t[n]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(r, Object.getOwnPropertyDescriptors(t)) : T(Object(t)).forEach(function(n) { Object.defineProperty(r, n, Object.getOwnPropertyDescriptor(t, n)); }); } return r; } function Fe(r, e, t) { return (e = Re(e)) in r ? Object.defineProperty(r, e, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : r[e] = t, r; } function Re(r) { var e = ze(r, "string"); return typeof e == "symbol" ? e : e + ""; } function ze(r, e) { if (typeof r != "object" || !r) return r; var t = r[Symbol.toPrimitive]; if (t !== void 0) { var n = t.call(r, e); if (typeof n != "object") return n; throw new TypeError("@@toPrimitive must return a primitive value."); } return (e === "string" ? String : Number)(r); } var R = [0, "auto"], We = { allowDataOverflow: !1, allowDecimals: !0, allowDuplicatedCategory: !0, angle: 0, dataKey: void 0, domain: void 0, height: 30, hide: !0, id: 0, includeHidden: !1, interval: "preserveEnd", minTickGap: 5, mirror: !1, name: void 0, orientation: "bottom", padding: { left: 0, right: 0 }, reversed: !1, scale: "auto", tick: !0, tickCount: 5, tickFormatter: void 0, ticks: void 0, type: "category", unit: void 0 }, b = (r, e) => { var t = r.cartesianAxis.xAxis[e]; return t ?? We; }, Se = { allowDataOverflow: !1, allowDecimals: !0, allowDuplicatedCategory: !0, angle: 0, dataKey: void 0, domain: R, hide: !0, id: 0, includeHidden: !1, interval: "preserveEnd", minTickGap: 5, mirror: !1, name: void 0, orientation: "left", padding: { top: 0, bottom: 0 }, reversed: !1, scale: "auto", tick: !0, tickCount: 5, tickFormatter: void 0, ticks: void 0, type: "number", unit: void 0, width: W }, D = (r, e) => { var t = r.cartesianAxis.yAxis[e]; return t ?? Se; }, Ve = { domain: [0, "auto"], includeHidden: !1, reversed: !1, allowDataOverflow: !1, allowDuplicatedCategory: !1, dataKey: void 0, id: 0, name: "", range: [64, 64], scale: "auto", type: "number", unit: "" }, S = (r, e) => { var t = r.cartesianAxis.zAxis[e]; return t ?? Ve; }, v = (r, e, t) => { switch (e) { case "xAxis": return b(r, t); case "yAxis": return D(r, t); case "zAxis": return S(r, t); case "angleAxis": return le(r, t); case "radiusAxis": return ue(r, t); default: throw new Error("Unexpected axis type: ".concat(e)); } }, Xe = (r, e, t) => { switch (e) { case "xAxis": return b(r, t); case "yAxis": return D(r, t); default: throw new Error("Unexpected axis type: ".concat(e)); } }, B = (r, e, t) => { switch (e) { case "xAxis": return b(r, t); case "yAxis": return D(r, t); case "angleAxis": return le(r, t); case "radiusAxis": return ue(r, t); default: throw new Error("Unexpected axis type: ".concat(e)); } }, Ye = (r) => r.graphicalItems.countOfBars > 0; function $e(r, e) { return (t) => { switch (r) { case "xAxis": return "xAxisId" in t && t.xAxisId === e; case "yAxis": return "yAxisId" in t && t.yAxisId === e; case "zAxis": return "zAxisId" in t && t.zAxisId === e; case "angleAxis": return "angleAxisId" in t && t.angleAxisId === e; case "radiusAxis": return "radiusAxisId" in t && t.radiusAxisId === e; default: return !1; } }; } var He = (r) => r.graphicalItems.cartesianItems, Le = l([f, P], $e), Te = (r, e, t) => r.filter(t).filter((n) => e?.includeHidden === !0 ? !0 : !n.hide), O = l([He, v, Le], Te), Ue = (r) => r.filter((e) => e.stackId === void 0), Ze = l([O], Ue), qe = (r) => r.map((e) => e.data).filter(Boolean).flat(1), Je = l([O], qe), Qe = (r, e) => { var { chartData: t = [], dataStartIndex: n, dataEndIndex: i } = e; return r.length > 0 ? r : t.slice(n, i + 1); }, E = l([Je, ke], Qe), er = (r, e, t) => e?.dataKey != null ? r.map((n) => ({ value: C(n, e.dataKey) })) : t.length > 0 ? t.map((n) => n.dataKey).flatMap((n) => r.map((i) => ({ value: C(i, n) }))) : r.map((n) => ({ value: n })), K = l([E, v, O], er); function oe(r, e) { switch (r) { case "xAxis": return e.direction === "x"; case "yAxis": return e.direction === "y"; default: return !1; } } function g(r) { return r.filter((e) => Q(e) || e instanceof Date).map(Number).filter((e) => z(e) === !1); } function rr(r, e, t) { return !t || typeof e != "number" || z(e) ? [] : t.length ? g(t.flatMap((n) => { var i = C(r, n.dataKey), a, u; if (Array.isArray(i) ? [a, u] = i : a = u = i, !(!F(a) || !F(u))) return [e - a, e + u]; })) : []; } var tr = (r, e, t) => { var n = {}, i = e.reduce((a, u) => (u.stackId == null || (a[u.stackId] == null && (a[u.stackId] = []), a[u.stackId].push(u)), a), n); return Object.fromEntries(Object.entries(i).map((a) => { var [u, o] = a, d = o.map((c) => c.dataKey); return [u, { // @ts-expect-error getStackedData requires that the input is array of objects, Recharts does not test for that stackedData: we(r, d, t), graphicalItems: o }]; })); }, nr = l([E, O, ae], tr), ir = (r, e, t) => { var { dataStartIndex: n, dataEndIndex: i } = e; if (t !== "zAxis") { var a = De(r, n, i); if (!(a != null && a[0] === 0 && a[1] === 0)) return a; } }, ar = l([nr, xe, f], ir), ur = (r, e, t, n) => t.length > 0 ? r.flatMap((i) => t.flatMap((a) => { var u, o, d = (u = a.errorBars) === null || u === void 0 ? void 0 : u.filter((m) => oe(n, m)), c = C(i, (o = e.dataKey) !== null && o !== void 0 ? o : a.dataKey); return { value: c, errorDomain: rr(i, c, d) }; })).filter(Boolean) : e?.dataKey != null ? r.map((i) => ({ value: C(i, e.dataKey), errorDomain: [] })) : r.map((i) => ({ value: i, errorDomain: [] })), lr = l(E, v, Ze, f, ur); function or(r) { var { value: e } = r; if (Q(e) || e instanceof Date) return e; } var cr = (r) => { var e = r.flatMap((n) => [n.value, n.errorDomain]).flat(1), t = g(e); if (t.length !== 0) return [Math.min(...t), Math.max(...t)]; }, dr = (r, e, t) => { var n = r.map(or).filter((i) => i != null); return t && (e.dataKey == null || e.allowDuplicatedCategory && J(n)) ? U(0, r.length) : e.allowDuplicatedCategory ? n : Array.from(new Set(n)); }, ce = (r) => { var e; if (r == null || !("domain" in r)) return R; if (r.domain != null) return r.domain; if (r.ticks != null) { if (r.type === "number") { var t = g(r.ticks); return [Math.min(...t), Math.max(...t)]; } if (r.type === "category") return r.ticks.map(String); } return (e = r?.domain) !== null && e !== void 0 ? e : R; }, de = function() { for (var e = arguments.length, t = new Array(e), n = 0; n < e; n++) t[n] = arguments[n]; var i = t.filter(Boolean); if (i.length !== 0) { var a = i.flat(), u = Math.min(...a), o = Math.max(...a); return [u, o]; } }, fr = (r) => r.referenceElements.dots, V = (r, e, t) => r.filter((n) => n.ifOverflow === "extendDomain").filter((n) => e === "xAxis" ? n.xAxisId === t : n.yAxisId === t), sr = l([fr, f, P], V), vr = (r) => r.referenceElements.areas, mr = l([vr, f, P], V), pr = (r) => r.referenceElements.lines, hr = l([pr, f, P], V), Ar = (r, e) => { var t = g(r.map((n) => e === "xAxis" ? n.x : n.y)); if (t.length !== 0) return [Math.min(...t), Math.max(...t)]; }, gr = l(sr, f, Ar), yr = (r, e) => { var t = g(r.flatMap((n) => [e === "xAxis" ? n.x1 : n.y1, e === "xAxis" ? n.x2 : n.y2])); if (t.length !== 0) return [Math.min(...t), Math.max(...t)]; }, br = l([mr, f], yr), Dr = (r, e) => { var t = g(r.map((n) => e === "xAxis" ? n.x : n.y)); if (t.length !== 0) return [Math.min(...t), Math.max(...t)]; }, wr = l(hr, f, Dr), kr = l(gr, wr, br, (r, e, t) => de(r, t, e)), xr = l([v], ce), Cr = (r, e, t, n, i) => { var a = Ce(e, r.allowDataOverflow); return a ?? Oe(e, de(t, i, cr(n)), r.allowDataOverflow); }, Or = l([v, xr, ar, lr, kr], Cr), Ir = [0, 1], Nr = (r, e, t, n, i, a, u) => { if (!(r == null || t == null || t.length === 0)) { var { dataKey: o, type: d } = r, c = y(e, a); return c && o == null ? U(0, t.length) : d === "category" ? dr(n, r, c) : i === "expand" ? Ir : u; } }, X = l([v, h, E, K, ae, f, Or], Nr), Pr = (r, e, t, n, i) => { if (r != null) { var { scale: a, type: u } = r; if (a === "auto") return e === "radial" && i === "radiusAxis" ? "band" : e === "radial" && i === "angleAxis" ? "linear" : u === "category" && n && (n.indexOf("LineChart") >= 0 || n.indexOf("AreaChart") >= 0 || n.indexOf("ComposedChart") >= 0 && !t) ? "point" : u === "category" ? "band" : "linear"; if (typeof a == "string") { var o = "scale".concat(q(a)); return o in x ? o : "point"; } } }, I = l([v, h, Ye, Ee, f], Pr); function Br(r) { if (r != null) { if (r in x) return x[r](); var e = "scale".concat(q(r)); if (e in x) return x[e](); } } function fe(r, e, t, n) { if (!(t == null || n == null)) { if (typeof r.scale == "function") return r.scale.copy().domain(t).range(n); var i = Br(e); if (i != null) { var a = i.domain(t).range(n); return be(a), a; } } } var Er = (r, e, t) => { var n = ce(e); if (!(t !== "auto" && t !== "linear")) { if (e != null && e.tickCount && Array.isArray(n) && (n[0] === "auto" || n[1] === "auto") && Z(r)) return Ge(r, e.tickCount, e.allowDecimals); if (e != null && e.tickCount && e.type === "number" && r != null) return je(r, e.tickCount, e.allowDecimals); } }, Y = l([X, B, I], Er), Kr = (r, e, t, n) => { if ( /* * Angle axis for some reason uses nice ticks when rendering axis tick labels, * but doesn't use nice ticks for extending domain like all the other axes do. * Not really sure why? Is there a good reason, * or is it just because someone added support for nice ticks to the other axes and forgot this one? */ n !== "angleAxis" && r?.type === "number" && Z(e) && Array.isArray(t) && t.length > 0 ) { var i = e[0], a = t[0], u = e[1], o = t[t.length - 1]; return [Math.min(i, a), Math.max(u, o)]; } return e; }, Mr = l([v, X, Y, f], Kr), _r = l(K, v, (r, e) => { if (!(!e || e.type !== "number")) { var t = 1 / 0, n = Array.from(g(r.map((o) => o.value))).sort((o, d) => o - d); if (n.length < 2) return 1 / 0; var i = n[n.length - 1] - n[0]; if (i === 0) return 1 / 0; for (var a = 0; a < n.length - 1; a++) { var u = n[a + 1] - n[a]; t = Math.min(t, u); } return t / i; } }), se = l(_r, h, Be, A, (r, e, t, n) => n, (r, e, t, n, i) => { if (!F(r)) return 0; var a = e === "vertical" ? n.height : n.width; if (i === "gap") return r * a / 2; if (i === "no-gap") { var u = Ie(t, r * a), o = r * a / 2; return o - u - (o - u) / a * u; } return 0; }), Gr = (r, e) => { var t = b(r, e); return t == null || typeof t.padding != "string" ? 0 : se(r, "xAxis", e, t.padding); }, jr = (r, e) => { var t = D(r, e); return t == null || typeof t.padding != "string" ? 0 : se(r, "yAxis", e, t.padding); }, Fr = l(b, Gr, (r, e) => { var t, n; if (r == null) return { left: 0, right: 0 }; var { padding: i } = r; return typeof i == "string" ? { left: e, right: e } : { left: ((t = i.left) !== null && t !== void 0 ? t : 0) + e, right: ((n = i.right) !== null && n !== void 0 ? n : 0) + e }; }), Rr = l(D, jr, (r, e) => { var t, n; if (r == null) return { top: 0, bottom: 0 }; var { padding: i } = r; return typeof i == "string" ? { top: e, bottom: e } : { top: ((t = i.top) !== null && t !== void 0 ? t : 0) + e, bottom: ((n = i.bottom) !== null && n !== void 0 ? n : 0) + e }; }), zr = l([A, Fr, ne, ie, (r, e, t) => t], (r, e, t, n, i) => { var { padding: a } = n; return i ? [a.left, t.width - a.right] : [r.left + e.left, r.left + r.width - e.right]; }), Wr = l([A, h, Rr, ne, ie, (r, e, t) => t], (r, e, t, n, i, a) => { var { padding: u } = i; return a ? [n.height - u.bottom, u.top] : e === "horizontal" ? [r.top + r.height - t.bottom, r.top + t.top] : [r.top + t.top, r.top + r.height - t.bottom]; }), M = (r, e, t, n) => { var i; switch (e) { case "xAxis": return zr(r, t, n); case "yAxis": return Wr(r, t, n); case "zAxis": return (i = S(r, t)) === null || i === void 0 ? void 0 : i.range; case "angleAxis": return Me(r); case "radiusAxis": return Ke(r, t); default: return; } }, ve = l([v, M], _e), _ = l([v, I, Mr, ve], fe); l(O, f, (r, e) => r.flatMap((t) => { var n; return (n = t.errorBars) !== null && n !== void 0 ? n : []; }).filter((t) => oe(e, t))); function me(r, e) { return r.id < e.id ? -1 : r.id > e.id ? 1 : 0; } var G = (r, e) => e, j = (r, e, t) => t, Sr = l(re, G, j, (r, e, t) => r.filter((n) => n.orientation === e).filter((n) => n.mirror === t).sort(me)), Vr = l(te, G, j, (r, e, t) => r.filter((n) => n.orientation === e).filter((n) => n.mirror === t).sort(me)), pe = (r, e) => ({ width: r.width, height: e.height }), Xr = (r, e) => { var t = typeof e.width == "number" ? e.width : W; return { width: t, height: r.height }; }; l(A, b, pe); var Yr = (r, e, t) => { switch (e) { case "top": return r.top; case "bottom": return t - r.bottom; default: return 0; } }, $r = (r, e, t) => { switch (e) { case "left": return r.left; case "right": return t - r.right; default: return 0; } }; l(Ne, A, Sr, G, j, (r, e, t, n, i) => { var a = {}, u; return t.forEach((o) => { var d = pe(e, o); u == null && (u = Yr(e, n, r)); var c = n === "top" && !i || n === "bottom" && i; a[o.id] = u - Number(c) * d.height, u += (c ? -1 : 1) * d.height; }), a; }); l(Pe, A, Vr, G, j, (r, e, t, n, i) => { var a = {}, u; return t.forEach((o) => { var d = Xr(e, o); u == null && (u = $r(e, n, r)); var c = n === "left" && !i || n === "right" && i; a[o.id] = u - Number(c) * d.width, u += (c ? -1 : 1) * d.width; }), a; }); l(A, D, (r, e) => { var t = typeof e.width == "number" ? e.width : W; return { width: t, height: r.height }; }); var Hr = (r, e, t, n) => { if (t != null) { var { allowDuplicatedCategory: i, type: a, dataKey: u } = t, o = y(r, n), d = e.map((c) => c.value); if (u && o && a === "category" && i && J(d)) return d; } }, $ = l([h, K, v, f], Hr), Lr = (r, e, t, n) => { if (!(t == null || t.dataKey == null)) { var { type: i, scale: a } = t, u = y(r, n); if (u && (i === "number" || a !== "auto")) return e.map((o) => o.value); } }, H = l([h, K, B, f], Lr); l([h, Xe, I, _, $, H, M, Y, f], (r, e, t, n, i, a, u, o, d) => { if (e == null) return null; var c = y(r, d); return { angle: e.angle, interval: e.interval, minTickGap: e.minTickGap, orientation: e.orientation, tick: e.tick, tickCount: e.tickCount, tickFormatter: e.tickFormatter, ticks: e.ticks, type: e.type, unit: e.unit, axisType: d, categoricalDomain: a, duplicateDomain: i, isCategorical: c, niceTicks: o, range: u, realScaleType: t, scale: n }; }); var Tr = (r, e, t, n, i, a, u, o, d) => { if (!(e == null || n == null)) { var c = y(r, d), { type: m, ticks: w, tickCount: he } = e, Ae = t === "scaleBand" && typeof n.bandwidth == "function" ? n.bandwidth() / 2 : 2, p = m === "category" && n.bandwidth ? n.bandwidth() / Ae : 0; p = d === "angleAxis" && a != null && a.length >= 2 ? ee(a[0] - a[1]) * 2 * p : p; var L = w || i; if (L) { var ge = L.map((s, k) => { var ye = u ? u.indexOf(s) : s; return { index: k, // If the scaleContent is not a number, the coordinate will be NaN. // That could be the case for example with a PointScale and a string as domain. coordinate: n(ye) + p, value: s, offset: p }; }); return ge.filter((s) => !z(s.coordinate)); } return c && o ? o.map((s, k) => ({ coordinate: n(s) + p, value: s, index: k, offset: p })) : n.ticks ? n.ticks(he).map((s) => ({ coordinate: n(s) + p, value: s, offset: p })) : n.domain().map((s, k) => ({ coordinate: n(s) + p, value: u ? u[s] : s, index: k, offset: p })); } }; l([h, B, I, _, Y, M, $, H, f], Tr); var Ur = (r, e, t, n, i, a, u) => { if (!(e == null || t == null || n == null || n[0] === n[1])) { var o = y(r, u), { tickCount: d } = e, c = 0; return c = u === "angleAxis" && n?.length >= 2 ? ee(n[0] - n[1]) * 2 * c : c, o && a ? a.map((m, w) => ({ coordinate: t(m) + c, value: m, index: w, offset: c })) : t.ticks ? t.ticks(d).map((m) => ({ coordinate: t(m) + c, value: m, offset: c })) : t.domain().map((m, w) => ({ coordinate: t(m) + c, value: i ? i[m] : m, index: w, offset: c })); } }; l([h, B, _, M, $, H, f], Ur); l(v, _, (r, e) => { if (!(r == null || e == null)) return N(N({}, r), {}, { scale: e }); }); var Zr = l([v, I, X, ve], fe); l((r, e, t) => S(r, t), Zr, (r, e) => { if (!(r == null || e == null)) return N(N({}, r), {}, { scale: e }); }); l([h, re, te], (r, e, t) => { switch (r) { case "horizontal": return e.some((n) => n.reversed) ? "right-to-left" : "left-to-right"; case "vertical": return t.some((n) => n.reversed) ? "bottom-to-top" : "top-to-bottom"; // TODO: make this better. For now, right arrow triggers "forward", left arrow "back" // however, the tooltip moves an unintuitive direction because of how the indices are rendered case "centric": case "radial": return "left-to-right"; default: return; } }); export { ur as combineAppliedNumericalValuesIncludingErrorValues, er as combineAppliedValues, yr as combineAreasDomain, Nr as combineAxisDomain, Kr as combineAxisDomainWithNiceTicks, Tr as combineAxisTicks, Lr as combineCategoricalDomain, Qe as combineDisplayedData, ir as combineDomainOfStackGroups, Ar as combineDotsDomain, Hr as combineDuplicateDomain, Ur as combineGraphicalItemTicks, qe as combineGraphicalItemsData, Te as combineGraphicalItemsSettings, Dr as combineLinesDomain, Er as combineNiceTicks, Cr as combineNumericalDomain, Pr as combineRealScaleType, fe as combineScaleFunction, tr as combineStackGroups, zr as combineXAxisRange, Wr as combineYAxisRange, Ue as filterGraphicalNotStackedItems, V as filterReferenceElements, ce as getDomainDefinition, rr as getErrorDomainByDataKey, We as implicitXAxis, Se as implicitYAxis, Ve as implicitZAxis, oe as isErrorBarRelevantForAxisType, $e as itemAxisPredicate, de as mergeDomains, lr as selectAllAppliedNumericalValuesIncludingErrorValues, K as selectAllAppliedValues, X as selectAxisDomain, Mr as selectAxisDomainIncludingNiceTicks, M as selectAxisRange, ve as selectAxisRangeWithReverse, _ as selectAxisScale, B as selectAxisSettings, v as selectBaseAxis, Gr as selectCalculatedXAxisPadding, jr as selectCalculatedYAxisPadding, Je as selectCartesianGraphicalItemsData, O as selectCartesianItemsSettings, H as selectCategoricalDomain, E as selectDisplayedData, xr as selectDomainDefinition, ar as selectDomainOfStackGroups, $ as selectDuplicateDomain, Ye as selectHasBar, Y as selectNiceTicks, I as selectRealScaleType, vr as selectReferenceAreas, mr as selectReferenceAreasByAxis, fr as selectReferenceDots, sr as selectReferenceDotsByAxis, pr as selectReferenceLines, hr as selectReferenceLinesByAxis, _r as selectSmallestDistanceBetweenValues, nr as selectStackGroups, He as selectUnfilteredCartesianItems, b as selectXAxisSettings, D as selectYAxisSettings, S as selectZAxisSettings };