mark.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. "use strict";
  2. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  3. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  4. return new (P || (P = Promise))(function (resolve, reject) {
  5. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  6. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  7. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  8. step((generator = generator.apply(thisArg, _arguments || [])).next());
  9. });
  10. };
  11. var __rest = (this && this.__rest) || function (s, e) {
  12. var t = {};
  13. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  14. t[p] = s[p];
  15. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  16. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  17. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  18. t[p[i]] = s[p[i]];
  19. }
  20. return t;
  21. };
  22. Object.defineProperty(exports, "__esModule", { value: true });
  23. exports.createColumnOf = exports.initializeMark = void 0;
  24. const d3_array_1 = require("d3-array");
  25. const helper_1 = require("../utils/helper");
  26. const library_1 = require("./library");
  27. const transform_1 = require("./transform");
  28. function initializeMark(partialMark, partialProps, library) {
  29. return __awaiter(this, void 0, void 0, function* () {
  30. // Apply transform to mark to derive indices, data, encode, etc,.
  31. const context = { library };
  32. const [I, transformedMark] = yield applyMarkTransform(partialMark, partialProps, context);
  33. const { encode, scale, data, tooltip } = transformedMark;
  34. // Skip mark with non-tabular data. Do not skip empty
  35. // data, they are useful for facet to display axes.
  36. if (Array.isArray(data) === false) {
  37. return null;
  38. }
  39. // Group non-independent channels with same prefix, such as x1, x2 => x.
  40. // For independent channels, dot not group them, such as position1, position2.
  41. const { channels: channelDescriptors } = partialProps;
  42. const nameChannels = (0, d3_array_1.rollups)(Object.entries(encode).filter(([, value]) => (0, helper_1.defined)(value)), (values) => values.map(([key, options]) => (Object.assign({ name: key }, options))), ([key]) => {
  43. var _a;
  44. const prefix = (_a = /([^\d]+)\d*$/.exec(key)) === null || _a === void 0 ? void 0 : _a[1];
  45. const descriptor = channelDescriptors.find((d) => d.name === prefix);
  46. if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.independent)
  47. return key;
  48. return prefix;
  49. });
  50. // Check required channels and initialize scale options for each channel.
  51. const channels = channelDescriptors
  52. .filter((descriptor) => {
  53. const { name, required } = descriptor;
  54. if (nameChannels.find(([d]) => d === name))
  55. return true;
  56. if (required)
  57. throw new Error(`Missing encoding for channel: ${name}.`);
  58. return false;
  59. })
  60. .flatMap((descriptor) => {
  61. const { name, scale: scaleType, scaleKey, range } = descriptor;
  62. const valuesArray = nameChannels.filter(([channel]) => channel.startsWith(name));
  63. return valuesArray.map(([channel, values], i) => {
  64. const visual = values.some((d) => d.visual);
  65. const constant = values.some((d) => d.constant);
  66. const _a = scale[channel] || {}, { independent = false,
  67. // Use channel name as default scale key.
  68. key = scaleKey || channel,
  69. // Visual channel use identity scale.
  70. type = constant ? 'constant' : visual ? 'identity' : scaleType } = _a, scaleOptions = __rest(_a, ["independent", "key", "type"]);
  71. // For constant scale, infer range from data.
  72. const isConstant = type === 'constant';
  73. const finalRange = isConstant ? undefined : range;
  74. return {
  75. name: channel,
  76. values,
  77. // Generate a unique key for independent channel,
  78. // which will not group with any other channels.
  79. scaleKey: independent || isConstant ? Symbol('independent') : key,
  80. scale: Object.assign({ type, range: finalRange }, scaleOptions),
  81. };
  82. });
  83. });
  84. return [transformedMark, Object.assign(Object.assign({}, partialProps), { index: I, channels, tooltip })];
  85. });
  86. }
  87. exports.initializeMark = initializeMark;
  88. function createColumnOf(library) {
  89. const [useEncode] = (0, library_1.useLibrary)('encode', library);
  90. return (data, encode) => {
  91. if (encode === undefined)
  92. return null;
  93. if (data === undefined)
  94. return null;
  95. return Object.assign(Object.assign({}, encode), { type: 'column', value: useEncode(encode)(data), field: fieldOf(encode) });
  96. };
  97. }
  98. exports.createColumnOf = createColumnOf;
  99. function applyMarkTransform(mark, props, context) {
  100. return __awaiter(this, void 0, void 0, function* () {
  101. const { library } = context;
  102. const [useTransform] = (0, library_1.useLibrary)('transform', library);
  103. const { preInference = [], postInference = [] } = props;
  104. const { transform = [] } = mark;
  105. const transforms = [
  106. transform_1.applyDefaults,
  107. transform_1.applyDataTransform,
  108. transform_1.flatEncode,
  109. transform_1.inferChannelsType,
  110. transform_1.maybeVisualChannel,
  111. transform_1.extractColumns,
  112. transform_1.maybeArrayField,
  113. transform_1.maybeNonAnimate,
  114. transform_1.addGuideToScale,
  115. transform_1.normalizeTooltip,
  116. ...preInference.map(useTransform),
  117. ...transform.map(useTransform),
  118. ...postInference.map(useTransform),
  119. transform_1.extractTooltip,
  120. ];
  121. let index = [];
  122. let transformedMark = mark;
  123. for (const t of transforms) {
  124. [index, transformedMark] = yield t(index, transformedMark, context);
  125. }
  126. return [index, transformedMark];
  127. });
  128. }
  129. function fieldOf(encode) {
  130. const { type, value } = encode;
  131. if (type === 'field' && typeof value === 'string')
  132. return value;
  133. return null;
  134. }
  135. //# sourceMappingURL=mark.js.map