mark.js 6.4 KB

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