minerva-design 1.6.0 → 1.7.0

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.
Files changed (120) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/charts/engine/data.cjs +1 -1
  3. package/dist/charts/engine/data.cjs.map +1 -1
  4. package/dist/charts/engine/data.d.cts +2 -0
  5. package/dist/charts/engine/data.d.ts +2 -0
  6. package/dist/charts/engine/data.js +6 -4
  7. package/dist/charts/engine/data.js.map +1 -1
  8. package/dist/charts/engine/defaults.cjs +1 -1
  9. package/dist/charts/engine/defaults.cjs.map +1 -1
  10. package/dist/charts/engine/defaults.js +22 -18
  11. package/dist/charts/engine/defaults.js.map +1 -1
  12. package/dist/charts/engine/graph/chart.cjs +1 -1
  13. package/dist/charts/engine/graph/chart.cjs.map +1 -1
  14. package/dist/charts/engine/graph/chart.js +532 -493
  15. package/dist/charts/engine/graph/chart.js.map +1 -1
  16. package/dist/charts/engine/graph/geometry.cjs +1 -1
  17. package/dist/charts/engine/graph/geometry.cjs.map +1 -1
  18. package/dist/charts/engine/graph/geometry.d.cts +12 -2
  19. package/dist/charts/engine/graph/geometry.d.ts +12 -2
  20. package/dist/charts/engine/graph/geometry.js +35 -31
  21. package/dist/charts/engine/graph/geometry.js.map +1 -1
  22. package/dist/charts/engine/model.cjs +1 -1
  23. package/dist/charts/engine/model.cjs.map +1 -1
  24. package/dist/charts/engine/model.js +95 -74
  25. package/dist/charts/engine/model.js.map +1 -1
  26. package/dist/charts/engine/orderbook/field.cjs +1 -1
  27. package/dist/charts/engine/orderbook/field.cjs.map +1 -1
  28. package/dist/charts/engine/orderbook/field.d.cts +15 -2
  29. package/dist/charts/engine/orderbook/field.d.ts +15 -2
  30. package/dist/charts/engine/orderbook/field.js +21 -9
  31. package/dist/charts/engine/orderbook/field.js.map +1 -1
  32. package/dist/charts/engine/orderbook/heatmap.cjs +1 -1
  33. package/dist/charts/engine/orderbook/heatmap.cjs.map +1 -1
  34. package/dist/charts/engine/orderbook/heatmap.d.cts +29 -0
  35. package/dist/charts/engine/orderbook/heatmap.d.ts +29 -0
  36. package/dist/charts/engine/orderbook/heatmap.js +576 -453
  37. package/dist/charts/engine/orderbook/heatmap.js.map +1 -1
  38. package/dist/charts/engine/orderbook/types.d.cts +36 -11
  39. package/dist/charts/engine/orderbook/types.d.ts +36 -11
  40. package/dist/charts/engine/presets.cjs +1 -1
  41. package/dist/charts/engine/presets.cjs.map +1 -1
  42. package/dist/charts/engine/presets.d.cts +16 -3
  43. package/dist/charts/engine/presets.d.ts +16 -3
  44. package/dist/charts/engine/presets.js +42 -32
  45. package/dist/charts/engine/presets.js.map +1 -1
  46. package/dist/charts/engine/scene.cjs +1 -1
  47. package/dist/charts/engine/scene.cjs.map +1 -1
  48. package/dist/charts/engine/scene.d.cts +4 -2
  49. package/dist/charts/engine/scene.d.ts +4 -2
  50. package/dist/charts/engine/scene.js +185 -107
  51. package/dist/charts/engine/scene.js.map +1 -1
  52. package/dist/charts/engine/three-d/oit.cjs +119 -34
  53. package/dist/charts/engine/three-d/oit.cjs.map +1 -1
  54. package/dist/charts/engine/three-d/oit.d.cts +65 -10
  55. package/dist/charts/engine/three-d/oit.d.ts +65 -10
  56. package/dist/charts/engine/three-d/oit.js +119 -34
  57. package/dist/charts/engine/three-d/oit.js.map +1 -1
  58. package/dist/charts/engine/three-d/render-types.cjs.map +1 -1
  59. package/dist/charts/engine/three-d/render-types.d.cts +19 -0
  60. package/dist/charts/engine/three-d/render-types.d.ts +19 -0
  61. package/dist/charts/engine/three-d/render-types.js.map +1 -1
  62. package/dist/charts/engine/three-d/shaders.cjs +14 -6
  63. package/dist/charts/engine/three-d/shaders.cjs.map +1 -1
  64. package/dist/charts/engine/three-d/shaders.d.cts +6 -1
  65. package/dist/charts/engine/three-d/shaders.d.ts +6 -1
  66. package/dist/charts/engine/three-d/shaders.js +40 -26
  67. package/dist/charts/engine/three-d/shaders.js.map +1 -1
  68. package/dist/charts/engine/three-d/webgl.cjs +1 -1
  69. package/dist/charts/engine/three-d/webgl.cjs.map +1 -1
  70. package/dist/charts/engine/three-d/webgl.js +167 -125
  71. package/dist/charts/engine/three-d/webgl.js.map +1 -1
  72. package/dist/charts/engine/three-d/webgpu.cjs +1 -1
  73. package/dist/charts/engine/three-d/webgpu.cjs.map +1 -1
  74. package/dist/charts/engine/three-d/webgpu.js +169 -140
  75. package/dist/charts/engine/three-d/webgpu.js.map +1 -1
  76. package/dist/charts/engine/trading/chart.cjs +1 -1
  77. package/dist/charts/engine/trading/chart.cjs.map +1 -1
  78. package/dist/charts/engine/trading/chart.js +1149 -1023
  79. package/dist/charts/engine/trading/chart.js.map +1 -1
  80. package/dist/charts/engine/trading/labels.cjs +1 -1
  81. package/dist/charts/engine/trading/labels.cjs.map +1 -1
  82. package/dist/charts/engine/trading/labels.js +12 -0
  83. package/dist/charts/engine/trading/labels.js.map +1 -1
  84. package/dist/charts/engine/trading/layout.cjs +2 -0
  85. package/dist/charts/engine/trading/layout.cjs.map +1 -0
  86. package/dist/charts/engine/trading/layout.d.cts +37 -0
  87. package/dist/charts/engine/trading/layout.d.ts +37 -0
  88. package/dist/charts/engine/trading/layout.js +63 -0
  89. package/dist/charts/engine/trading/layout.js.map +1 -0
  90. package/dist/charts/engine/trading/types.d.cts +24 -7
  91. package/dist/charts/engine/trading/types.d.ts +24 -7
  92. package/dist/charts/engine/types.d.cts +21 -8
  93. package/dist/charts/engine/types.d.ts +21 -8
  94. package/dist/core/contracts.cjs +1 -1
  95. package/dist/core/contracts.cjs.map +1 -1
  96. package/dist/core/contracts.js +1 -1
  97. package/dist/core/contracts.js.map +1 -1
  98. package/dist/native/charts/src/engine/data.cjs +1 -1
  99. package/dist/native/charts/src/engine/data.cjs.map +1 -1
  100. package/dist/native/charts/src/engine/data.js +6 -4
  101. package/dist/native/charts/src/engine/data.js.map +1 -1
  102. package/dist/native/charts/src/engine/model.cjs +1 -1
  103. package/dist/native/charts/src/engine/model.cjs.map +1 -1
  104. package/dist/native/charts/src/engine/model.js +104 -83
  105. package/dist/native/charts/src/engine/model.js.map +1 -1
  106. package/dist/native/charts/src/engine/presets.cjs +1 -1
  107. package/dist/native/charts/src/engine/presets.cjs.map +1 -1
  108. package/dist/native/charts/src/engine/presets.js +42 -32
  109. package/dist/native/charts/src/engine/presets.js.map +1 -1
  110. package/dist/native/charts/src/engine/scene.cjs +1 -1
  111. package/dist/native/charts/src/engine/scene.cjs.map +1 -1
  112. package/dist/native/charts/src/engine/scene.js +185 -107
  113. package/dist/native/charts/src/engine/scene.js.map +1 -1
  114. package/dist/taro/index.js +1263 -1152
  115. package/dist/vue/components/Chart/OrderBookHeatmap.vue.d.ts +11 -0
  116. package/dist/vue/components/Chart/orderbook.d.ts +7 -0
  117. package/dist/vue/components/Chart/orderbook.js +2 -0
  118. package/dist/vue/components/Chart/orderbook.js.map +1 -1
  119. package/dist/weapp/charts/canvas.js +234 -58
  120. package/package.json +1 -1
@@ -12,6 +12,11 @@ declare const __VLS_export: import('vue').DefineComponent<import('vue').ExtractP
12
12
  colorScale: import('vue').PropType<import('../../../charts/core.js').OrderBookHeatmapScale>;
13
13
  contrast: NumberConstructor;
14
14
  maxSize: NumberConstructor;
15
+ sizeUnit: StringConstructor;
16
+ legend: {
17
+ readonly type: BooleanConstructor;
18
+ readonly default: undefined;
19
+ };
15
20
  colors: import('vue').PropType<readonly string[]>;
16
21
  bubbles: {
17
22
  readonly type: BooleanConstructor;
@@ -71,6 +76,11 @@ declare const __VLS_export: import('vue').DefineComponent<import('vue').ExtractP
71
76
  colorScale: import('vue').PropType<import('../../../charts/core.js').OrderBookHeatmapScale>;
72
77
  contrast: NumberConstructor;
73
78
  maxSize: NumberConstructor;
79
+ sizeUnit: StringConstructor;
80
+ legend: {
81
+ readonly type: BooleanConstructor;
82
+ readonly default: undefined;
83
+ };
74
84
  colors: import('vue').PropType<readonly string[]>;
75
85
  bubbles: {
76
86
  readonly type: BooleanConstructor;
@@ -120,6 +130,7 @@ declare const __VLS_export: import('vue').DefineComponent<import('vue').ExtractP
120
130
  onFollowChange?: ((follow: boolean) => any) | undefined;
121
131
  }>, {
122
132
  tooltip: boolean;
133
+ legend: boolean;
123
134
  bubbles: boolean;
124
135
  interactive: boolean;
125
136
  deep: boolean;
@@ -196,6 +196,13 @@ export declare const orderBookHeatmapProps: {
196
196
  contrast: NumberConstructor;
197
197
  /** Size drawn with the last color; follows the data by default */
198
198
  maxSize: NumberConstructor;
199
+ /** Unit after the sizes of the legend and tooltip, e.g. "BTC" */
200
+ sizeUnit: StringConstructor;
201
+ /** Color legend with its size range at the top left (default `true`) */
202
+ legend: {
203
+ readonly type: BooleanConstructor;
204
+ readonly default: undefined;
205
+ };
199
206
  /** Colors from no liquidity to `maxSize` (any CSS colors) */
200
207
  colors: PropType<readonly string[]>;
201
208
  /** Trades as bubbles (default `true`) */
@@ -72,6 +72,8 @@ var a = {
72
72
  colorScale: String,
73
73
  contrast: Number,
74
74
  maxSize: Number,
75
+ sizeUnit: String,
76
+ legend: a,
75
77
  colors: Array,
76
78
  bubbles: a,
77
79
  bubbleSize: Number,
@@ -1 +1 @@
1
- {"version":3,"file":"orderbook.js","names":["optionalBoolean","commonProps","chartFrameProps","depthChartProps","orderBookProps","orderBookHeatmapProps","timeAndSalesProps","STREAMED","useBookWidget","previous","feed","list","raw","props","before","trades","n","engine","useChartEngine","factory","definedOptions","instance","bind","watch","book"],"sources":["../../../../../vue/src/components/Chart/orderbook.ts"],"sourcesContent":["import { watch, type PropType } from \"vue\";\nimport type {\n ChartRendererPreference,\n ChartTimeZone,\n DepthChartLabels,\n DepthChartPriceLine,\n OrderBookColorConvention,\n OrderBookDelta,\n OrderBookHeatmapLabels,\n OrderBookHeatmapScale,\n OrderBookLabels,\n OrderBookMode,\n OrderBookSnapshot,\n TimeAndSalesColumn,\n TimeAndSalesLabels,\n} from \"minerva-design/charts/core\";\nimport { raw, useChartEngine, type EngineInstance } from \"./engine\";\nimport { chartFrameProps } from \"./props\";\nimport { definedOptions } from \"./trading\";\nimport type { ChartTrades } from \"./types\";\n\nconst optionalBoolean = { type: Boolean, default: undefined } as const;\n\n/** Options shared by the order book components */\nconst commonProps = {\n ...chartFrameProps,\n /** Color of the bids / buys (any CSS color); from `colorConvention` by default */\n upColor: String,\n /** Color of the asks / sells */\n downColor: String,\n /** `red-up` swaps the default colors (default `green-up`) */\n colorConvention: String as PropType<OrderBookColorConvention>,\n /** Decimals of the prices; detected from the data by default */\n pricePrecision: Number,\n /** Decimals of the sizes; detected from the data by default */\n sizePrecision: Number,\n /** Locale of the numbers and texts (`\"zh-CN\"`); the page language by default */\n locale: String,\n /** Formats the prices; overrides `pricePrecision` */\n formatPrice: Function as PropType<(price: number) => string>,\n /** Formats the sizes; overrides `sizePrecision` */\n formatSize: Function as PropType<(size: number) => string>,\n /** Font family of the texts (default: the theme font) */\n fontFamily: String,\n /** Font size of the texts, in pixels (default 12) */\n fontSize: Number,\n /** Accessible label */\n ariaLabel: String,\n};\n\n/** Props of DepthChart */\nexport const depthChartProps = {\n ...commonProps,\n /** Book to draw, applied when the object changes (stream updates through the handle's `applyDeltas`) */\n book: Object as PropType<OrderBookSnapshot>,\n /** Visible range on each side of the mid price, as a fraction of the mid; fits the book by default */\n range: Number,\n /** Smallest and largest `range` reachable by zooming (default `[0.0005, 0.5]`) */\n rangeLimits: Array as unknown as PropType<readonly [number, number]>,\n /** Zoom around the mid with the wheel / pinch (default `true`) */\n zoomable: optionalBoolean,\n /** Stepped or straight curves (default `step`) */\n curve: String as PropType<\"step\" | \"linear\">,\n /** Cumulative amount in the base asset or the quote notional (default `base`) */\n amount: String as PropType<\"base\" | \"quote\">,\n /** Eased transitions between books (default `true`) */\n animate: optionalBoolean,\n /** Opacity of the areas, 0-1 (default 0.28) */\n fillOpacity: Number,\n /** Line and label at the mid price (default `true`) */\n midLine: optionalBoolean,\n /** Legend with the spread (default `true`) */\n legend: optionalBoolean,\n /** Grid lines (default `true`) */\n grid: optionalBoolean,\n /** Price and amount axes (default `true`) */\n axes: optionalBoolean,\n /** Hover readout (default `true`) */\n tooltip: optionalBoolean,\n /** Mirrored readout on the other side (default `true`) */\n mirror: optionalBoolean,\n /** Reference lines at prices (an order, a liquidation) */\n priceLines: Array as PropType<readonly DepthChartPriceLine[]>,\n /** Overrides of the built-in texts of the `locale` */\n labels: Object as PropType<Partial<DepthChartLabels>>,\n};\n\n/** Props of OrderBook */\nexport const orderBookProps = {\n ...commonProps,\n /** Book to draw, applied when the object changes (stream updates through the handle's `applyDeltas`) */\n book: Object as PropType<OrderBookSnapshot>,\n /** Price of the spread row, colored by its last move; the mid price when omitted */\n lastPrice: { type: Number as PropType<number | null>, default: undefined },\n /** Sides shown (default `both`) */\n mode: String as PropType<OrderBookMode>,\n /** Price step the levels are grouped by (default 0: none) */\n grouping: Number,\n /** Rows per side; fills the height by default */\n rows: Number,\n /** Height of a row, in pixels (default 20) */\n rowHeight: Number,\n /** Depth bars behind the rows (default `cumulative`) */\n depthBars: String as PropType<\"cumulative\" | \"level\" | \"none\">,\n /** Total column in the base asset or the quote notional (default `base`) */\n total: String as PropType<\"base\" | \"quote\">,\n /** Columns, in order (default `[\"price\", \"size\", \"total\"]`) */\n columns: Array as PropType<readonly (\"price\" | \"size\" | \"total\")[]>,\n /** Flashes the changed sizes (default `true`) */\n flash: optionalBoolean,\n /** Duration of a flash, in ms (default 450) */\n flashDuration: Number,\n /** Highlights the levels at or above this size */\n largeOrderThreshold: Number,\n /** Column headers (default `true`) */\n header: optionalBoolean,\n /** Spread row between the sides (default `true`) */\n spreadRow: optionalBoolean,\n /** Bid / ask imbalance bar (default `true`) */\n imbalance: optionalBoolean,\n /** Hover summary of the cumulative levels (default `true`) */\n tooltip: optionalBoolean,\n /** Overrides of the built-in texts of the `locale` */\n labels: Object as PropType<Partial<OrderBookLabels>>,\n};\n\n/** Props of OrderBookHeatmap */\nexport const orderBookHeatmapProps = {\n ...commonProps,\n /** Book, applied when the object changes (stream updates through the handle's `applyDeltas`) */\n book: Object as PropType<OrderBookSnapshot>,\n /** Trades; when the array grows, only the appended ones are added */\n trades: Array as PropType<ChartTrades>,\n /** Price step of the rows; detected from the book by default */\n tickSize: Number,\n /** Duration of a column, in ms (default 100) */\n interval: Number,\n /** Time shown, in ms (default 60000) */\n window: Number,\n /** Time kept for panning back, in ms (default 300000) */\n history: Number,\n /** Price levels kept on each side (default 160) */\n depth: Number,\n /** Price range shown around the mid; from `depth` by default */\n priceSpan: Number,\n /** Scale of the sizes to the colors (default `log`) */\n colorScale: String as PropType<OrderBookHeatmapScale>,\n /** Contrast of the colors (default 1) */\n contrast: Number,\n /** Size drawn with the last color; follows the data by default */\n maxSize: Number,\n /** Colors from no liquidity to `maxSize` (any CSS colors) */\n colors: Array as PropType<readonly string[]>,\n /** Trades as bubbles (default `true`) */\n bubbles: optionalBoolean,\n /** Diameter of the largest bubble, in pixels (default 28) */\n bubbleSize: Number,\n /** Trade volume of the largest bubble; follows the data by default */\n bubbleVolume: Number,\n /** Best bid / ask lines (default `true`) */\n bestLines: optionalBoolean,\n /** Size profile of the current book at the right (default `true`) */\n profile: optionalBoolean,\n /** Zoom and pan (default `true`) */\n interactive: optionalBoolean,\n /** Hover readout (default `true`) */\n tooltip: optionalBoolean,\n /** Backend: WebGPU, then WebGL2, WebGL, Canvas2D (default `auto`) */\n renderer: String as PropType<ChartRendererPreference>,\n /** Clock of the time axis and the tooltip: the local time or UTC, the clock of most exchanges (default `local`) */\n timeZone: String as PropType<ChartTimeZone>,\n /** Overrides of the built-in texts of the `locale` */\n labels: Object as PropType<Partial<OrderBookHeatmapLabels>>,\n};\n\n/** Props of TimeAndSales */\nexport const timeAndSalesProps = {\n ...commonProps,\n /** Trades, oldest first; when the array grows, only the appended ones are added (other changes replace the tape) */\n trades: Array as PropType<ChartTrades>,\n /** Trades kept (default 200000) */\n capacity: Number,\n /** Height of a row, in pixels (default 20) */\n rowHeight: Number,\n /** Columns, in order (default `[\"time\", \"price\", \"size\"]`) */\n columns: Array as PropType<readonly TimeAndSalesColumn[]>,\n /** Hides the trades below this size (default 0) */\n minSize: Number,\n /** Highlights the trades at or above this size */\n largeTradeThreshold: Number,\n /** Merges the consecutive trades of the same side and price (default `false`) */\n aggregate: optionalBoolean,\n /** Price color: the side of the trade or the tick direction (default `side`) */\n priceColor: String as PropType<\"side\" | \"tick\">,\n /** Pauses the tape while hovered (default `true`) */\n pauseOnHover: optionalBoolean,\n /** Slides the new rows in (default `true`) */\n animate: optionalBoolean,\n /** Column headers (default `true`) */\n header: optionalBoolean,\n /** Milliseconds in the times (default `true`) */\n milliseconds: optionalBoolean,\n /** Clock of the default time format: the local time or UTC, the clock of most exchanges (default `local`) */\n timeZone: String as PropType<ChartTimeZone>,\n /** Formats the times */\n formatTime: Function as PropType<(time: number) => string>,\n /** Overrides of the built-in texts of the `locale` */\n labels: Object as PropType<Partial<TimeAndSalesLabels>>,\n};\n\n/** Props passed through engine methods rather than the options */\nconst STREAMED = [\"book\", \"trades\", \"lastPrice\"];\n\ninterface Widget<O> extends EngineInstance<O> {\n setBook?(snapshot: OrderBookSnapshot): void;\n applyDeltas?(deltas: OrderBookDelta | readonly OrderBookDelta[]): void;\n}\n\n/**\n * Mounts an order book engine: the options are every set prop but the\n * streamed ones; `book` goes through `setBook` when the object changes,\n * `trades` through `add` (the appended trades) / `replace` (any other\n * change)\n */\nexport function useBookWidget<O, I extends Widget<O>>(\n factory: (container: HTMLElement, options: O) => I,\n props: Record<string, unknown> & {\n book?: OrderBookSnapshot;\n trades?: ChartTrades;\n deep?: boolean;\n },\n bind: (engine: I) => Array<() => void>,\n trades?: {\n add: (engine: I, trades: ChartTrades) => void;\n replace: (engine: I, trades: ChartTrades) => void;\n },\n) {\n let previous: ChartTrades | undefined;\n const feed = (engine: I) => {\n const list = raw(props.trades);\n const before = previous;\n previous = list;\n if (!trades || !list || list === before) return;\n const n = before?.length ?? 0;\n if (\n before &&\n n > 0 &&\n list.length >= n &&\n list[0] === before[0] &&\n list[n - 1] === before[n - 1]\n ) {\n if (list.length > n) trades.add(engine, list.slice(n));\n return;\n }\n trades.replace(engine, list);\n };\n const engine = useChartEngine<O, I>(\n factory,\n props,\n () => definedOptions<O>(props, STREAMED),\n (instance) => {\n previous = undefined;\n if (props.book) instance.setBook?.(raw(props.book));\n feed(instance);\n return bind(instance);\n },\n () => definedOptions(props, STREAMED),\n );\n watch(\n () => props.book,\n (book) => {\n if (book) engine.instance.value?.setBook?.(raw(book));\n },\n );\n watch(\n () => props.trades,\n () => {\n if (engine.instance.value) feed(engine.instance.value);\n },\n );\n return engine;\n}\n"],"mappings":";;;;;AAqBA,IAAMA,IAAkB;CAAE,MAAM;CAAS,SAAS,KAAA;AAAU,GAGtDC,IAAc;CAClB,GAAGC;CAEH,SAAS;CAET,WAAW;CAEX,iBAAiB;CAEjB,gBAAgB;CAEhB,eAAe;CAEf,QAAQ;CAER,aAAa;CAEb,YAAY;CAEZ,YAAY;CAEZ,UAAU;CAEV,WAAW;AACb,GAGaC,IAAkB;CAC7B,GAAGF;CAEH,MAAM;CAEN,OAAO;CAEP,aAAa;CAEb,UAAUD;CAEV,OAAO;CAEP,QAAQ;CAER,SAASA;CAET,aAAa;CAEb,SAASA;CAET,QAAQA;CAER,MAAMA;CAEN,MAAMA;CAEN,SAASA;CAET,QAAQA;CAER,YAAY;CAEZ,QAAQ;AACV,GAGaI,IAAiB;CAC5B,GAAGH;CAEH,MAAM;CAEN,WAAW;EAAE,MAAM;EAAmC,SAAS,KAAA;CAAU;CAEzE,MAAM;CAEN,UAAU;CAEV,MAAM;CAEN,WAAW;CAEX,WAAW;CAEX,OAAO;CAEP,SAAS;CAET,OAAOD;CAEP,eAAe;CAEf,qBAAqB;CAErB,QAAQA;CAER,WAAWA;CAEX,WAAWA;CAEX,SAASA;CAET,QAAQ;AACV,GAGaK,IAAwB;CACnC,GAAGJ;CAEH,MAAM;CAEN,QAAQ;CAER,UAAU;CAEV,UAAU;CAEV,QAAQ;CAER,SAAS;CAET,OAAO;CAEP,WAAW;CAEX,YAAY;CAEZ,UAAU;CAEV,SAAS;CAET,QAAQ;CAER,SAASD;CAET,YAAY;CAEZ,cAAc;CAEd,WAAWA;CAEX,SAASA;CAET,aAAaA;CAEb,SAASA;CAET,UAAU;CAEV,UAAU;CAEV,QAAQ;AACV,GAGaM,IAAoB;CAC/B,GAAGL;CAEH,QAAQ;CAER,UAAU;CAEV,WAAW;CAEX,SAAS;CAET,SAAS;CAET,qBAAqB;CAErB,WAAWD;CAEX,YAAY;CAEZ,cAAcA;CAEd,SAASA;CAET,QAAQA;CAER,cAAcA;CAEd,UAAU;CAEV,YAAY;CAEZ,QAAQ;AACV,GAGMO,IAAW;CAAC;CAAQ;CAAU;AAAW;AAa/C,SAAgBC,EACd,GACA,GAKA,GACA,GAIA;CACA,IAAIC,GACEC,KAAQ,MAAc;EAC1B,IAAMC,IAAOC,EAAIC,EAAM,MAAM,GACvBC,IAASL;EAEf,IADA,IAAWE,GACP,CAACI,KAAU,CAACJ,KAAQA,MAASG,GAAQ;EACzC,IAAME,IAAIF,GAAQ,UAAU;EAC5B,IACEA,KACAE,IAAI,KACJL,EAAK,UAAUK,KACfL,EAAK,OAAOG,EAAO,MACnBH,EAAKK,IAAI,OAAOF,EAAOE,IAAI,IAC3B;GACA,AAAIL,EAAK,SAASK,KAAGD,EAAO,IAAIE,GAAQN,EAAK,MAAMK,CAAC,CAAC;GACrD;EACF;EACA,EAAO,QAAQC,GAAQN,CAAI;CAC7B,GACMM,IAASC,EACbC,GACAN,SACMO,EAAkBP,GAAON,CAAQ,IACtC,OACC,IAAW,KAAA,GACPM,EAAM,QAAMQ,EAAS,UAAUT,EAAIC,EAAM,IAAI,CAAC,GAClDH,EAAKW,CAAQ,GACNC,EAAKD,CAAQ,UAEhBD,EAAeP,GAAON,CAAQ,CACtC;CAaA,OAZAgB,QACQV,EAAM,OACX,MAAS;EACR,AAAIW,KAAMP,EAAO,SAAS,OAAO,UAAUL,EAAIY,CAAI,CAAC;CACtD,CACF,GACAD,QACQV,EAAM,cACN;EACJ,AAAII,EAAO,SAAS,SAAOP,EAAKO,EAAO,SAAS,KAAK;CACvD,CACF,GACOA;AACT"}
1
+ {"version":3,"file":"orderbook.js","names":["optionalBoolean","commonProps","chartFrameProps","depthChartProps","orderBookProps","orderBookHeatmapProps","timeAndSalesProps","STREAMED","useBookWidget","previous","feed","list","raw","props","before","trades","n","engine","useChartEngine","factory","definedOptions","instance","bind","watch","book"],"sources":["../../../../../vue/src/components/Chart/orderbook.ts"],"sourcesContent":["import { watch, type PropType } from \"vue\";\nimport type {\n ChartRendererPreference,\n ChartTimeZone,\n DepthChartLabels,\n DepthChartPriceLine,\n OrderBookColorConvention,\n OrderBookDelta,\n OrderBookHeatmapLabels,\n OrderBookHeatmapScale,\n OrderBookLabels,\n OrderBookMode,\n OrderBookSnapshot,\n TimeAndSalesColumn,\n TimeAndSalesLabels,\n} from \"minerva-design/charts/core\";\nimport { raw, useChartEngine, type EngineInstance } from \"./engine\";\nimport { chartFrameProps } from \"./props\";\nimport { definedOptions } from \"./trading\";\nimport type { ChartTrades } from \"./types\";\n\nconst optionalBoolean = { type: Boolean, default: undefined } as const;\n\n/** Options shared by the order book components */\nconst commonProps = {\n ...chartFrameProps,\n /** Color of the bids / buys (any CSS color); from `colorConvention` by default */\n upColor: String,\n /** Color of the asks / sells */\n downColor: String,\n /** `red-up` swaps the default colors (default `green-up`) */\n colorConvention: String as PropType<OrderBookColorConvention>,\n /** Decimals of the prices; detected from the data by default */\n pricePrecision: Number,\n /** Decimals of the sizes; detected from the data by default */\n sizePrecision: Number,\n /** Locale of the numbers and texts (`\"zh-CN\"`); the page language by default */\n locale: String,\n /** Formats the prices; overrides `pricePrecision` */\n formatPrice: Function as PropType<(price: number) => string>,\n /** Formats the sizes; overrides `sizePrecision` */\n formatSize: Function as PropType<(size: number) => string>,\n /** Font family of the texts (default: the theme font) */\n fontFamily: String,\n /** Font size of the texts, in pixels (default 12) */\n fontSize: Number,\n /** Accessible label */\n ariaLabel: String,\n};\n\n/** Props of DepthChart */\nexport const depthChartProps = {\n ...commonProps,\n /** Book to draw, applied when the object changes (stream updates through the handle's `applyDeltas`) */\n book: Object as PropType<OrderBookSnapshot>,\n /** Visible range on each side of the mid price, as a fraction of the mid; fits the book by default */\n range: Number,\n /** Smallest and largest `range` reachable by zooming (default `[0.0005, 0.5]`) */\n rangeLimits: Array as unknown as PropType<readonly [number, number]>,\n /** Zoom around the mid with the wheel / pinch (default `true`) */\n zoomable: optionalBoolean,\n /** Stepped or straight curves (default `step`) */\n curve: String as PropType<\"step\" | \"linear\">,\n /** Cumulative amount in the base asset or the quote notional (default `base`) */\n amount: String as PropType<\"base\" | \"quote\">,\n /** Eased transitions between books (default `true`) */\n animate: optionalBoolean,\n /** Opacity of the areas, 0-1 (default 0.28) */\n fillOpacity: Number,\n /** Line and label at the mid price (default `true`) */\n midLine: optionalBoolean,\n /** Legend with the spread (default `true`) */\n legend: optionalBoolean,\n /** Grid lines (default `true`) */\n grid: optionalBoolean,\n /** Price and amount axes (default `true`) */\n axes: optionalBoolean,\n /** Hover readout (default `true`) */\n tooltip: optionalBoolean,\n /** Mirrored readout on the other side (default `true`) */\n mirror: optionalBoolean,\n /** Reference lines at prices (an order, a liquidation) */\n priceLines: Array as PropType<readonly DepthChartPriceLine[]>,\n /** Overrides of the built-in texts of the `locale` */\n labels: Object as PropType<Partial<DepthChartLabels>>,\n};\n\n/** Props of OrderBook */\nexport const orderBookProps = {\n ...commonProps,\n /** Book to draw, applied when the object changes (stream updates through the handle's `applyDeltas`) */\n book: Object as PropType<OrderBookSnapshot>,\n /** Price of the spread row, colored by its last move; the mid price when omitted */\n lastPrice: { type: Number as PropType<number | null>, default: undefined },\n /** Sides shown (default `both`) */\n mode: String as PropType<OrderBookMode>,\n /** Price step the levels are grouped by (default 0: none) */\n grouping: Number,\n /** Rows per side; fills the height by default */\n rows: Number,\n /** Height of a row, in pixels (default 20) */\n rowHeight: Number,\n /** Depth bars behind the rows (default `cumulative`) */\n depthBars: String as PropType<\"cumulative\" | \"level\" | \"none\">,\n /** Total column in the base asset or the quote notional (default `base`) */\n total: String as PropType<\"base\" | \"quote\">,\n /** Columns, in order (default `[\"price\", \"size\", \"total\"]`) */\n columns: Array as PropType<readonly (\"price\" | \"size\" | \"total\")[]>,\n /** Flashes the changed sizes (default `true`) */\n flash: optionalBoolean,\n /** Duration of a flash, in ms (default 450) */\n flashDuration: Number,\n /** Highlights the levels at or above this size */\n largeOrderThreshold: Number,\n /** Column headers (default `true`) */\n header: optionalBoolean,\n /** Spread row between the sides (default `true`) */\n spreadRow: optionalBoolean,\n /** Bid / ask imbalance bar (default `true`) */\n imbalance: optionalBoolean,\n /** Hover summary of the cumulative levels (default `true`) */\n tooltip: optionalBoolean,\n /** Overrides of the built-in texts of the `locale` */\n labels: Object as PropType<Partial<OrderBookLabels>>,\n};\n\n/** Props of OrderBookHeatmap */\nexport const orderBookHeatmapProps = {\n ...commonProps,\n /** Book, applied when the object changes (stream updates through the handle's `applyDeltas`) */\n book: Object as PropType<OrderBookSnapshot>,\n /** Trades; when the array grows, only the appended ones are added */\n trades: Array as PropType<ChartTrades>,\n /** Price step of the rows; detected from the book by default */\n tickSize: Number,\n /** Duration of a column, in ms (default 100) */\n interval: Number,\n /** Time shown, in ms (default 60000) */\n window: Number,\n /** Time kept for panning back, in ms (default 300000) */\n history: Number,\n /** Price levels kept on each side (default 160) */\n depth: Number,\n /** Price range shown around the mid; from `depth` by default */\n priceSpan: Number,\n /** Scale of the sizes to the colors (default `log`) */\n colorScale: String as PropType<OrderBookHeatmapScale>,\n /** Contrast of the colors (default 1) */\n contrast: Number,\n /** Size drawn with the last color; follows the data by default */\n maxSize: Number,\n /** Unit after the sizes of the legend and tooltip, e.g. \"BTC\" */\n sizeUnit: String,\n /** Color legend with its size range at the top left (default `true`) */\n legend: optionalBoolean,\n /** Colors from no liquidity to `maxSize` (any CSS colors) */\n colors: Array as PropType<readonly string[]>,\n /** Trades as bubbles (default `true`) */\n bubbles: optionalBoolean,\n /** Diameter of the largest bubble, in pixels (default 28) */\n bubbleSize: Number,\n /** Trade volume of the largest bubble; follows the data by default */\n bubbleVolume: Number,\n /** Best bid / ask lines (default `true`) */\n bestLines: optionalBoolean,\n /** Size profile of the current book at the right (default `true`) */\n profile: optionalBoolean,\n /** Zoom and pan (default `true`) */\n interactive: optionalBoolean,\n /** Hover readout (default `true`) */\n tooltip: optionalBoolean,\n /** Backend: WebGPU, then WebGL2, WebGL, Canvas2D (default `auto`) */\n renderer: String as PropType<ChartRendererPreference>,\n /** Clock of the time axis and the tooltip: the local time or UTC, the clock of most exchanges (default `local`) */\n timeZone: String as PropType<ChartTimeZone>,\n /** Overrides of the built-in texts of the `locale` */\n labels: Object as PropType<Partial<OrderBookHeatmapLabels>>,\n};\n\n/** Props of TimeAndSales */\nexport const timeAndSalesProps = {\n ...commonProps,\n /** Trades, oldest first; when the array grows, only the appended ones are added (other changes replace the tape) */\n trades: Array as PropType<ChartTrades>,\n /** Trades kept (default 200000) */\n capacity: Number,\n /** Height of a row, in pixels (default 20) */\n rowHeight: Number,\n /** Columns, in order (default `[\"time\", \"price\", \"size\"]`) */\n columns: Array as PropType<readonly TimeAndSalesColumn[]>,\n /** Hides the trades below this size (default 0) */\n minSize: Number,\n /** Highlights the trades at or above this size */\n largeTradeThreshold: Number,\n /** Merges the consecutive trades of the same side and price (default `false`) */\n aggregate: optionalBoolean,\n /** Price color: the side of the trade or the tick direction (default `side`) */\n priceColor: String as PropType<\"side\" | \"tick\">,\n /** Pauses the tape while hovered (default `true`) */\n pauseOnHover: optionalBoolean,\n /** Slides the new rows in (default `true`) */\n animate: optionalBoolean,\n /** Column headers (default `true`) */\n header: optionalBoolean,\n /** Milliseconds in the times (default `true`) */\n milliseconds: optionalBoolean,\n /** Clock of the default time format: the local time or UTC, the clock of most exchanges (default `local`) */\n timeZone: String as PropType<ChartTimeZone>,\n /** Formats the times */\n formatTime: Function as PropType<(time: number) => string>,\n /** Overrides of the built-in texts of the `locale` */\n labels: Object as PropType<Partial<TimeAndSalesLabels>>,\n};\n\n/** Props passed through engine methods rather than the options */\nconst STREAMED = [\"book\", \"trades\", \"lastPrice\"];\n\ninterface Widget<O> extends EngineInstance<O> {\n setBook?(snapshot: OrderBookSnapshot): void;\n applyDeltas?(deltas: OrderBookDelta | readonly OrderBookDelta[]): void;\n}\n\n/**\n * Mounts an order book engine: the options are every set prop but the\n * streamed ones; `book` goes through `setBook` when the object changes,\n * `trades` through `add` (the appended trades) / `replace` (any other\n * change)\n */\nexport function useBookWidget<O, I extends Widget<O>>(\n factory: (container: HTMLElement, options: O) => I,\n props: Record<string, unknown> & {\n book?: OrderBookSnapshot;\n trades?: ChartTrades;\n deep?: boolean;\n },\n bind: (engine: I) => Array<() => void>,\n trades?: {\n add: (engine: I, trades: ChartTrades) => void;\n replace: (engine: I, trades: ChartTrades) => void;\n },\n) {\n let previous: ChartTrades | undefined;\n const feed = (engine: I) => {\n const list = raw(props.trades);\n const before = previous;\n previous = list;\n if (!trades || !list || list === before) return;\n const n = before?.length ?? 0;\n if (\n before &&\n n > 0 &&\n list.length >= n &&\n list[0] === before[0] &&\n list[n - 1] === before[n - 1]\n ) {\n if (list.length > n) trades.add(engine, list.slice(n));\n return;\n }\n trades.replace(engine, list);\n };\n const engine = useChartEngine<O, I>(\n factory,\n props,\n () => definedOptions<O>(props, STREAMED),\n (instance) => {\n previous = undefined;\n if (props.book) instance.setBook?.(raw(props.book));\n feed(instance);\n return bind(instance);\n },\n () => definedOptions(props, STREAMED),\n );\n watch(\n () => props.book,\n (book) => {\n if (book) engine.instance.value?.setBook?.(raw(book));\n },\n );\n watch(\n () => props.trades,\n () => {\n if (engine.instance.value) feed(engine.instance.value);\n },\n );\n return engine;\n}\n"],"mappings":";;;;;AAqBA,IAAMA,IAAkB;CAAE,MAAM;CAAS,SAAS,KAAA;AAAU,GAGtDC,IAAc;CAClB,GAAGC;CAEH,SAAS;CAET,WAAW;CAEX,iBAAiB;CAEjB,gBAAgB;CAEhB,eAAe;CAEf,QAAQ;CAER,aAAa;CAEb,YAAY;CAEZ,YAAY;CAEZ,UAAU;CAEV,WAAW;AACb,GAGaC,IAAkB;CAC7B,GAAGF;CAEH,MAAM;CAEN,OAAO;CAEP,aAAa;CAEb,UAAUD;CAEV,OAAO;CAEP,QAAQ;CAER,SAASA;CAET,aAAa;CAEb,SAASA;CAET,QAAQA;CAER,MAAMA;CAEN,MAAMA;CAEN,SAASA;CAET,QAAQA;CAER,YAAY;CAEZ,QAAQ;AACV,GAGaI,IAAiB;CAC5B,GAAGH;CAEH,MAAM;CAEN,WAAW;EAAE,MAAM;EAAmC,SAAS,KAAA;CAAU;CAEzE,MAAM;CAEN,UAAU;CAEV,MAAM;CAEN,WAAW;CAEX,WAAW;CAEX,OAAO;CAEP,SAAS;CAET,OAAOD;CAEP,eAAe;CAEf,qBAAqB;CAErB,QAAQA;CAER,WAAWA;CAEX,WAAWA;CAEX,SAASA;CAET,QAAQ;AACV,GAGaK,IAAwB;CACnC,GAAGJ;CAEH,MAAM;CAEN,QAAQ;CAER,UAAU;CAEV,UAAU;CAEV,QAAQ;CAER,SAAS;CAET,OAAO;CAEP,WAAW;CAEX,YAAY;CAEZ,UAAU;CAEV,SAAS;CAET,UAAU;CAEV,QAAQD;CAER,QAAQ;CAER,SAASA;CAET,YAAY;CAEZ,cAAc;CAEd,WAAWA;CAEX,SAASA;CAET,aAAaA;CAEb,SAASA;CAET,UAAU;CAEV,UAAU;CAEV,QAAQ;AACV,GAGaM,IAAoB;CAC/B,GAAGL;CAEH,QAAQ;CAER,UAAU;CAEV,WAAW;CAEX,SAAS;CAET,SAAS;CAET,qBAAqB;CAErB,WAAWD;CAEX,YAAY;CAEZ,cAAcA;CAEd,SAASA;CAET,QAAQA;CAER,cAAcA;CAEd,UAAU;CAEV,YAAY;CAEZ,QAAQ;AACV,GAGMO,IAAW;CAAC;CAAQ;CAAU;AAAW;AAa/C,SAAgBC,EACd,GACA,GAKA,GACA,GAIA;CACA,IAAIC,GACEC,KAAQ,MAAc;EAC1B,IAAMC,IAAOC,EAAIC,EAAM,MAAM,GACvBC,IAASL;EAEf,IADA,IAAWE,GACP,CAACI,KAAU,CAACJ,KAAQA,MAASG,GAAQ;EACzC,IAAME,IAAIF,GAAQ,UAAU;EAC5B,IACEA,KACAE,IAAI,KACJL,EAAK,UAAUK,KACfL,EAAK,OAAOG,EAAO,MACnBH,EAAKK,IAAI,OAAOF,EAAOE,IAAI,IAC3B;GACA,AAAIL,EAAK,SAASK,KAAGD,EAAO,IAAIE,GAAQN,EAAK,MAAMK,CAAC,CAAC;GACrD;EACF;EACA,EAAO,QAAQC,GAAQN,CAAI;CAC7B,GACMM,IAASC,EACbC,GACAN,SACMO,EAAkBP,GAAON,CAAQ,IACtC,OACC,IAAW,KAAA,GACPM,EAAM,QAAMQ,EAAS,UAAUT,EAAIC,EAAM,IAAI,CAAC,GAClDH,EAAKW,CAAQ,GACNC,EAAKD,CAAQ,UAEhBD,EAAeP,GAAON,CAAQ,CACtC;CAaA,OAZAgB,QACQV,EAAM,OACX,MAAS;EACR,AAAIW,KAAMP,EAAO,SAAS,OAAO,UAAUL,EAAIY,CAAI,CAAC;CACtD,CACF,GACAD,QACQV,EAAM,cACN;EACJ,AAAII,EAAO,SAAS,SAAOP,EAAKO,EAAO,SAAS,KAAK;CACvD,CACF,GACOA;AACT"}
@@ -495,7 +495,8 @@ var normalizeData = (data, resolveX, resolveY = toNumber) => {
495
495
  q1: null,
496
496
  q3: null,
497
497
  outliers: null,
498
- details: null
498
+ details: null,
499
+ ids: null
499
500
  };
500
501
  if (isColumns(data)) {
501
502
  const count = data.y.length;
@@ -546,6 +547,7 @@ var normalizeData = (data, resolveX, resolveY = toNumber) => {
546
547
  let q3 = null;
547
548
  let outliers = null;
548
549
  let details = null;
550
+ let ids = null;
549
551
  const nanColumn = () => new Float64Array(count).fill(NaN);
550
552
  for (let i = 0; i < count; i++) {
551
553
  const item = list[i];
@@ -586,6 +588,10 @@ var normalizeData = (data, resolveX, resolveY = toNumber) => {
586
588
  details ??= new Array(count);
587
589
  details[i] = d.details;
588
590
  }
591
+ if (d.id !== void 0) {
592
+ ids ??= new Array(count);
593
+ ids[i] = d.id;
594
+ }
589
595
  } else {
590
596
  x[i] = i;
591
597
  y[i] = NaN;
@@ -603,7 +609,8 @@ var normalizeData = (data, resolveX, resolveY = toNumber) => {
603
609
  q1,
604
610
  q3,
605
611
  outliers,
606
- details
612
+ details,
613
+ ids
607
614
  });
608
615
  };
609
616
  /** First index whose x is >= value (sorted x) */
@@ -1512,6 +1519,38 @@ var decades = (range) => {
1512
1519
  const hi = Math.ceil(range[1] - 1e-9);
1513
1520
  return [lo, hi > lo ? hi : lo + 1];
1514
1521
  };
1522
+ /** Exponent of `m × 10^k`, exact for the values of the ticks */
1523
+ var niceExponent = (m, k) => Math.log10(Number((m * 10 ** k).toPrecision(12)));
1524
+ /**
1525
+ * A log range widened to the closest 1, 2 or 5 × 10^k bounds (the values
1526
+ * 900 - 140k -> 500 - 200k), tighter than whole decades
1527
+ */
1528
+ var niceLogRange = (range) => {
1529
+ const below = (e) => {
1530
+ const k = Math.floor(e + 1e-9);
1531
+ let best = k;
1532
+ for (const m of [2, 5]) {
1533
+ const v = niceExponent(m, k);
1534
+ if (v <= e + 1e-9) best = v;
1535
+ }
1536
+ return best;
1537
+ };
1538
+ const above = (e) => {
1539
+ const k = Math.floor(e - 1e-9);
1540
+ for (const m of [
1541
+ 1,
1542
+ 2,
1543
+ 5
1544
+ ]) {
1545
+ const v = niceExponent(m, k);
1546
+ if (v >= e - 1e-9) return v;
1547
+ }
1548
+ return k + 1;
1549
+ };
1550
+ const lo = below(range[0]);
1551
+ const hi = above(range[1]);
1552
+ return [lo, hi > lo + 1e-9 ? hi : above(lo + 1e-6)];
1553
+ };
1515
1554
  /**
1516
1555
  * Plots a series through a map: its columns, bars, stacks and lower
1517
1556
  * edges (bars / areas of the right axis start at `zero`)
@@ -1861,7 +1900,7 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
1861
1900
  xRange = [xRange[0] - pad, xRange[1] + pad];
1862
1901
  }
1863
1902
  if ((xOpts?.nice ?? (pointsOnly && xType === "linear")) && xType === "linear") xRange = niceDomain(xRange[0], xRange[1], xOpts?.tickCount ?? 6);
1864
- if (xLog && xOpts?.nice !== false) xRange = decades(xRange);
1903
+ if (xLog && xOpts?.nice !== false) xRange = niceLogRange(xRange);
1865
1904
  }
1866
1905
  const xBound = (v) => xLog ? Math.log10(v) : v;
1867
1906
  if (xOpts?.min !== void 0) xRange[0] = xBound(xOpts.min);
@@ -2176,7 +2215,7 @@ var drawBackground = (ctx, input) => {
2176
2215
  }
2177
2216
  };
2178
2217
  var overlaps = (a, b) => a.x < b.x + b.width && b.x < a.x + a.width && a.y < b.y + b.height && b.y < a.y + a.height;
2179
- var inside = (r, plot) => r.x >= plot.x && r.y >= plot.y && r.x + r.width <= plot.x + plot.width && r.y + r.height <= plot.y + plot.height;
2218
+ var inside$1 = (r, plot) => r.x >= plot.x && r.y >= plot.y && r.x + r.width <= plot.x + plot.width && r.y + r.height <= plot.y + plot.height;
2180
2219
  /** Text with a halo in the background color (readable over data) */
2181
2220
  var haloText = (ctx, text, x, y, color, halo) => {
2182
2221
  ctx.lineWidth = 3;
@@ -2231,7 +2270,7 @@ var placeLabels = (labels, plot, measure, height, occupied = []) => {
2231
2270
  },
2232
2271
  above,
2233
2272
  below
2234
- ]).find((c) => inside(c, plot) && !occupied.some((o) => overlaps(o, c)));
2273
+ ]).find((c) => inside$1(c, plot) && !occupied.some((o) => overlaps(o, c)));
2235
2274
  if (!box) continue;
2236
2275
  occupied.push(box);
2237
2276
  placed.push({
@@ -3569,44 +3608,180 @@ var ARROW_HEAD = {
3569
3608
  length: 6,
3570
3609
  half: 3.5
3571
3610
  };
3572
- /** Bars (or dots) of every category, the first visible one per category */
3573
- var rowSpans = (model, sc) => {
3574
- const rows = /* @__PURE__ */ new Map();
3611
+ var taskIndex = (model, sc, valuePx, categoryPx) => {
3612
+ const index = {
3613
+ boxes: [],
3614
+ byId: /* @__PURE__ */ new Map(),
3615
+ byRow: /* @__PURE__ */ new Map(),
3616
+ ids: /* @__PURE__ */ new Set()
3617
+ };
3618
+ const categories = model.x.type === "category" ? model.x.categories : null;
3575
3619
  for (const s of model.series) {
3576
- if (s.hidden || !s.tooltip) continue;
3577
3620
  if (s.type !== "bar" && s.type !== "scatter") continue;
3621
+ const ids = s.raw.ids;
3622
+ if (ids) {
3623
+ for (const id of ids) if (id !== void 0) index.ids.add(id);
3624
+ }
3625
+ if (s.hidden || !s.tooltip) continue;
3578
3626
  const { x, y, count } = s.cols;
3579
3627
  const bar = s.type === "bar" && s.barBase && s.barTop;
3580
- const half = bar ? s.barHalfWidth / Math.abs(sc.xPerPx) : dotSize(s, 0) / 2;
3628
+ const offset = slotOffset(s);
3581
3629
  for (let i = 0; i < count; i++) {
3582
- const k = Math.round(x[i]);
3583
- if (rows.has(k)) continue;
3584
3630
  const start = bar ? s.barBase[i] : y[i];
3585
3631
  const end = bar ? s.barTop[i] : y[i];
3586
- if (!Number.isFinite(start) || !Number.isFinite(end)) continue;
3587
- rows.set(k, {
3588
- at: x[i] + slotOffset(s),
3589
- start: Math.min(start, end),
3590
- end: Math.max(start, end),
3632
+ if (!Number.isFinite(x[i]) || !Number.isFinite(start) || !Number.isFinite(end)) continue;
3633
+ const half = bar ? s.barHalfWidth / Math.abs(sc.xPerPx) : dotSize(s, i) / 2;
3634
+ const p0 = valuePx(Math.min(start, end));
3635
+ const p1 = valuePx(Math.max(start, end));
3636
+ const pad = bar ? 0 : half;
3637
+ const box = {
3638
+ c: categoryPx(x[i] + offset),
3591
3639
  half,
3640
+ start: p0,
3641
+ end: p1,
3642
+ lo: Math.min(p0, p1) - pad,
3643
+ hi: Math.max(p0, p1) + pad,
3592
3644
  dot: !bar
3593
- });
3594
- }
3645
+ };
3646
+ index.boxes.push(box);
3647
+ const id = ids?.[i];
3648
+ if (id !== void 0 && !index.byId.has(id)) index.byId.set(id, box);
3649
+ const row = categories ? categories[Math.round(x[i])] : String(s.raw.x[i]);
3650
+ if (row !== void 0 && !index.byRow.has(row)) index.byRow.set(row, box);
3651
+ }
3652
+ }
3653
+ return index;
3654
+ };
3655
+ /** Run of an arrow out of a bar before it turns, in pixels */
3656
+ var ARROW_RUN = 8;
3657
+ /** Distance an arrow keeps from the bars it passes, in pixels */
3658
+ var ARROW_CLEARANCE = 4;
3659
+ /** Value-axis extents of bars (with the clearance), sorted and merged */
3660
+ var blockedLanes = (boxes) => {
3661
+ const list = boxes.map((o) => [o.lo - ARROW_CLEARANCE, o.hi + ARROW_CLEARANCE]).sort((p, q) => p[0] - q[0]);
3662
+ const out = [];
3663
+ for (const r of list) {
3664
+ const last = out[out.length - 1];
3665
+ if (last && r[0] <= last[1]) last[1] = Math.max(last[1], r[1]);
3666
+ else out.push(r);
3595
3667
  }
3596
- return rows;
3668
+ return out;
3669
+ };
3670
+ var inside = (lanes, v) => lanes.some(([lo, hi]) => v > lo + 1e-6 && v < hi - 1e-6);
3671
+ /** First free lane from `from` towards `to` (direction `dir`), or null */
3672
+ var freeLane = (lanes, from, to, dir) => {
3673
+ const candidates = [from];
3674
+ for (const [lo, hi] of lanes) candidates.push(lo, hi);
3675
+ let best = null;
3676
+ for (const v of candidates) {
3677
+ const along = dir * (v - from);
3678
+ if (along < 0 || dir * (to - v) < 0 || inside(lanes, v)) continue;
3679
+ if (best === null || along < dir * (best - from)) best = v;
3680
+ }
3681
+ return best;
3682
+ };
3683
+ /** Free lane closest to `want` (ties: the lower one) */
3684
+ var nearestLane = (lanes, want) => {
3685
+ const hit = lanes.find(([lo, hi]) => want > lo + 1e-6 && want < hi - 1e-6);
3686
+ if (!hit) return want;
3687
+ const [lo, hi] = hit;
3688
+ return want - lo <= hi - want ? lo : hi;
3689
+ };
3690
+ /** Drops repeated points and the middle of straight runs */
3691
+ var straighten = (points) => {
3692
+ const out = [];
3693
+ const same = (p, q) => Math.abs(p - q) < 1e-6;
3694
+ for (const p of points) {
3695
+ const last = out[out.length - 1];
3696
+ if (last && same(last[0], p[0]) && same(last[1], p[1])) continue;
3697
+ const prev = out[out.length - 2];
3698
+ if (prev && last && (same(prev[0], last[0]) && same(last[0], p[0]) || same(prev[1], last[1]) && same(last[1], p[1]))) out.pop();
3699
+ out.push(p);
3700
+ }
3701
+ return out;
3702
+ };
3703
+ /**
3704
+ * Route of an arrow as (value pixel, category pixel) corners, from the end
3705
+ * of `a` (`ev`) to the base of the head before `b` (`base`): one lane
3706
+ * across the rows clear of the other bars, searched from the predecessor
3707
+ * towards the successor; else (no such lane, or the successor starts
3708
+ * before the predecessor ends) along the gaps between the rows, crossing
3709
+ * every row in a free lane
3710
+ */
3711
+ var routeArrow = (a, b, ev, base, dir, boxes) => {
3712
+ const ca = a.c;
3713
+ const cb = b.c;
3714
+ const exit = ev + dir * ARROW_RUN;
3715
+ const room = dir * (base - exit) >= 0;
3716
+ const lo = Math.min(ca, cb);
3717
+ const hi = Math.max(ca, cb);
3718
+ const others = hi - lo < .5 ? [] : boxes.filter((o) => o !== a && o !== b && o.c + o.half > lo && o.c - o.half < hi);
3719
+ if (room) {
3720
+ const lane = freeLane(blockedLanes(others), exit, base, dir);
3721
+ if (lane !== null) return straighten([
3722
+ [ev, ca],
3723
+ [lane, ca],
3724
+ [lane, cb],
3725
+ [base, cb]
3726
+ ]);
3727
+ }
3728
+ const side = Math.sign(cb - ca) || 1;
3729
+ const rows = /* @__PURE__ */ new Map();
3730
+ for (const o of others) {
3731
+ if (Math.abs(o.c - ca) < .5 || Math.abs(o.c - cb) < .5) continue;
3732
+ const key = Math.round(o.c * 2);
3733
+ const row = rows.get(key);
3734
+ if (row) {
3735
+ row.half = Math.max(row.half, o.half);
3736
+ row.of.push(o);
3737
+ } else rows.set(key, {
3738
+ c: o.c,
3739
+ half: o.half,
3740
+ of: [o]
3741
+ });
3742
+ }
3743
+ const stops = [
3744
+ {
3745
+ c: ca,
3746
+ half: a.half,
3747
+ lanes: []
3748
+ },
3749
+ ...[...rows.values()].sort((p, q) => side * (p.c - q.c)).map((r) => ({
3750
+ c: r.c,
3751
+ half: r.half,
3752
+ lanes: blockedLanes(r.of)
3753
+ })),
3754
+ {
3755
+ c: cb,
3756
+ half: b.half,
3757
+ lanes: []
3758
+ }
3759
+ ];
3760
+ const back = base - dir * ARROW_RUN;
3761
+ const points = [[ev, ca], [exit, ca]];
3762
+ let v = exit;
3763
+ for (let k = 0; k + 1 < stops.length; k++) {
3764
+ const from = stops[k];
3765
+ const to = stops[k + 1];
3766
+ const m = Math.abs(to.c - from.c) < .5 ? from.c + side * (Math.max(from.half, to.half) + ARROW_CLEARANCE) : (from.c + side * from.half + to.c - side * to.half) / 2;
3767
+ const lane = k + 2 === stops.length ? room && dir * (base - v) >= 0 ? v : back : nearestLane(to.lanes, room ? v : back);
3768
+ if (lane !== v) {
3769
+ points.push([v, m], [lane, m]);
3770
+ v = lane;
3771
+ }
3772
+ }
3773
+ points.push([v, cb], [base, cb]);
3774
+ return straighten(points);
3597
3775
  };
3598
3776
  /**
3599
3777
  * Dependency arrows (`dependencies`, Gantt charts): from the end of the
3600
- * predecessor to the start of the successor; when the successor starts
3601
- * too early the line turns around between the rows
3778
+ * predecessor to the start of the successor, both found by point `id`
3779
+ * (else by category), on any x axis and orientation. The line crosses the
3780
+ * rows in a lane clear of the other bars, or goes along the gaps between
3781
+ * the rows (also when the successor starts too early)
3602
3782
  */
3603
3783
  var dependencyArrows = (model, sc, dependencies) => {
3604
- if (!dependencies.length || model.x.type !== "category") return [];
3605
- const rows = rowSpans(model, sc);
3606
- const index = /* @__PURE__ */ new Map();
3607
- model.x.categories.forEach((c, i) => {
3608
- if (!index.has(c)) index.set(c, i);
3609
- });
3784
+ if (!dependencies.length) return [];
3610
3785
  const horizontal = sc.horizontal;
3611
3786
  const pt = (v, c) => horizontal ? {
3612
3787
  x: v,
@@ -3624,33 +3799,24 @@ var dependencyArrows = (model, sc, dependencies) => {
3624
3799
  return horizontal ? p.y : p.x;
3625
3800
  };
3626
3801
  const dir = Math.sign(valuePx(sc.view.y[1]) - valuePx(sc.view.y[0])) || 1;
3627
- const rowPx = Math.abs(categoryPx(1) - categoryPx(0));
3802
+ const tasks = taskIndex(model, sc, valuePx, categoryPx);
3803
+ const find = (key) => tasks.byId.get(key) ?? (tasks.ids.has(key) ? void 0 : tasks.byRow.get(key));
3628
3804
  const { length, half } = ARROW_HEAD;
3629
- const gap = 8;
3630
3805
  const out = [];
3631
3806
  for (const d of dependencies) {
3632
- const a = rows.get(index.get(d.from) ?? NaN);
3633
- const b = rows.get(index.get(d.to) ?? NaN);
3807
+ const a = find(d.from);
3808
+ const b = find(d.to);
3634
3809
  if (!a || !b || a === b) continue;
3635
- const ev = valuePx(a.end) + (a.dot ? dir * a.half : 0);
3636
- const ca = categoryPx(a.at);
3637
- const sv = valuePx(b.start) - dir * (b.dot ? b.half + 1 : 1);
3638
- const cb = categoryPx(b.at);
3810
+ const ev = a.end + (a.dot ? dir * a.half : 0);
3811
+ const sv = b.start - dir * (b.dot ? b.half + 1 : 1);
3639
3812
  const base = sv - dir * length;
3640
- const points = [pt(ev, ca)];
3641
- const exit = ev + dir * gap;
3642
- if (dir * (base - exit) >= 0) points.push(pt(exit, ca), pt(exit, cb), pt(base, cb));
3643
- else {
3644
- const between = ca + (Math.sign(cb - ca) || 1) * Math.max(a.half + 3, rowPx / 2);
3645
- const back = base - dir * gap;
3646
- points.push(pt(exit, ca), pt(exit, between), pt(back, between), pt(back, cb), pt(base, cb));
3647
- }
3813
+ const route = routeArrow(a, b, ev, base, dir, tasks.boxes);
3648
3814
  out.push({
3649
- points,
3815
+ points: route.map(([v, c]) => pt(v, c)),
3650
3816
  head: [
3651
- pt(sv, cb),
3652
- pt(base, cb - half),
3653
- pt(base, cb + half)
3817
+ pt(sv, b.c),
3818
+ pt(base, b.c - half),
3819
+ pt(base, b.c + half)
3654
3820
  ],
3655
3821
  color: d.color,
3656
3822
  width: 1.25
@@ -6872,6 +7038,16 @@ var ganttSeries = (tasks, options = {}) => {
6872
7038
  const taskName = options.taskName ?? names.tasks;
6873
7039
  const progressName = options.progressName ?? names.progress;
6874
7040
  const separator = /^(zh|ja)\b/i.test(locale) ? "、" : ", ";
7041
+ const idOf = (t) => t.id ?? t.name;
7042
+ const rowOf = (t) => t.row ?? t.name;
7043
+ const byKey = /* @__PURE__ */ new Map();
7044
+ for (const t of tasks) if (!byKey.has(idOf(t))) byKey.set(idOf(t), t);
7045
+ for (const t of tasks) if (!byKey.has(t.name)) byKey.set(t.name, t);
7046
+ const point = (t) => ({
7047
+ x: rowOf(t),
7048
+ id: idOf(t),
7049
+ ...rowOf(t) !== t.name ? { label: t.name } : {}
7050
+ });
6875
7051
  const groups = [];
6876
7052
  for (const t of tasks) {
6877
7053
  const g = t.group ?? taskName;
@@ -6902,10 +7078,10 @@ var ganttSeries = (tasks, options = {}) => {
6902
7078
  });
6903
7079
  if (t.dependencies?.length) details.push({
6904
7080
  name: options.dependenciesName ?? rows.dependencies,
6905
- value: t.dependencies.join(separator)
7081
+ value: t.dependencies.map((k) => byKey.get(k)?.name ?? k).join(separator)
6906
7082
  });
6907
7083
  return {
6908
- x: t.name,
7084
+ ...point(t),
6909
7085
  y0: time(t.start),
6910
7086
  y: time(t.end ?? t.start),
6911
7087
  ...t.color ? { color: t.color } : {},
@@ -6927,7 +7103,7 @@ var ganttSeries = (tasks, options = {}) => {
6927
7103
  const end = time(t.end ?? t.start);
6928
7104
  const share = Math.min(1, Math.max(0, t.progress ?? 0));
6929
7105
  return {
6930
- x: t.name,
7106
+ x: rowOf(t),
6931
7107
  y0: start,
6932
7108
  y: start + (end - start) * share,
6933
7109
  label: formatProgress(share),
@@ -6944,7 +7120,7 @@ var ganttSeries = (tasks, options = {}) => {
6944
7120
  pointSize: 13,
6945
7121
  opacity: 1,
6946
7122
  data: milestones.map((t) => ({
6947
- x: t.name,
7123
+ ...point(t),
6948
7124
  y: time(t.start),
6949
7125
  ...t.color ? { color: t.color } : {}
6950
7126
  }))
@@ -6956,19 +7132,19 @@ var ganttSeries = (tasks, options = {}) => {
6956
7132
  if (v > hi) hi = v;
6957
7133
  }
6958
7134
  const pad = Number.isFinite(hi - lo) ? Math.max((hi - lo) * .025, 1) : 0;
6959
- const known = new Set(tasks.map((t) => t.name));
6960
7135
  const dependencies = [];
6961
- if (options.dependencyArrows !== false) for (const t of tasks) for (const from of t.dependencies ?? []) {
6962
- if (from === t.name || !known.has(from)) continue;
7136
+ if (options.dependencyArrows !== false) for (const t of tasks) for (const key of t.dependencies ?? []) {
7137
+ const from = byKey.get(key);
7138
+ if (!from || from === t) continue;
6963
7139
  dependencies.push({
6964
- from,
6965
- to: t.name,
7140
+ from: idOf(from),
7141
+ to: idOf(t),
6966
7142
  ...options.dependencyColor ? { color: options.dependencyColor } : {}
6967
7143
  });
6968
7144
  }
6969
7145
  return {
6970
7146
  series,
6971
- categories: tasks.map((t) => t.name),
7147
+ categories: [...new Set(tasks.map(rowOf))],
6972
7148
  domain: Number.isFinite(lo) ? [lo - pad, hi + pad] : [0, 1],
6973
7149
  dependencies
6974
7150
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minerva-design",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Minerva Design: React, Vue, Angular, Web Components and native platform components with shared design tokens and contracts",
5
5
  "license": "MIT",
6
6
  "author": "fwx5618177 <fwx5618177@gmail.com>",