@deriv-web-design/ui 0.1.35 → 0.1.36

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.js CHANGED
@@ -52,10 +52,16 @@ __export(index_exports, {
52
52
  CryptoMarketsTable: () => CryptoMarketsTable,
53
53
  CryptoTradeConverter: () => CryptoTradeConverter,
54
54
  DEFAULT_AWARDS: () => DEFAULT_AWARDS,
55
+ DEFAULT_CRYPTO_MARKETS_TABLE_LABELS: () => DEFAULT_CRYPTO_MARKETS_TABLE_LABELS,
56
+ DEFAULT_CRYPTO_MARKETS_TABLE_TITLE: () => DEFAULT_CRYPTO_MARKETS_TABLE_TITLE,
57
+ DEFAULT_CRYPTO_TRADE_CONVERTER_LABELS: () => DEFAULT_CRYPTO_TRADE_CONVERTER_LABELS,
58
+ DEFAULT_CRYPTO_TRADE_CONVERTER_SUBTITLE: () => DEFAULT_CRYPTO_TRADE_CONVERTER_SUBTITLE,
59
+ DEFAULT_CRYPTO_TRADE_CONVERTER_TITLE: () => DEFAULT_CRYPTO_TRADE_CONVERTER_TITLE,
55
60
  DEFAULT_CULTURE_CARDS: () => DEFAULT_CULTURE_CARDS,
56
61
  DEFAULT_EXCHANGE_RATE_WS_URL: () => DEFAULT_EXCHANGE_RATE_WS_URL,
57
62
  DEFAULT_SYMBOLS_ENDPOINT: () => DEFAULT_SYMBOLS_ENDPOINT,
58
63
  DEFAULT_TRADE_HREF: () => DEFAULT_TRADE_HREF,
64
+ DEFAULT_TRADING_CALCULATOR_LABELS: () => DEFAULT_TRADING_CALCULATOR_LABELS,
59
65
  DayNightTransition: () => DayNightTransition,
60
66
  DocumentChips: () => DocumentChips,
61
67
  DotLottieInView: () => DotLottieInView,
@@ -8321,7 +8327,55 @@ var ParallaxBanner = ({
8321
8327
 
8322
8328
  // templates/TradingCalculator/TradingCalculator.tsx
8323
8329
  var import_react34 = require("react");
8330
+
8331
+ // templates/TradingCalculator/TradingCalculator.types.ts
8332
+ var DEFAULT_TRADING_CALCULATOR_LABELS = {
8333
+ calculatorPanel: "Calculator",
8334
+ resultsPanel: "Results",
8335
+ calculate: "Calculate",
8336
+ calculating: "Calculating\u2026",
8337
+ reset: "Reset",
8338
+ symbols: "Symbols",
8339
+ volume: "Volume in Lots",
8340
+ assetPrice: "Asset price",
8341
+ contractSize: "Contract size",
8342
+ pipSize: "Pip size",
8343
+ effectiveLeverage: "Effective Leverage",
8344
+ pointSize: "Point size",
8345
+ marginRequired: "Margin Required",
8346
+ tradeVolume: "Trade Volume",
8347
+ pipValue: "Pip value",
8348
+ swapChargeLong: "Swap Charge Long",
8349
+ swapChargeShort: "Swap Charge Short",
8350
+ swapLongRate: "Swap long rate",
8351
+ swapShortRate: "Swap short rate",
8352
+ swapCalculationType: "Swap calculation type",
8353
+ threeDaySwap: "Three-day swap",
8354
+ weekendSwaps: "Weekend swaps",
8355
+ threeDaySwapFallback: "No",
8356
+ loadingSymbols: "Loading symbols\u2026",
8357
+ symbolsUnavailable: "Symbols unavailable",
8358
+ searchSymbolPlaceholder: "Search symbol, e.g. EURUSD",
8359
+ symbolsLoadError: "Unable to load symbols.",
8360
+ retry: "Retry",
8361
+ selectSymbolError: "Select a symbol to continue.",
8362
+ volumeRequiredError: "Enter a valid volume in lots.",
8363
+ volumePositiveError: "Volume must be greater than 0.",
8364
+ volumeRangeError: "Volume must be between {min} and {max} lots.",
8365
+ assetPriceError: "Enter a valid asset price.",
8366
+ exchangeRateError: "Unable to fetch live exchange rates. Please try again.",
8367
+ exchangeRateErrorWithMessage: "Unable to fetch live exchange rates ({message}). Please try again.",
8368
+ noSymbolsMatch: 'No symbols match "{query}"'
8369
+ };
8370
+
8371
+ // templates/TradingCalculator/TradingCalculator.tsx
8324
8372
  var import_jsx_runtime60 = require("react/jsx-runtime");
8373
+ function fillTemplate2(template, values) {
8374
+ return template.replace(/\{(\w+)\}/g, (_, key) => values[key] ?? "");
8375
+ }
8376
+ function mergeLabels(overrides) {
8377
+ return { ...DEFAULT_TRADING_CALCULATOR_LABELS, ...overrides };
8378
+ }
8325
8379
  var DEFAULT_SYMBOLS_ENDPOINT = "https://deriv-static-pricingfeedv2.firebaseio.com/n8n/row/prod/dynamic_trading_specs.json";
8326
8380
  var DEFAULT_EXCHANGE_RATE_WS_URL = "wss://ws.derivws.com/websockets/v3?app_id=1089";
8327
8381
  var USD = "USD";
@@ -8481,7 +8535,15 @@ function groupByAssetClass(symbols) {
8481
8535
  }
8482
8536
  return [...groups.entries()];
8483
8537
  }
8484
- var SymbolCombobox = ({ symbolsState, onRetry, selected, onSelect, error, inputId }) => {
8538
+ var SymbolCombobox = ({
8539
+ symbolsState,
8540
+ onRetry,
8541
+ selected,
8542
+ onSelect,
8543
+ error,
8544
+ inputId,
8545
+ copy
8546
+ }) => {
8485
8547
  const [query, setQuery] = (0, import_react34.useState)("");
8486
8548
  const [isOpen, setIsOpen] = (0, import_react34.useState)(false);
8487
8549
  const [activeIndex, setActiveIndex] = (0, import_react34.useState)(-1);
@@ -8539,7 +8601,8 @@ var SymbolCombobox = ({ symbolsState, onRetry, selected, onSelect, error, inputI
8539
8601
  {
8540
8602
  id: inputId,
8541
8603
  label: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
8542
- "Symbols ",
8604
+ copy.symbols,
8605
+ " ",
8543
8606
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "tcalc-required", children: "*" })
8544
8607
  ] }),
8545
8608
  role: "combobox",
@@ -8554,7 +8617,7 @@ var SymbolCombobox = ({ symbolsState, onRetry, selected, onSelect, error, inputI
8554
8617
  disabled: isLoading || isError,
8555
8618
  hideClearButton: true,
8556
8619
  trailingSlot: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ChevronIcon3, {}),
8557
- placeholder: isLoading ? "Loading symbols\u2026" : isError ? "Symbols unavailable" : "Search symbol, e.g. EURUSD",
8620
+ placeholder: isLoading ? copy.loadingSymbols : isError ? copy.symbolsUnavailable : copy.searchSymbolPlaceholder,
8558
8621
  value: displayValue,
8559
8622
  onFocus: () => setIsOpen(true),
8560
8623
  onChange: (event) => {
@@ -8566,11 +8629,7 @@ var SymbolCombobox = ({ symbolsState, onRetry, selected, onSelect, error, inputI
8566
8629
  }
8567
8630
  ),
8568
8631
  isOpen && !isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-dropdown", id: listboxId, role: "listbox", children: [
8569
- grouped.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("p", { className: "tcalc-dropdownEmpty", children: [
8570
- 'No symbols match "',
8571
- query,
8572
- '"'
8573
- ] }),
8632
+ grouped.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "tcalc-dropdownEmpty", children: fillTemplate2(copy.noSymbolsMatch, { query }) }),
8574
8633
  grouped.map(([assetClass, items]) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-dropdownGroup", children: [
8575
8634
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "tcalc-dropdownGroupTitle", children: assetClass }),
8576
8635
  items.map((item) => {
@@ -8602,9 +8661,10 @@ var SymbolCombobox = ({ symbolsState, onRetry, selected, onSelect, error, inputI
8602
8661
  ] }),
8603
8662
  isError && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("p", { className: "tcalc-fieldError", children: [
8604
8663
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ErrorIcon, {}),
8605
- " Unable to load symbols.",
8606
8664
  " ",
8607
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "tcalc-retryLink", onClick: onRetry, children: "Retry" })
8665
+ copy.symbolsLoadError,
8666
+ " ",
8667
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "tcalc-retryLink", onClick: onRetry, children: copy.retry })
8608
8668
  ] }),
8609
8669
  !isError && error && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("p", { className: "tcalc-fieldError", children: [
8610
8670
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ErrorIcon, {}),
@@ -8632,9 +8692,11 @@ var TradingCalculator = ({
8632
8692
  symbolsEndpoint = DEFAULT_SYMBOLS_ENDPOINT,
8633
8693
  exchangeRateWsUrl = DEFAULT_EXCHANGE_RATE_WS_URL,
8634
8694
  defaultSymbol,
8695
+ labels: labelsProp,
8635
8696
  className,
8636
8697
  ...props
8637
8698
  }) => {
8699
+ const copy = mergeLabels(labelsProp);
8638
8700
  const showMargin = variant === "main" || variant === "margin";
8639
8701
  const showPip = variant === "main" || variant === "pip";
8640
8702
  const showSwap = variant === "main" || variant === "swap";
@@ -8678,15 +8740,18 @@ var TradingCalculator = ({
8678
8740
  const volume = Number.parseFloat(volumeInLots);
8679
8741
  const price = Number.parseFloat(assetPrice);
8680
8742
  const nextErrors = {};
8681
- if (!selectedSymbol) nextErrors.symbol = "Select a symbol to continue.";
8743
+ if (!selectedSymbol) nextErrors.symbol = copy.selectSymbolError;
8682
8744
  if (!volumeInLots || Number.isNaN(volume)) {
8683
- nextErrors.volume = "Enter a valid volume in lots.";
8745
+ nextErrors.volume = copy.volumeRequiredError;
8684
8746
  } else if (volume <= 0) {
8685
- nextErrors.volume = "Volume must be greater than 0.";
8747
+ nextErrors.volume = copy.volumePositiveError;
8686
8748
  } else if (selectedSymbol && (volume < selectedSymbol.volume_min || volume > selectedSymbol.volume_limit)) {
8687
- nextErrors.volume = `Volume must be between ${selectedSymbol.volume_min} and ${selectedSymbol.volume_limit} lots.`;
8749
+ nextErrors.volume = fillTemplate2(copy.volumeRangeError, {
8750
+ min: String(selectedSymbol.volume_min),
8751
+ max: String(selectedSymbol.volume_limit)
8752
+ });
8688
8753
  }
8689
- if (!assetPrice || Number.isNaN(price) || price <= 0) nextErrors.price = "Enter a valid asset price.";
8754
+ if (!assetPrice || Number.isNaN(price) || price <= 0) nextErrors.price = copy.assetPriceError;
8690
8755
  setErrors(nextErrors);
8691
8756
  if (Object.keys(nextErrors).length > 0 || !selectedSymbol) return;
8692
8757
  setCalcError(null);
@@ -8697,7 +8762,7 @@ var TradingCalculator = ({
8697
8762
  setResults(computeResults(selectedSymbol, volume, price, rates));
8698
8763
  } catch (error) {
8699
8764
  setCalcError(
8700
- error instanceof Error ? `Unable to fetch live exchange rates (${error.message}). Please try again.` : "Unable to fetch live exchange rates. Please try again."
8765
+ error instanceof Error ? fillTemplate2(copy.exchangeRateErrorWithMessage, { message: error.message }) : copy.exchangeRateError
8701
8766
  );
8702
8767
  } finally {
8703
8768
  setIsCalculating(false);
@@ -8708,7 +8773,7 @@ var TradingCalculator = ({
8708
8773
  const priceInputId = (0, import_react34.useId)();
8709
8774
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("section", { className: ["tcalc-section", className ?? ""].filter(Boolean).join(" "), ...props, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "tcalc-container", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-card", children: [
8710
8775
  /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-column", children: [
8711
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h3", { className: "tcalc-panelTitle", children: "Calculator" }),
8776
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h3", { className: "tcalc-panelTitle", children: copy.calculatorPanel }),
8712
8777
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8713
8778
  SymbolCombobox,
8714
8779
  {
@@ -8717,20 +8782,21 @@ var TradingCalculator = ({
8717
8782
  selected: selectedSymbol,
8718
8783
  onSelect: handleSelectSymbol,
8719
8784
  error: errors.symbol,
8720
- inputId: symbolInputId
8785
+ inputId: symbolInputId,
8786
+ copy
8721
8787
  }
8722
8788
  ),
8723
8789
  /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-infoGrid", children: [
8724
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: "Contract size", value: selectedSymbol ? integerFormatter.format(selectedSymbol.contract_size) : "-" }),
8725
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: "Pip size", value: selectedSymbol ? String(selectedSymbol.pip_size) : "-" }),
8790
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: copy.contractSize, value: selectedSymbol ? integerFormatter.format(selectedSymbol.contract_size) : "-" }),
8791
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: copy.pipSize, value: selectedSymbol ? String(selectedSymbol.pip_size) : "-" }),
8726
8792
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8727
8793
  InfoRow,
8728
8794
  {
8729
- label: "Effective Leverage",
8795
+ label: copy.effectiveLeverage,
8730
8796
  value: selectedSymbol ? `1 : ${Math.round((selectedSymbol.effective_leverage + Number.EPSILON) * 100) / 100}` : "-"
8731
8797
  }
8732
8798
  ),
8733
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: "Point size", value: selectedSymbol ? String(selectedSymbol.point_size) : "-" })
8799
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: copy.pointSize, value: selectedSymbol ? String(selectedSymbol.point_size) : "-" })
8734
8800
  ] }),
8735
8801
  /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-field", children: [
8736
8802
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
@@ -8739,7 +8805,8 @@ var TradingCalculator = ({
8739
8805
  id: volumeInputId,
8740
8806
  className: "tcalc-numberField",
8741
8807
  label: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
8742
- "Volume in Lots ",
8808
+ copy.volume,
8809
+ " ",
8743
8810
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "tcalc-required", children: "*" })
8744
8811
  ] }),
8745
8812
  status: errors.volume ? "fail" : "neutral",
@@ -8756,7 +8823,7 @@ var TradingCalculator = ({
8756
8823
  const isNegative = value !== "" && !Number.isNaN(parsed) && parsed <= 0;
8757
8824
  setErrors((prev) => ({
8758
8825
  ...prev,
8759
- volume: isNegative ? "Volume must be greater than 0." : void 0
8826
+ volume: isNegative ? copy.volumePositiveError : void 0
8760
8827
  }));
8761
8828
  }
8762
8829
  }
@@ -8774,7 +8841,8 @@ var TradingCalculator = ({
8774
8841
  id: priceInputId,
8775
8842
  className: "tcalc-numberField",
8776
8843
  label: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
8777
- "Asset price ",
8844
+ copy.assetPrice,
8845
+ " ",
8778
8846
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "tcalc-required", children: "*" })
8779
8847
  ] }),
8780
8848
  status: errors.price ? "fail" : "neutral",
@@ -8803,7 +8871,7 @@ var TradingCalculator = ({
8803
8871
  type: "button",
8804
8872
  colorScheme: "coral",
8805
8873
  variant: "primary",
8806
- label: isCalculating ? "Calculating\u2026" : "Calculate",
8874
+ label: isCalculating ? copy.calculating : copy.calculate,
8807
8875
  onClick: handleCalculate,
8808
8876
  disabled: isCalculating,
8809
8877
  fullWidth: true
@@ -8815,7 +8883,7 @@ var TradingCalculator = ({
8815
8883
  type: "button",
8816
8884
  colorScheme: "black",
8817
8885
  variant: "secondary",
8818
- label: "Reset",
8886
+ label: copy.reset,
8819
8887
  onClick: handleReset,
8820
8888
  fullWidth: true
8821
8889
  }
@@ -8823,16 +8891,16 @@ var TradingCalculator = ({
8823
8891
  ] })
8824
8892
  ] }),
8825
8893
  /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-column tcalc-column--results", children: [
8826
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h3", { className: "tcalc-panelTitle", children: "Results" }),
8827
- showMargin && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: "Margin Required", value: results ? formatMoney(results.marginRequired) : "$" }),
8894
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h3", { className: "tcalc-panelTitle", children: copy.resultsPanel }),
8895
+ showMargin && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: copy.marginRequired, value: results ? formatMoney(results.marginRequired) : "$" }),
8828
8896
  showTradeVolume && showPip && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-resultRow", children: [
8829
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: "Trade Volume", value: results ? formatInteger(results.tradeVolume) : "$" }),
8830
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: "Pip value", value: results ? formatMoney(results.pipValue) : "$" })
8897
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: copy.tradeVolume, value: results ? formatInteger(results.tradeVolume) : "$" }),
8898
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: copy.pipValue, value: results ? formatMoney(results.pipValue) : "$" })
8831
8899
  ] }),
8832
- !showTradeVolume && showPip && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: "Pip value", value: results ? formatMoney(results.pipValue) : "$" }),
8900
+ !showTradeVolume && showPip && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: copy.pipValue, value: results ? formatMoney(results.pipValue) : "$" }),
8833
8901
  showSwap && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-resultRow", children: [
8834
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: "Swap Charge Long", value: results ? formatMoney(results.swapChargeLong) : "$" }),
8835
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: "Swap Charge Short", value: results ? formatMoney(results.swapChargeShort) : "$" })
8902
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: copy.swapChargeLong, value: results ? formatMoney(results.swapChargeLong) : "$" }),
8903
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ResultBox, { label: copy.swapChargeShort, value: results ? formatMoney(results.swapChargeShort) : "$" })
8836
8904
  ] }),
8837
8905
  calcError && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("p", { className: "tcalc-fieldError tcalc-calcError", children: [
8838
8906
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ErrorIcon, {}),
@@ -8841,12 +8909,12 @@ var TradingCalculator = ({
8841
8909
  ] }),
8842
8910
  showSwap && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
8843
8911
  /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "tcalc-infoGrid", children: [
8844
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: "Swap long rate", value: selectedSymbol ? String(selectedSymbol.swap_rate_long) : "-" }),
8845
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: "Swap short rate", value: selectedSymbol ? String(selectedSymbol.swap_rate_short) : "-" })
8912
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: copy.swapLongRate, value: selectedSymbol ? String(selectedSymbol.swap_rate_long) : "-" }),
8913
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { label: copy.swapShortRate, value: selectedSymbol ? String(selectedSymbol.swap_rate_short) : "-" })
8846
8914
  ] }),
8847
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { separator: ":", label: "Swap calculation type", value: selectedSymbol ? selectedSymbol.swap_mode : "-" }),
8848
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { separator: ":", label: "Three-day swap", value: selectedSymbol ? selectedSymbol.three_day_swap || "No" : "-" }),
8849
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { separator: ":", label: "Weekend swaps", value: selectedSymbol ? String(selectedSymbol.weekend_swaps ?? "-") : "-" })
8915
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { separator: ":", label: copy.swapCalculationType, value: selectedSymbol ? selectedSymbol.swap_mode : "-" }),
8916
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { separator: ":", label: copy.threeDaySwap, value: selectedSymbol ? selectedSymbol.three_day_swap || copy.threeDaySwapFallback : "-" }),
8917
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InfoRow, { separator: ":", label: copy.weekendSwaps, value: selectedSymbol ? String(selectedSymbol.weekend_swaps ?? "-") : "-" })
8850
8918
  ] })
8851
8919
  ] })
8852
8920
  ] }) }) });
@@ -9444,9 +9512,11 @@ function browserSupportsMarketStreaming() {
9444
9512
 
9445
9513
  // templates/cryptoMarketData/conversion.ts
9446
9514
  function convertAmounts(options) {
9515
+ const waitingForPrice = options.messages?.waitingForPrice ?? "Waiting for a live price";
9516
+ const invalidAmount = options.messages?.invalidAmount ?? "Enter a valid amount";
9447
9517
  const price = options.price;
9448
9518
  if (price == null || !Number.isFinite(price) || price <= 0) {
9449
- return { pay: options.payInput, receive: options.receiveInput, valid: false, error: "Waiting for a live price" };
9519
+ return { pay: options.payInput, receive: options.receiveInput, valid: false, error: waitingForPrice };
9450
9520
  }
9451
9521
  const source = options.edited === "pay" ? options.payInput : options.receiveInput;
9452
9522
  const trimmed = source.trim();
@@ -9459,7 +9529,7 @@ function convertAmounts(options) {
9459
9529
  pay: options.payInput,
9460
9530
  receive: options.receiveInput,
9461
9531
  valid: false,
9462
- error: "Enter a valid amount"
9532
+ error: invalidAmount
9463
9533
  };
9464
9534
  }
9465
9535
  if (options.side === "buy") {
@@ -10004,9 +10074,39 @@ function useCryptoMarketData(options) {
10004
10074
  return snapshot;
10005
10075
  }
10006
10076
 
10077
+ // templates/CryptoTradeConverter/CryptoTradeConverter.types.ts
10078
+ var DEFAULT_CRYPTO_TRADE_CONVERTER_TITLE = "Buy and sell in seconds";
10079
+ var DEFAULT_CRYPTO_TRADE_CONVERTER_SUBTITLE = "Choose your asset, enter an amount, and confirm. Your crypto lands in your account instantly, ready to trade, hold, or withdraw whenever you want.";
10080
+ var DEFAULT_CRYPTO_TRADE_CONVERTER_LABELS = {
10081
+ buy: "Buy",
10082
+ sell: "Sell",
10083
+ connecting: "Connecting to live prices\u2026",
10084
+ livePrices: "Live prices",
10085
+ waitingForPrice: "Waiting for a live price",
10086
+ unsupportedBrowser: "Please use a current browser to view live prices.",
10087
+ selectMarket: "Select a market",
10088
+ chooseMarket: "Choose a market",
10089
+ tradeSideGroup: "Trade side",
10090
+ youPay: "You pay",
10091
+ youReceive: "You receive",
10092
+ amountToSpend: "Amount to spend",
10093
+ primaryAmountAria: "Primary trade amount",
10094
+ convertedAmountAria: "Converted trade amount",
10095
+ estimateTemplate: "Estimate at 1 {base} = {price} {quote}. Fees and spread excluded.",
10096
+ change24hSuffix: "(24h)",
10097
+ waitingForLivePrice: "Waiting for live price\u2026",
10098
+ invalidAmount: "Enter a valid amount"
10099
+ };
10100
+
10007
10101
  // templates/CryptoTradeConverter/CryptoTradeConverter.tsx
10008
10102
  var import_jsx_runtime62 = require("react/jsx-runtime");
10009
10103
  var DEFAULT_TRADE_HREF = "https://deriv.exchange";
10104
+ function fillTemplate3(template, values) {
10105
+ return template.replace(/\{(\w+)\}/g, (_, key) => values[key] ?? "");
10106
+ }
10107
+ function mergeLabels2(overrides) {
10108
+ return { ...DEFAULT_CRYPTO_TRADE_CONVERTER_LABELS, ...overrides };
10109
+ }
10010
10110
  function matchPair(rows, defaultPair) {
10011
10111
  if (!rows.length) return null;
10012
10112
  if (!defaultPair) {
@@ -10059,8 +10159,12 @@ var CryptoTradeConverter = ({
10059
10159
  defaultPair,
10060
10160
  tradeHref = DEFAULT_TRADE_HREF,
10061
10161
  apiOrigin,
10162
+ title = DEFAULT_CRYPTO_TRADE_CONVERTER_TITLE,
10163
+ subtitle = DEFAULT_CRYPTO_TRADE_CONVERTER_SUBTITLE,
10164
+ labels: labelsProp,
10062
10165
  className
10063
10166
  }) => {
10167
+ const copy = mergeLabels2(labelsProp);
10064
10168
  const reactId = (0, import_react37.useId)().replace(/:/g, "");
10065
10169
  const listboxId = `ctc-listbox-${reactId}`;
10066
10170
  const payId = `ctc-pay-${reactId}`;
@@ -10088,9 +10192,13 @@ var CryptoTradeConverter = ({
10088
10192
  price: selected?.last ?? null,
10089
10193
  payInput: pay,
10090
10194
  receiveInput: receive,
10091
- edited
10195
+ edited,
10196
+ messages: {
10197
+ waitingForPrice: copy.waitingForPrice,
10198
+ invalidAmount: copy.invalidAmount
10199
+ }
10092
10200
  }),
10093
- [side, selected?.last, pay, receive, edited]
10201
+ [side, selected?.last, pay, receive, edited, copy.waitingForPrice, copy.invalidAmount]
10094
10202
  );
10095
10203
  (0, import_react37.useEffect)(() => {
10096
10204
  if (edited === "pay") setReceive(conversion.receive);
@@ -10161,8 +10269,12 @@ var CryptoTradeConverter = ({
10161
10269
  const changeClass = selected?.change24hPct == null ? "" : selected.change24hPct >= 0 ? "ctc-change--up" : "ctc-change--down";
10162
10270
  const payValue = edited === "pay" ? pay : conversion.pay;
10163
10271
  const receiveValue = edited === "receive" ? receive : conversion.receive;
10164
- const receiveMeta = priceReady && selected ? `Estimate at 1 ${selected.base} = ${formatPrice(selected.last, selected.pricePrecision)} ${selected.quote}. Fees and spread excluded.` : snapshot.status === "unsupported" ? "Please use a current browser to view live prices." : conversion.error || (snapshot.status === "idle" || snapshot.status === "connecting" ? "Connecting to live prices\u2026" : "Waiting for live price\u2026");
10165
- const ctaLabel = side === "buy" ? "Buy" : "Sell";
10272
+ const receiveMeta = priceReady && selected ? fillTemplate3(copy.estimateTemplate, {
10273
+ base: selected.base,
10274
+ price: formatPrice(selected.last, selected.pricePrecision),
10275
+ quote: selected.quote
10276
+ }) : snapshot.status === "unsupported" ? copy.unsupportedBrowser : conversion.error || (snapshot.status === "idle" || snapshot.status === "connecting" ? copy.connecting : copy.waitingForLivePrice);
10277
+ const ctaLabel = side === "buy" ? copy.buy : copy.sell;
10166
10278
  const ctaClass = ["ctc-cta__btn", side === "sell" ? "is-sell" : "is-buy"].join(" ");
10167
10279
  return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10168
10280
  "section",
@@ -10174,8 +10286,8 @@ var CryptoTradeConverter = ({
10174
10286
  "aria-labelledby": `ctc-heading-${reactId}`,
10175
10287
  children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "ctc-container", children: [
10176
10288
  /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("header", { className: "ctc-header", children: [
10177
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h2", { id: `ctc-heading-${reactId}`, className: "ctc-title", children: "Buy and sell in seconds" }),
10178
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "ctc-subtitle", children: "Choose your asset, enter an amount, and confirm. Your crypto lands in your account instantly, ready to trade, hold, or withdraw whenever you want." })
10289
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h2", { id: `ctc-heading-${reactId}`, className: "ctc-title", children: title }),
10290
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "ctc-subtitle", children: subtitle })
10179
10291
  ] }),
10180
10292
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ctc-card", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "ctc-widget", children: [
10181
10293
  /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
@@ -10187,7 +10299,7 @@ var CryptoTradeConverter = ({
10187
10299
  "aria-live": "polite",
10188
10300
  children: [
10189
10301
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-status-dot", "aria-hidden": "true" }),
10190
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: snapshot.status === "idle" || snapshot.status === "connecting" ? "Connecting to live prices\u2026" : snapshot.statusMessage || (priceReady ? "Live prices" : "Waiting for live price\u2026") })
10302
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: snapshot.status === "idle" || snapshot.status === "connecting" ? copy.connecting : snapshot.statusMessage || (priceReady ? copy.livePrices : copy.waitingForLivePrice) })
10191
10303
  ]
10192
10304
  }
10193
10305
  ),
@@ -10227,12 +10339,13 @@ var CryptoTradeConverter = ({
10227
10339
  " ",
10228
10340
  /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: ["ctc-change", changeClass].filter(Boolean).join(" "), children: [
10229
10341
  formatPct(selected.change24hPct),
10230
- " (24h)"
10342
+ " ",
10343
+ copy.change24hSuffix
10231
10344
  ] })
10232
10345
  ] })
10233
10346
  ] })
10234
10347
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "ctc-pair__meta", children: [
10235
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-pair__name", children: "Select a market" }),
10348
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-pair__name", children: copy.selectMarket }),
10236
10349
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-pair__price", children: "\u2014" })
10237
10350
  ] }),
10238
10351
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(ChevronIcon4, { className: "ctc-pair__chevron" })
@@ -10246,11 +10359,11 @@ var CryptoTradeConverter = ({
10246
10359
  id: listboxId,
10247
10360
  className: "ctc-listbox",
10248
10361
  role: "listbox",
10249
- "aria-label": "Choose a market",
10362
+ "aria-label": copy.chooseMarket,
10250
10363
  tabIndex: -1,
10251
10364
  onKeyDown: onPickerKeyDown,
10252
10365
  children: [
10253
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("li", { className: "ctc-listbox__header", role: "presentation", children: "Choose a market" }),
10366
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("li", { className: "ctc-listbox__header", role: "presentation", children: copy.chooseMarket }),
10254
10367
  sortedRows.map((row, index) => {
10255
10368
  const selectedOption = selected?.id === row.id;
10256
10369
  const active = index === activeOption;
@@ -10290,7 +10403,7 @@ var CryptoTradeConverter = ({
10290
10403
  }
10291
10404
  ) : null
10292
10405
  ] }),
10293
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "ctc-seg", role: "group", "aria-label": "Trade side", children: [
10406
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "ctc-seg", role: "group", "aria-label": copy.tradeSideGroup, children: [
10294
10407
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10295
10408
  "button",
10296
10409
  {
@@ -10298,7 +10411,7 @@ var CryptoTradeConverter = ({
10298
10411
  className: side === "buy" ? "ctc-seg__btn is-active is-buy" : "ctc-seg__btn is-buy",
10299
10412
  "aria-pressed": side === "buy",
10300
10413
  onClick: () => setSide("buy"),
10301
- children: "Buy"
10414
+ children: copy.buy
10302
10415
  }
10303
10416
  ),
10304
10417
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
@@ -10308,7 +10421,7 @@ var CryptoTradeConverter = ({
10308
10421
  className: side === "sell" ? "ctc-seg__btn is-active is-sell" : "ctc-seg__btn is-sell",
10309
10422
  "aria-pressed": side === "sell",
10310
10423
  onClick: () => setSide("sell"),
10311
- children: "Sell"
10424
+ children: copy.sell
10312
10425
  }
10313
10426
  )
10314
10427
  ] }),
@@ -10319,7 +10432,7 @@ var CryptoTradeConverter = ({
10319
10432
  className: ["ctc-amount", conversion.error ? "is-invalid" : ""].filter(Boolean).join(" "),
10320
10433
  htmlFor: payId,
10321
10434
  children: [
10322
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-amount__label", children: "You pay" }),
10435
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-amount__label", children: copy.youPay }),
10323
10436
  /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "ctc-amount__row", children: [
10324
10437
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10325
10438
  "input",
@@ -10331,7 +10444,7 @@ var CryptoTradeConverter = ({
10331
10444
  autoComplete: "off",
10332
10445
  placeholder: "0.00",
10333
10446
  value: payValue,
10334
- "aria-label": "Primary trade amount",
10447
+ "aria-label": copy.primaryAmountAria,
10335
10448
  "aria-invalid": Boolean(conversion.error),
10336
10449
  "aria-describedby": statusId,
10337
10450
  onChange: (event) => {
@@ -10342,7 +10455,7 @@ var CryptoTradeConverter = ({
10342
10455
  ),
10343
10456
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-amount__unit", children: labels.pay })
10344
10457
  ] }),
10345
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-amount__meta", children: "Amount to spend" })
10458
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-amount__meta", children: copy.amountToSpend })
10346
10459
  ]
10347
10460
  }
10348
10461
  ),
@@ -10352,7 +10465,7 @@ var CryptoTradeConverter = ({
10352
10465
  className: ["ctc-amount", conversion.error ? "is-invalid" : ""].filter(Boolean).join(" "),
10353
10466
  htmlFor: receiveId,
10354
10467
  children: [
10355
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-amount__label", children: "You receive" }),
10468
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ctc-amount__label", children: copy.youReceive }),
10356
10469
  /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "ctc-amount__row", children: [
10357
10470
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
10358
10471
  "input",
@@ -10364,7 +10477,7 @@ var CryptoTradeConverter = ({
10364
10477
  autoComplete: "off",
10365
10478
  placeholder: "0.00",
10366
10479
  value: receiveValue,
10367
- "aria-label": "Converted trade amount",
10480
+ "aria-label": copy.convertedAmountAria,
10368
10481
  "aria-invalid": Boolean(conversion.error),
10369
10482
  "aria-describedby": `ctc-rate-${reactId}`,
10370
10483
  onChange: (event) => {
@@ -10407,7 +10520,37 @@ var CryptoTradeConverter = ({
10407
10520
 
10408
10521
  // templates/CryptoMarketsTable/CryptoMarketsTable.tsx
10409
10522
  var import_react38 = require("react");
10523
+
10524
+ // templates/CryptoMarketsTable/CryptoMarketsTable.types.ts
10525
+ var DEFAULT_CRYPTO_MARKETS_TABLE_TITLE = "Explore the markets";
10526
+ var DEFAULT_CRYPTO_MARKETS_TABLE_LABELS = {
10527
+ spot: "Spot",
10528
+ futures: "Futures",
10529
+ live: "Live",
10530
+ connecting: "Connecting\u2026",
10531
+ marketTypeGroup: "Market type",
10532
+ quoteCurrencyTabs: "Quote currency",
10533
+ scrollRegion: "Market prices. Scroll horizontally to see all columns.",
10534
+ columnName: "Name",
10535
+ columnPrice: "Price",
10536
+ column1h: "1h %",
10537
+ column24h: "24h %",
10538
+ column7d: "7d chart",
10539
+ unsupportedBrowser: "Please use a current browser to view market prices.",
10540
+ loadError: "Unable to load market data. Retrying\u2026",
10541
+ loading: "Loading market data\u2026",
10542
+ emptyPairsTemplate: "No {quote} pairs on {kind} yet\u2026",
10543
+ sparklineAriaTemplate: "{name} available hourly price history, up to 7 days"
10544
+ };
10545
+
10546
+ // templates/CryptoMarketsTable/CryptoMarketsTable.tsx
10410
10547
  var import_jsx_runtime63 = require("react/jsx-runtime");
10548
+ function fillTemplate4(template, values) {
10549
+ return template.replace(/\{(\w+)\}/g, (_, key) => values[key] ?? "");
10550
+ }
10551
+ function mergeLabels3(overrides) {
10552
+ return { ...DEFAULT_CRYPTO_MARKETS_TABLE_LABELS, ...overrides };
10553
+ }
10411
10554
  function CoinAvatar2({ base, icon }) {
10412
10555
  const [failed, setFailed] = (0, import_react38.useState)(false);
10413
10556
  if (failed) {
@@ -10513,8 +10656,11 @@ var CryptoMarketsTable = ({
10513
10656
  initialQuoteCurrency = "USDT",
10514
10657
  apiOrigin,
10515
10658
  maxRows,
10659
+ title = DEFAULT_CRYPTO_MARKETS_TABLE_TITLE,
10660
+ labels: labelsProp,
10516
10661
  className
10517
10662
  }) => {
10663
+ const copy = mergeLabels3(labelsProp);
10518
10664
  const reactId = (0, import_react38.useId)().replace(/:/g, "");
10519
10665
  const [kind, setKind] = (0, import_react38.useState)(initialMarket);
10520
10666
  const [quote, setQuote] = (0, import_react38.useState)(initialQuoteCurrency.toUpperCase());
@@ -10561,7 +10707,14 @@ var CryptoMarketsTable = ({
10561
10707
  }
10562
10708
  };
10563
10709
  const statusTone = snapshot.status === "live" ? "live" : snapshot.status === "reconnecting" || snapshot.status === "stale" ? "warn" : snapshot.status === "error" || snapshot.status === "unsupported" ? "error" : "muted";
10564
- const emptyMessage = snapshot.status === "unsupported" ? "Please use a current browser to view market prices." : snapshot.status === "error" ? "Unable to load market data. Retrying\u2026" : snapshot.status === "connecting" || snapshot.status === "idle" ? "Loading market data\u2026" : `No ${quote} pairs on ${kind} yet\u2026`;
10710
+ const emptyMessage = snapshot.status === "unsupported" ? copy.unsupportedBrowser : snapshot.status === "error" ? copy.loadError : snapshot.status === "connecting" || snapshot.status === "idle" ? copy.loading : fillTemplate4(copy.emptyPairsTemplate, { quote, kind });
10711
+ const columnLabels = [
10712
+ ["name", copy.columnName],
10713
+ ["last", copy.columnPrice],
10714
+ ["change1hPct", copy.column1h],
10715
+ ["change24hPct", copy.column24h],
10716
+ ["change7dPct", copy.column7d]
10717
+ ];
10565
10718
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10566
10719
  "section",
10567
10720
  {
@@ -10570,26 +10723,26 @@ var CryptoMarketsTable = ({
10570
10723
  "aria-labelledby": `cmt-heading-${reactId}`,
10571
10724
  children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "cmt-container", children: [
10572
10725
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("header", { className: "cmt-header", children: [
10573
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h2", { id: `cmt-heading-${reactId}`, className: "cmt-title", children: "Explore the markets" }),
10726
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h2", { id: `cmt-heading-${reactId}`, className: "cmt-title", children: title }),
10574
10727
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("p", { className: `cmt-status cmt-status--${statusTone}`, role: "status", "aria-live": "polite", children: [
10575
10728
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "cmt-status-dot", "aria-hidden": "true" }),
10576
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { children: snapshot.status === "live" ? "Live" : snapshot.statusMessage || "Connecting\u2026" })
10729
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { children: snapshot.status === "live" ? copy.live : snapshot.statusMessage || copy.connecting })
10577
10730
  ] })
10578
10731
  ] }),
10579
10732
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "cmt-card", children: [
10580
10733
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "cmt-toolbar", children: [
10581
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "cmt-seg", role: "group", "aria-label": "Market type", children: ["spot", "futures"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10734
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "cmt-seg", role: "group", "aria-label": copy.marketTypeGroup, children: ["spot", "futures"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10582
10735
  "button",
10583
10736
  {
10584
10737
  type: "button",
10585
10738
  className: kind === value ? "cmt-seg__btn is-active" : "cmt-seg__btn",
10586
10739
  "aria-pressed": kind === value,
10587
10740
  onClick: () => setKind(value),
10588
- children: value === "spot" ? "Spot" : "Futures"
10741
+ children: value === "spot" ? copy.spot : copy.futures
10589
10742
  },
10590
10743
  value
10591
10744
  )) }),
10592
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "cmt-tabs", role: "tablist", "aria-label": "Quote currency", children: snapshot.quotes.map((q) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10745
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "cmt-tabs", role: "tablist", "aria-label": copy.quoteCurrencyTabs, children: snapshot.quotes.map((q) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10593
10746
  "button",
10594
10747
  {
10595
10748
  type: "button",
@@ -10609,15 +10762,9 @@ var CryptoMarketsTable = ({
10609
10762
  className: ["cmt-scroll", scrolled ? "is-scrolled" : ""].filter(Boolean).join(" "),
10610
10763
  tabIndex: 0,
10611
10764
  role: "region",
10612
- "aria-label": "Market prices. Scroll horizontally to see all columns.",
10765
+ "aria-label": copy.scrollRegion,
10613
10766
  children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("table", { className: "cmt-table", children: [
10614
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("tr", { children: [
10615
- ["name", "Name"],
10616
- ["last", "Price"],
10617
- ["change1hPct", "1h %"],
10618
- ["change24hPct", "24h %"],
10619
- ["change7dPct", "7d chart"]
10620
- ].map(([key, label]) => {
10767
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("tr", { children: columnLabels.map(([key, label]) => {
10621
10768
  const active = sortKey === key;
10622
10769
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
10623
10770
  "th",
@@ -10662,7 +10809,9 @@ var CryptoMarketsTable = ({
10662
10809
  {
10663
10810
  values: row.spark7d,
10664
10811
  up: (row.change7dPct ?? 0) >= 0,
10665
- label: `${row.name} available hourly price history, up to 7 days`,
10812
+ label: fillTemplate4(copy.sparklineAriaTemplate, {
10813
+ name: row.name
10814
+ }),
10666
10815
  reducedMotion
10667
10816
  }
10668
10817
  ) })
@@ -12315,10 +12464,16 @@ var AffiliatesSlider = ({
12315
12464
  CryptoMarketsTable,
12316
12465
  CryptoTradeConverter,
12317
12466
  DEFAULT_AWARDS,
12467
+ DEFAULT_CRYPTO_MARKETS_TABLE_LABELS,
12468
+ DEFAULT_CRYPTO_MARKETS_TABLE_TITLE,
12469
+ DEFAULT_CRYPTO_TRADE_CONVERTER_LABELS,
12470
+ DEFAULT_CRYPTO_TRADE_CONVERTER_SUBTITLE,
12471
+ DEFAULT_CRYPTO_TRADE_CONVERTER_TITLE,
12318
12472
  DEFAULT_CULTURE_CARDS,
12319
12473
  DEFAULT_EXCHANGE_RATE_WS_URL,
12320
12474
  DEFAULT_SYMBOLS_ENDPOINT,
12321
12475
  DEFAULT_TRADE_HREF,
12476
+ DEFAULT_TRADING_CALCULATOR_LABELS,
12322
12477
  DayNightTransition,
12323
12478
  DocumentChips,
12324
12479
  DotLottieInView,