@perses-dev/components 0.29.1 → 0.31.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 (198) hide show
  1. package/dist/DateTimeRangePicker/TimeRangeSelector.d.ts.map +1 -1
  2. package/dist/DateTimeRangePicker/TimeRangeSelector.js +7 -1
  3. package/dist/DateTimeRangePicker/TimeRangeSelector.js.map +1 -1
  4. package/dist/EChart/EChart.d.ts.map +1 -1
  5. package/dist/EChart/EChart.js +1 -7
  6. package/dist/EChart/EChart.js.map +1 -1
  7. package/dist/Legend/CompactLegend.d.ts +6 -4
  8. package/dist/Legend/CompactLegend.d.ts.map +1 -1
  9. package/dist/Legend/CompactLegend.js +4 -1
  10. package/dist/Legend/CompactLegend.js.map +1 -1
  11. package/dist/Legend/Legend.d.ts +11 -9
  12. package/dist/Legend/Legend.d.ts.map +1 -1
  13. package/dist/Legend/Legend.js +45 -11
  14. package/dist/Legend/Legend.js.map +1 -1
  15. package/dist/Legend/ListLegend.d.ts +5 -8
  16. package/dist/Legend/ListLegend.d.ts.map +1 -1
  17. package/dist/Legend/ListLegend.js +34 -99
  18. package/dist/Legend/ListLegend.js.map +1 -1
  19. package/dist/Legend/ListLegendItem.d.ts +8 -8
  20. package/dist/Legend/ListLegendItem.d.ts.map +1 -1
  21. package/dist/Legend/ListLegendItem.js +9 -12
  22. package/dist/Legend/ListLegendItem.js.map +1 -1
  23. package/dist/LineChart/LineChart.d.ts +2 -1
  24. package/dist/LineChart/LineChart.d.ts.map +1 -1
  25. package/dist/LineChart/LineChart.js +35 -22
  26. package/dist/LineChart/LineChart.js.map +1 -1
  27. package/dist/StatChart/StatChart.d.ts.map +1 -1
  28. package/dist/StatChart/StatChart.js +5 -1
  29. package/dist/StatChart/StatChart.js.map +1 -1
  30. package/dist/Table/InnerTable.d.ts +9 -0
  31. package/dist/Table/InnerTable.d.ts.map +1 -0
  32. package/dist/Table/InnerTable.js +38 -0
  33. package/dist/Table/InnerTable.js.map +1 -0
  34. package/dist/Table/Table.d.ts +10 -0
  35. package/dist/Table/Table.d.ts.map +1 -0
  36. package/dist/Table/Table.js +101 -0
  37. package/dist/Table/Table.js.map +1 -0
  38. package/dist/Table/TableBody.d.ts +6 -0
  39. package/dist/Table/TableBody.d.ts.map +1 -0
  40. package/dist/Table/TableBody.js +23 -0
  41. package/dist/Table/TableBody.js.map +1 -0
  42. package/dist/Table/TableCell.d.ts +18 -0
  43. package/dist/Table/TableCell.d.ts.map +1 -0
  44. package/dist/Table/TableCell.js +91 -0
  45. package/dist/Table/TableCell.js.map +1 -0
  46. package/dist/Table/TableCheckbox.d.ts +9 -0
  47. package/dist/Table/TableCheckbox.d.ts.map +1 -0
  48. package/dist/Table/TableCheckbox.js +49 -0
  49. package/dist/Table/TableCheckbox.js.map +1 -0
  50. package/dist/Table/TableHead.d.ts +6 -0
  51. package/dist/Table/TableHead.d.ts.map +1 -0
  52. package/dist/Table/TableHead.js +23 -0
  53. package/dist/Table/TableHead.js.map +1 -0
  54. package/dist/Table/TableRow.d.ts +9 -0
  55. package/dist/Table/TableRow.d.ts.map +1 -0
  56. package/dist/Table/TableRow.js +29 -0
  57. package/dist/Table/TableRow.js.map +1 -0
  58. package/dist/Table/VirtualizedTable.d.ts +11 -0
  59. package/dist/Table/VirtualizedTable.d.ts.map +1 -0
  60. package/dist/Table/VirtualizedTable.js +152 -0
  61. package/dist/Table/VirtualizedTable.js.map +1 -0
  62. package/dist/Table/VirtualizedTableContainer.d.ts +6 -0
  63. package/dist/Table/VirtualizedTableContainer.d.ts.map +1 -0
  64. package/dist/Table/VirtualizedTableContainer.js +24 -0
  65. package/dist/Table/VirtualizedTableContainer.js.map +1 -0
  66. package/dist/Table/hooks/useTableKeyboardNav.d.ts +32 -0
  67. package/dist/Table/hooks/useTableKeyboardNav.d.ts.map +1 -0
  68. package/dist/Table/hooks/useTableKeyboardNav.js +98 -0
  69. package/dist/Table/hooks/useTableKeyboardNav.js.map +1 -0
  70. package/dist/Table/hooks/useVirtualizedTableKeyboardNav.d.ts +29 -0
  71. package/dist/Table/hooks/useVirtualizedTableKeyboardNav.d.ts.map +1 -0
  72. package/dist/Table/hooks/useVirtualizedTableKeyboardNav.js +89 -0
  73. package/dist/Table/hooks/useVirtualizedTableKeyboardNav.js.map +1 -0
  74. package/dist/Table/index.d.ts +4 -0
  75. package/dist/Table/index.d.ts.map +1 -0
  76. package/dist/Table/index.js +16 -0
  77. package/dist/Table/index.js.map +1 -0
  78. package/dist/Table/model/table-model.d.ts +83 -0
  79. package/dist/Table/model/table-model.d.ts.map +1 -0
  80. package/dist/Table/model/table-model.js +73 -0
  81. package/dist/Table/model/table-model.js.map +1 -0
  82. package/dist/TimeSeriesTooltip/SeriesInfo.d.ts +1 -0
  83. package/dist/TimeSeriesTooltip/SeriesInfo.d.ts.map +1 -1
  84. package/dist/TimeSeriesTooltip/SeriesInfo.js +11 -9
  85. package/dist/TimeSeriesTooltip/SeriesInfo.js.map +1 -1
  86. package/dist/TimeSeriesTooltip/TimeSeriesTooltip.d.ts +3 -2
  87. package/dist/TimeSeriesTooltip/TimeSeriesTooltip.d.ts.map +1 -1
  88. package/dist/TimeSeriesTooltip/TimeSeriesTooltip.js +63 -17
  89. package/dist/TimeSeriesTooltip/TimeSeriesTooltip.js.map +1 -1
  90. package/dist/TimeSeriesTooltip/TooltipContent.d.ts +5 -3
  91. package/dist/TimeSeriesTooltip/TooltipContent.d.ts.map +1 -1
  92. package/dist/TimeSeriesTooltip/TooltipContent.js +81 -44
  93. package/dist/TimeSeriesTooltip/TooltipContent.js.map +1 -1
  94. package/dist/TimeSeriesTooltip/index.d.ts +1 -1
  95. package/dist/TimeSeriesTooltip/index.d.ts.map +1 -1
  96. package/dist/TimeSeriesTooltip/index.js +1 -1
  97. package/dist/TimeSeriesTooltip/index.js.map +1 -1
  98. package/dist/TimeSeriesTooltip/nearby-series.d.ts +46 -0
  99. package/dist/TimeSeriesTooltip/nearby-series.d.ts.map +1 -0
  100. package/dist/TimeSeriesTooltip/nearby-series.js +200 -0
  101. package/dist/TimeSeriesTooltip/nearby-series.js.map +1 -0
  102. package/dist/TimeSeriesTooltip/tooltip-model.d.ts +12 -4
  103. package/dist/TimeSeriesTooltip/tooltip-model.d.ts.map +1 -1
  104. package/dist/TimeSeriesTooltip/tooltip-model.js +10 -2
  105. package/dist/TimeSeriesTooltip/tooltip-model.js.map +1 -1
  106. package/dist/TimeSeriesTooltip/utils.d.ts +1 -1
  107. package/dist/TimeSeriesTooltip/utils.d.ts.map +1 -1
  108. package/dist/TimeSeriesTooltip/utils.js +7 -15
  109. package/dist/TimeSeriesTooltip/utils.js.map +1 -1
  110. package/dist/UnitSelector/UnitSelector.d.ts.map +1 -1
  111. package/dist/UnitSelector/UnitSelector.js +40 -17
  112. package/dist/UnitSelector/UnitSelector.js.map +1 -1
  113. package/dist/cjs/DateTimeRangePicker/TimeRangeSelector.js +7 -1
  114. package/dist/cjs/EChart/EChart.js +1 -7
  115. package/dist/cjs/Legend/CompactLegend.js +4 -1
  116. package/dist/cjs/Legend/Legend.js +45 -11
  117. package/dist/cjs/Legend/ListLegend.js +33 -98
  118. package/dist/cjs/Legend/ListLegendItem.js +8 -11
  119. package/dist/cjs/LineChart/LineChart.js +35 -22
  120. package/dist/cjs/StatChart/StatChart.js +5 -1
  121. package/dist/cjs/Table/InnerTable.js +44 -0
  122. package/dist/cjs/Table/Table.js +102 -0
  123. package/dist/cjs/Table/TableBody.js +29 -0
  124. package/dist/cjs/Table/TableCell.js +97 -0
  125. package/dist/cjs/Table/TableCheckbox.js +55 -0
  126. package/dist/cjs/Table/TableHead.js +29 -0
  127. package/dist/cjs/Table/TableRow.js +35 -0
  128. package/dist/cjs/Table/VirtualizedTable.js +155 -0
  129. package/dist/cjs/Table/VirtualizedTableContainer.js +30 -0
  130. package/dist/cjs/Table/hooks/useTableKeyboardNav.js +99 -0
  131. package/dist/cjs/Table/hooks/useVirtualizedTableKeyboardNav.js +93 -0
  132. package/dist/cjs/Table/index.js +33 -0
  133. package/dist/cjs/Table/model/table-model.js +80 -0
  134. package/dist/cjs/TimeSeriesTooltip/SeriesInfo.js +10 -8
  135. package/dist/cjs/TimeSeriesTooltip/TimeSeriesTooltip.js +67 -16
  136. package/dist/cjs/TimeSeriesTooltip/TooltipContent.js +85 -43
  137. package/dist/cjs/TimeSeriesTooltip/index.js +1 -1
  138. package/dist/cjs/TimeSeriesTooltip/nearby-series.js +206 -0
  139. package/dist/cjs/TimeSeriesTooltip/tooltip-model.js +15 -3
  140. package/dist/cjs/TimeSeriesTooltip/utils.js +6 -14
  141. package/dist/cjs/UnitSelector/UnitSelector.js +39 -16
  142. package/dist/cjs/context/SnackbarProvider.js +66 -0
  143. package/dist/cjs/index.js +2 -0
  144. package/dist/cjs/model/legend.js +7 -1
  145. package/dist/cjs/model/units/bytes.js +25 -21
  146. package/dist/cjs/model/units/constants.js +3 -3
  147. package/dist/cjs/model/units/decimal.js +22 -19
  148. package/dist/cjs/model/units/percent.js +15 -22
  149. package/dist/cjs/model/units/time.js +24 -20
  150. package/dist/cjs/model/units/units.js +2 -2
  151. package/dist/cjs/model/units/utils.js +42 -0
  152. package/dist/cjs/theme/palette/grey.js +6 -2
  153. package/dist/context/SnackbarProvider.d.ts +23 -0
  154. package/dist/context/SnackbarProvider.d.ts.map +1 -0
  155. package/dist/context/SnackbarProvider.js +59 -0
  156. package/dist/context/SnackbarProvider.js.map +1 -0
  157. package/dist/index.d.ts +2 -0
  158. package/dist/index.d.ts.map +1 -1
  159. package/dist/index.js +2 -0
  160. package/dist/index.js.map +1 -1
  161. package/dist/model/legend.d.ts +10 -2
  162. package/dist/model/legend.d.ts.map +1 -1
  163. package/dist/model/legend.js +5 -0
  164. package/dist/model/legend.js.map +1 -1
  165. package/dist/model/units/bytes.d.ts +1 -1
  166. package/dist/model/units/bytes.d.ts.map +1 -1
  167. package/dist/model/units/bytes.js +26 -22
  168. package/dist/model/units/bytes.js.map +1 -1
  169. package/dist/model/units/constants.d.ts +1 -1
  170. package/dist/model/units/constants.js +1 -1
  171. package/dist/model/units/constants.js.map +1 -1
  172. package/dist/model/units/decimal.d.ts +2 -2
  173. package/dist/model/units/decimal.d.ts.map +1 -1
  174. package/dist/model/units/decimal.js +22 -19
  175. package/dist/model/units/decimal.js.map +1 -1
  176. package/dist/model/units/percent.d.ts +1 -1
  177. package/dist/model/units/percent.d.ts.map +1 -1
  178. package/dist/model/units/percent.js +14 -21
  179. package/dist/model/units/percent.js.map +1 -1
  180. package/dist/model/units/time.d.ts +1 -1
  181. package/dist/model/units/time.d.ts.map +1 -1
  182. package/dist/model/units/time.js +24 -20
  183. package/dist/model/units/time.js.map +1 -1
  184. package/dist/model/units/units.js +2 -2
  185. package/dist/model/units/units.js.map +1 -1
  186. package/dist/model/units/utils.d.ts +4 -0
  187. package/dist/model/units/utils.d.ts.map +1 -0
  188. package/dist/model/units/utils.js +32 -0
  189. package/dist/model/units/utils.js.map +1 -0
  190. package/dist/theme/palette/grey.d.ts.map +1 -1
  191. package/dist/theme/palette/grey.js +6 -2
  192. package/dist/theme/palette/grey.js.map +1 -1
  193. package/package.json +6 -6
  194. package/dist/TimeSeriesTooltip/focused-series.d.ts +0 -25
  195. package/dist/TimeSeriesTooltip/focused-series.d.ts.map +0 -1
  196. package/dist/TimeSeriesTooltip/focused-series.js +0 -111
  197. package/dist/TimeSeriesTooltip/focused-series.js.map +0 -1
  198. package/dist/cjs/TimeSeriesTooltip/focused-series.js +0 -117
@@ -1 +1 @@
1
- {"version":3,"file":"TimeRangeSelector.d.ts","sourceRoot":"","sources":["../../src/DateTimeRangePicker/TimeRangeSelector.tsx"],"names":[],"mappings":";AAaA,OAAO,EAAoB,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAuB,MAAM,kBAAkB,CAAC;AAM1F,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,iBAAiB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,sBAAsB;IAC9B,KAAK,EAAE,cAAc,CAAC;IACtB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,cAAc,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,eA+C9D"}
1
+ {"version":3,"file":"TimeRangeSelector.d.ts","sourceRoot":"","sources":["../../src/DateTimeRangePicker/TimeRangeSelector.tsx"],"names":[],"mappings":";AAaA,OAAO,EAAoB,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAuB,MAAM,kBAAkB,CAAC;AAM1F,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,iBAAiB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,sBAAsB;IAC9B,KAAK,EAAE,cAAc,CAAC;IACtB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,cAAc,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,eAqD9D"}
@@ -29,8 +29,14 @@ export function TimeRangeSelector(props) {
29
29
  'aria-label': `Select time range. Currently set to ${formattedValue}`
30
30
  },
31
31
  sx: {
32
+ // `transform: none` prevents calendar icon from flipping over when menu is open
32
33
  '.MuiSelect-icon': {
33
- marginTop: '1px'
34
+ marginTop: '1px',
35
+ transform: 'none'
36
+ },
37
+ // paddingRight creates more space for the calendar icon (it's a bigger icon)
38
+ '.MuiSelect-select.MuiSelect-outlined.MuiInputBase-input': {
39
+ paddingRight: '36px'
34
40
  },
35
41
  '.MuiSelect-select': height ? {
36
42
  lineHeight: height,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/DateTimeRangePicker/TimeRangeSelector.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { MenuItem, Select, SelectChangeEvent } from '@mui/material';\nimport Calendar from 'mdi-material-ui/Calendar';\nimport { TimeRangeValue, RelativeTimeRange, isRelativeTimeRange } from '@perses-dev/core';\nimport { useTimeZone } from '../context/TimeZoneProvider';\nimport { formatAbsoluteRange } from './utils';\n\nconst DATE_TIME_FORMAT = 'yyyy-MM-dd HH:mm:ss';\n\nexport interface TimeOption {\n value: RelativeTimeRange;\n display: string;\n}\n\ninterface TimeRangeSelectorProps {\n value: TimeRangeValue;\n timeOptions: TimeOption[];\n onSelectChange: (event: SelectChangeEvent<string>) => void;\n onCustomClick: () => void;\n height?: string;\n}\n\nexport function TimeRangeSelector(props: TimeRangeSelectorProps) {\n const { value, timeOptions, onSelectChange, onCustomClick, height } = props;\n const { timeZone } = useTimeZone();\n const formattedValue = !isRelativeTimeRange(value)\n ? formatAbsoluteRange(value, DATE_TIME_FORMAT, timeZone)\n : value.pastDuration;\n return (\n <Select\n value={formattedValue}\n onChange={onSelectChange}\n IconComponent={Calendar}\n inputProps={{\n 'aria-label': `Select time range. Currently set to ${formattedValue}`,\n }}\n sx={{\n '.MuiSelect-icon': {\n marginTop: '1px',\n },\n '.MuiSelect-select': height ? { lineHeight: height, paddingY: 0 } : {},\n }}\n >\n {timeOptions.map((item, idx) => (\n <MenuItem key={idx} value={item.value.pastDuration}>\n {item.display}\n </MenuItem>\n ))}\n\n {isRelativeTimeRange(value) ? (\n <MenuItem\n onClick={() => {\n onCustomClick();\n }}\n >\n Custom time range\n </MenuItem>\n ) : (\n <MenuItem\n value={formattedValue}\n onClick={() => {\n onCustomClick();\n }}\n >\n {formattedValue}\n </MenuItem>\n )}\n </Select>\n );\n}\n"],"names":["MenuItem","Select","Calendar","isRelativeTimeRange","useTimeZone","formatAbsoluteRange","DATE_TIME_FORMAT","TimeRangeSelector","props","value","timeOptions","onSelectChange","onCustomClick","height","timeZone","formattedValue","pastDuration","onChange","IconComponent","inputProps","sx","marginTop","lineHeight","paddingY","map","item","idx","display","onClick"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,QAAQ,EAAEC,MAAM,QAA2B,eAAe,CAAC;AACpE,OAAOC,QAAQ,MAAM,0BAA0B,CAAC;AAChD,SAA4CC,mBAAmB,QAAQ,kBAAkB,CAAC;AAC1F,SAASC,WAAW,QAAQ,6BAA6B,CAAC;AAC1D,SAASC,mBAAmB,QAAQ,SAAS,CAAC;AAE9C,MAAMC,gBAAgB,GAAG,qBAAqB,AAAC;AAe/C,OAAO,SAASC,iBAAiB,CAACC,KAA6B,EAAE;IAC/D,MAAM,EAAEC,KAAK,CAAA,EAAEC,WAAW,CAAA,EAAEC,cAAc,CAAA,EAAEC,aAAa,CAAA,EAAEC,MAAM,CAAA,EAAE,GAAGL,KAAK,AAAC;IAC5E,MAAM,EAAEM,QAAQ,CAAA,EAAE,GAAGV,WAAW,EAAE,AAAC;IACnC,MAAMW,cAAc,GAAG,CAACZ,mBAAmB,CAACM,KAAK,CAAC,GAC9CJ,mBAAmB,CAACI,KAAK,EAAEH,gBAAgB,EAAEQ,QAAQ,CAAC,GACtDL,KAAK,CAACO,YAAY,AAAC;IACvB,qBACE,MAACf,MAAM;QACLQ,KAAK,EAAEM,cAAc;QACrBE,QAAQ,EAAEN,cAAc;QACxBO,aAAa,EAAEhB,QAAQ;QACvBiB,UAAU,EAAE;YACV,YAAY,EAAE,CAAC,oCAAoC,EAAEJ,cAAc,CAAC,CAAC;SACtE;QACDK,EAAE,EAAE;YACF,iBAAiB,EAAE;gBACjBC,SAAS,EAAE,KAAK;aACjB;YACD,mBAAmB,EAAER,MAAM,GAAG;gBAAES,UAAU,EAAET,MAAM;gBAAEU,QAAQ,EAAE,CAAC;aAAE,GAAG,EAAE;SACvE;;YAEAb,WAAW,CAACc,GAAG,CAAC,CAACC,IAAI,EAAEC,GAAG,iBACzB,KAAC1B,QAAQ;oBAAWS,KAAK,EAAEgB,IAAI,CAAChB,KAAK,CAACO,YAAY;8BAC/CS,IAAI,CAACE,OAAO;mBADAD,GAAG,CAEP,AACZ,CAAC;YAEDvB,mBAAmB,CAACM,KAAK,CAAC,iBACzB,KAACT,QAAQ;gBACP4B,OAAO,EAAE,IAAM;oBACbhB,aAAa,EAAE,CAAC;gBAClB,CAAC;0BACF,mBAED;cAAW,iBAEX,KAACZ,QAAQ;gBACPS,KAAK,EAAEM,cAAc;gBACrBa,OAAO,EAAE,IAAM;oBACbhB,aAAa,EAAE,CAAC;gBAClB,CAAC;0BAEAG,cAAc;cACN,AACZ;;MACM,CACT;AACJ,CAAC"}
1
+ {"version":3,"sources":["../../src/DateTimeRangePicker/TimeRangeSelector.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { MenuItem, Select, SelectChangeEvent } from '@mui/material';\nimport Calendar from 'mdi-material-ui/Calendar';\nimport { TimeRangeValue, RelativeTimeRange, isRelativeTimeRange } from '@perses-dev/core';\nimport { useTimeZone } from '../context/TimeZoneProvider';\nimport { formatAbsoluteRange } from './utils';\n\nconst DATE_TIME_FORMAT = 'yyyy-MM-dd HH:mm:ss';\n\nexport interface TimeOption {\n value: RelativeTimeRange;\n display: string;\n}\n\ninterface TimeRangeSelectorProps {\n value: TimeRangeValue;\n timeOptions: TimeOption[];\n onSelectChange: (event: SelectChangeEvent<string>) => void;\n onCustomClick: () => void;\n height?: string;\n}\n\nexport function TimeRangeSelector(props: TimeRangeSelectorProps) {\n const { value, timeOptions, onSelectChange, onCustomClick, height } = props;\n const { timeZone } = useTimeZone();\n const formattedValue = !isRelativeTimeRange(value)\n ? formatAbsoluteRange(value, DATE_TIME_FORMAT, timeZone)\n : value.pastDuration;\n return (\n <Select\n value={formattedValue}\n onChange={onSelectChange}\n IconComponent={Calendar}\n inputProps={{\n 'aria-label': `Select time range. Currently set to ${formattedValue}`,\n }}\n sx={{\n // `transform: none` prevents calendar icon from flipping over when menu is open\n '.MuiSelect-icon': {\n marginTop: '1px',\n transform: 'none',\n },\n // paddingRight creates more space for the calendar icon (it's a bigger icon)\n '.MuiSelect-select.MuiSelect-outlined.MuiInputBase-input': {\n paddingRight: '36px',\n },\n '.MuiSelect-select': height ? { lineHeight: height, paddingY: 0 } : {},\n }}\n >\n {timeOptions.map((item, idx) => (\n <MenuItem key={idx} value={item.value.pastDuration}>\n {item.display}\n </MenuItem>\n ))}\n\n {isRelativeTimeRange(value) ? (\n <MenuItem\n onClick={() => {\n onCustomClick();\n }}\n >\n Custom time range\n </MenuItem>\n ) : (\n <MenuItem\n value={formattedValue}\n onClick={() => {\n onCustomClick();\n }}\n >\n {formattedValue}\n </MenuItem>\n )}\n </Select>\n );\n}\n"],"names":["MenuItem","Select","Calendar","isRelativeTimeRange","useTimeZone","formatAbsoluteRange","DATE_TIME_FORMAT","TimeRangeSelector","props","value","timeOptions","onSelectChange","onCustomClick","height","timeZone","formattedValue","pastDuration","onChange","IconComponent","inputProps","sx","marginTop","transform","paddingRight","lineHeight","paddingY","map","item","idx","display","onClick"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,QAAQ,EAAEC,MAAM,QAA2B,eAAe,CAAC;AACpE,OAAOC,QAAQ,MAAM,0BAA0B,CAAC;AAChD,SAA4CC,mBAAmB,QAAQ,kBAAkB,CAAC;AAC1F,SAASC,WAAW,QAAQ,6BAA6B,CAAC;AAC1D,SAASC,mBAAmB,QAAQ,SAAS,CAAC;AAE9C,MAAMC,gBAAgB,GAAG,qBAAqB,AAAC;AAe/C,OAAO,SAASC,iBAAiB,CAACC,KAA6B,EAAE;IAC/D,MAAM,EAAEC,KAAK,CAAA,EAAEC,WAAW,CAAA,EAAEC,cAAc,CAAA,EAAEC,aAAa,CAAA,EAAEC,MAAM,CAAA,EAAE,GAAGL,KAAK,AAAC;IAC5E,MAAM,EAAEM,QAAQ,CAAA,EAAE,GAAGV,WAAW,EAAE,AAAC;IACnC,MAAMW,cAAc,GAAG,CAACZ,mBAAmB,CAACM,KAAK,CAAC,GAC9CJ,mBAAmB,CAACI,KAAK,EAAEH,gBAAgB,EAAEQ,QAAQ,CAAC,GACtDL,KAAK,CAACO,YAAY,AAAC;IACvB,qBACE,MAACf,MAAM;QACLQ,KAAK,EAAEM,cAAc;QACrBE,QAAQ,EAAEN,cAAc;QACxBO,aAAa,EAAEhB,QAAQ;QACvBiB,UAAU,EAAE;YACV,YAAY,EAAE,CAAC,oCAAoC,EAAEJ,cAAc,CAAC,CAAC;SACtE;QACDK,EAAE,EAAE;YACF,gFAAgF;YAChF,iBAAiB,EAAE;gBACjBC,SAAS,EAAE,KAAK;gBAChBC,SAAS,EAAE,MAAM;aAClB;YACD,6EAA6E;YAC7E,yDAAyD,EAAE;gBACzDC,YAAY,EAAE,MAAM;aACrB;YACD,mBAAmB,EAAEV,MAAM,GAAG;gBAAEW,UAAU,EAAEX,MAAM;gBAAEY,QAAQ,EAAE,CAAC;aAAE,GAAG,EAAE;SACvE;;YAEAf,WAAW,CAACgB,GAAG,CAAC,CAACC,IAAI,EAAEC,GAAG,iBACzB,KAAC5B,QAAQ;oBAAWS,KAAK,EAAEkB,IAAI,CAAClB,KAAK,CAACO,YAAY;8BAC/CW,IAAI,CAACE,OAAO;mBADAD,GAAG,CAEP,AACZ,CAAC;YAEDzB,mBAAmB,CAACM,KAAK,CAAC,iBACzB,KAACT,QAAQ;gBACP8B,OAAO,EAAE,IAAM;oBACblB,aAAa,EAAE,CAAC;gBAClB,CAAC;0BACF,mBAED;cAAW,iBAEX,KAACZ,QAAQ;gBACPS,KAAK,EAAEM,cAAc;gBACrBe,OAAO,EAAE,IAAM;oBACblB,aAAa,EAAE,CAAC;gBAClB,CAAC;0BAEAG,cAAc;cACN,AACZ;;MACM,CACT;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"EChart.d.ts","sourceRoot":"","sources":["../../src/EChart/EChart.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EChart.d.ts","sourceRoot":"","sources":["../../src/EChart/EChart.tsx"],"names":[],"mappings":"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"}
@@ -15,7 +15,6 @@ import React, { useEffect, useLayoutEffect, useRef } from 'react';
15
15
  import { init } from 'echarts/core';
16
16
  import { Box } from '@mui/material';
17
17
  import { isEqual, debounce } from 'lodash-es';
18
- import { combineSx } from '../utils';
19
18
  const mouseEvents = [
20
19
  'click',
21
20
  'dblclick',
@@ -107,12 +106,7 @@ export const EChart = /*#__PURE__*/ React.memo(function EChart({ option , theme
107
106
  ]);
108
107
  return /*#__PURE__*/ _jsx(Box, {
109
108
  ref: containerRef,
110
- sx: combineSx({
111
- // Ensures chart fills container and updates size correctly when resizing,
112
- // combineSx allows this default behavior to be overriden from parent component
113
- width: '100%',
114
- height: '100%'
115
- }, sx)
109
+ sx: sx
116
110
  });
117
111
  });
118
112
  // Validate event config and bind custom events
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/EChart/EChart.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport React, { useEffect, useLayoutEffect, useRef } from 'react';\nimport { ECharts, EChartsCoreOption, init } from 'echarts/core';\nimport { Box, SxProps, Theme } from '@mui/material';\nimport { isEqual, debounce } from 'lodash-es';\nimport { EChartsTheme } from '../model';\nimport { combineSx } from '../utils';\n\n// see docs for info about each property: https://echarts.apache.org/en/api.html#events\nexport interface MouseEventsParameters<T> {\n componentType: string;\n seriesType: string;\n seriesIndex: number;\n seriesName: string;\n name: string;\n dataIndex: number;\n data: Record<string, unknown> & T;\n dataType: string;\n value: number | number[];\n color: string;\n info: Record<string, unknown>;\n}\n\ntype OnEventFunction<T> = (\n params: MouseEventsParameters<T>,\n // This is potentially undefined for testing purposes\n instance?: ECharts\n) => void;\n\nconst mouseEvents = [\n 'click',\n 'dblclick',\n 'mousedown',\n 'mousemove',\n 'mouseup',\n 'mouseover',\n 'mouseout',\n 'globalout',\n 'contextmenu',\n] as const;\n\nexport type MouseEventName = (typeof mouseEvents)[number];\n\n// batch event types\nexport interface DataZoomPayloadBatchItem {\n dataZoomId: string;\n // start and end not returned unless dataZoom is based on percentProp,\n // which is for cases when a dataZoom component controls multiple axes\n start?: number;\n end?: number;\n // startValue and endValue return data index for 'category' axes,\n // for axis types 'value' and 'time', actual values are returned\n startValue?: number;\n endValue?: number;\n}\n\nexport interface HighlightPayloadBatchItem {\n dataIndex: number;\n dataIndexInside: number;\n seriesIndex: number;\n // highlight action can effect multiple connected charts\n escapeConnect?: boolean;\n // whether blur state was triggered\n notBlur?: boolean;\n}\n\nexport interface BatchEventsParameters {\n type: BatchEventName;\n batch: DataZoomPayloadBatchItem[] & HighlightPayloadBatchItem[];\n}\n\ntype OnBatchEventFunction = (params: BatchEventsParameters) => void;\n\nconst batchEvents = ['datazoom', 'downplay', 'highlight'] as const;\n\nexport type BatchEventName = (typeof batchEvents)[number];\n\ntype ChartEventName = 'finished';\n\ntype EventName = MouseEventName | ChartEventName | BatchEventName;\n\nexport type OnEventsType<T> = {\n [mouseEventName in MouseEventName]?: OnEventFunction<T>;\n} & {\n [batchEventName in BatchEventName]?: OnBatchEventFunction;\n} & {\n [eventName in ChartEventName]?: () => void;\n};\n\nexport interface EChartsProps<T> {\n option: EChartsCoreOption;\n theme?: string | EChartsTheme;\n renderer?: 'canvas' | 'svg';\n sx?: SxProps<Theme>;\n onEvents?: OnEventsType<T>;\n _instance?: React.MutableRefObject<ECharts | undefined>;\n onChartInitialized?: (instance: ECharts) => void;\n}\n\nexport const EChart = React.memo(function EChart<T>({\n option,\n theme,\n renderer,\n sx,\n onEvents,\n _instance,\n onChartInitialized,\n}: EChartsProps<T>) {\n const initialOption = useRef<EChartsCoreOption>(option);\n const prevOption = useRef<EChartsCoreOption>(option);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const chartElement = useRef<ECharts | null>(null);\n\n // Initialize chart, dispose on unmount\n useLayoutEffect(() => {\n if (containerRef.current === null || chartElement.current !== null) return;\n chartElement.current = init(containerRef.current, theme, { renderer: renderer ?? 'canvas' });\n if (chartElement.current === undefined) return;\n chartElement.current.setOption(initialOption.current, true);\n onChartInitialized?.(chartElement.current);\n if (_instance !== undefined) {\n _instance.current = chartElement.current;\n }\n return () => {\n if (chartElement.current === null) return;\n chartElement.current.dispose();\n chartElement.current = null;\n };\n }, [_instance, onChartInitialized, theme, renderer]);\n\n // Update chart data when option changes\n useEffect(() => {\n if (prevOption.current === undefined || isEqual(prevOption.current, option)) return;\n if (!chartElement.current) return;\n chartElement.current.setOption(option, true);\n prevOption.current = option;\n }, [option]);\n\n // Resize chart, cleanup listener on unmount\n useLayoutEffect(() => {\n const updateSize = debounce(() => {\n if (!chartElement.current) return;\n chartElement.current.resize();\n }, 200);\n window.addEventListener('resize', updateSize);\n updateSize();\n return () => {\n window.removeEventListener('resize', updateSize);\n };\n }, []);\n\n // Bind and unbind chart events passed as prop\n useEffect(() => {\n const chart = chartElement.current;\n if (!chart || onEvents === undefined) return;\n bindEvents(chart, onEvents);\n return () => {\n if (chart === undefined) return;\n if (chart.isDisposed() === true) return;\n for (const event in onEvents) {\n chart.off(event);\n }\n };\n }, [onEvents]);\n\n useEffect(() => {\n const updateSize = debounce(() => {\n if (!chartElement.current) return;\n chartElement.current.resize();\n }, 200);\n updateSize();\n }, [sx]);\n\n return (\n <Box\n ref={containerRef}\n sx={combineSx(\n {\n // Ensures chart fills container and updates size correctly when resizing,\n // combineSx allows this default behavior to be overriden from parent component\n width: '100%',\n height: '100%',\n },\n sx\n )}\n ></Box>\n );\n});\n\n// Validate event config and bind custom events\nfunction bindEvents<T>(instance: ECharts, events?: OnEventsType<T>) {\n if (events === undefined) return;\n\n function bindEvent(eventName: EventName, OnEventFunction: unknown) {\n if (typeof OnEventFunction === 'function') {\n if (isMouseEvent(eventName)) {\n instance.on(eventName, (params) => OnEventFunction(params, instance));\n } else if (isBatchEvent(eventName)) {\n instance.on(eventName, (params) => OnEventFunction(params));\n } else {\n instance.on(eventName, () => OnEventFunction(null, instance));\n }\n }\n }\n\n for (const eventName in events) {\n if (Object.prototype.hasOwnProperty.call(events, eventName)) {\n const customEvent = events[eventName as EventName] ?? null;\n if (customEvent) {\n bindEvent(eventName as EventName, customEvent);\n }\n }\n }\n}\n\nfunction isMouseEvent(eventName: EventName): eventName is MouseEventName {\n return (mouseEvents as readonly string[]).includes(eventName);\n}\n\nfunction isBatchEvent(eventName: EventName): eventName is BatchEventName {\n return (batchEvents as readonly string[]).includes(eventName);\n}\n"],"names":["React","useEffect","useLayoutEffect","useRef","init","Box","isEqual","debounce","combineSx","mouseEvents","batchEvents","EChart","memo","option","theme","renderer","sx","onEvents","_instance","onChartInitialized","initialOption","prevOption","containerRef","chartElement","current","undefined","setOption","dispose","updateSize","resize","window","addEventListener","removeEventListener","chart","bindEvents","isDisposed","event","off","ref","width","height","instance","events","bindEvent","eventName","OnEventFunction","isMouseEvent","on","params","isBatchEvent","Object","prototype","hasOwnProperty","call","customEvent","includes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/EChart/EChart.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport React, { useEffect, useLayoutEffect, useRef } from 'react';\nimport { ECharts, EChartsCoreOption, init } from 'echarts/core';\nimport { Box, SxProps, Theme } from '@mui/material';\nimport { isEqual, debounce } from 'lodash-es';\nimport { EChartsTheme } from '../model';\n\n// see docs for info about each property: https://echarts.apache.org/en/api.html#events\nexport interface MouseEventsParameters<T> {\n componentType: string;\n seriesType: string;\n seriesIndex: number;\n seriesName: string;\n name: string;\n dataIndex: number;\n data: Record<string, unknown> & T;\n dataType: string;\n value: number | number[];\n color: string;\n info: Record<string, unknown>;\n}\n\ntype OnEventFunction<T> = (\n params: MouseEventsParameters<T>,\n // This is potentially undefined for testing purposes\n instance?: ECharts\n) => void;\n\nconst mouseEvents = [\n 'click',\n 'dblclick',\n 'mousedown',\n 'mousemove',\n 'mouseup',\n 'mouseover',\n 'mouseout',\n 'globalout',\n 'contextmenu',\n] as const;\n\nexport type MouseEventName = (typeof mouseEvents)[number];\n\n// batch event types\nexport interface DataZoomPayloadBatchItem {\n dataZoomId: string;\n // start and end not returned unless dataZoom is based on percentProp,\n // which is for cases when a dataZoom component controls multiple axes\n start?: number;\n end?: number;\n // startValue and endValue return data index for 'category' axes,\n // for axis types 'value' and 'time', actual values are returned\n startValue?: number;\n endValue?: number;\n}\n\nexport interface HighlightPayloadBatchItem {\n dataIndex: number;\n dataIndexInside: number;\n seriesIndex: number;\n // highlight action can effect multiple connected charts\n escapeConnect?: boolean;\n // whether blur state was triggered\n notBlur?: boolean;\n}\n\nexport interface BatchEventsParameters {\n type: BatchEventName;\n batch: DataZoomPayloadBatchItem[] & HighlightPayloadBatchItem[];\n}\n\ntype OnBatchEventFunction = (params: BatchEventsParameters) => void;\n\nconst batchEvents = ['datazoom', 'downplay', 'highlight'] as const;\n\nexport type BatchEventName = (typeof batchEvents)[number];\n\ntype ChartEventName = 'finished';\n\ntype EventName = MouseEventName | ChartEventName | BatchEventName;\n\nexport type OnEventsType<T> = {\n [mouseEventName in MouseEventName]?: OnEventFunction<T>;\n} & {\n [batchEventName in BatchEventName]?: OnBatchEventFunction;\n} & {\n [eventName in ChartEventName]?: () => void;\n};\n\nexport interface EChartsProps<T> {\n option: EChartsCoreOption;\n theme?: string | EChartsTheme;\n renderer?: 'canvas' | 'svg';\n sx?: SxProps<Theme>;\n onEvents?: OnEventsType<T>;\n _instance?: React.MutableRefObject<ECharts | undefined>;\n onChartInitialized?: (instance: ECharts) => void;\n}\n\nexport const EChart = React.memo(function EChart<T>({\n option,\n theme,\n renderer,\n sx,\n onEvents,\n _instance,\n onChartInitialized,\n}: EChartsProps<T>) {\n const initialOption = useRef<EChartsCoreOption>(option);\n const prevOption = useRef<EChartsCoreOption>(option);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const chartElement = useRef<ECharts | null>(null);\n\n // Initialize chart, dispose on unmount\n useLayoutEffect(() => {\n if (containerRef.current === null || chartElement.current !== null) return;\n chartElement.current = init(containerRef.current, theme, { renderer: renderer ?? 'canvas' });\n if (chartElement.current === undefined) return;\n chartElement.current.setOption(initialOption.current, true);\n onChartInitialized?.(chartElement.current);\n if (_instance !== undefined) {\n _instance.current = chartElement.current;\n }\n return () => {\n if (chartElement.current === null) return;\n chartElement.current.dispose();\n chartElement.current = null;\n };\n }, [_instance, onChartInitialized, theme, renderer]);\n\n // Update chart data when option changes\n useEffect(() => {\n if (prevOption.current === undefined || isEqual(prevOption.current, option)) return;\n if (!chartElement.current) return;\n chartElement.current.setOption(option, true);\n prevOption.current = option;\n }, [option]);\n\n // Resize chart, cleanup listener on unmount\n useLayoutEffect(() => {\n const updateSize = debounce(() => {\n if (!chartElement.current) return;\n chartElement.current.resize();\n }, 200);\n window.addEventListener('resize', updateSize);\n updateSize();\n return () => {\n window.removeEventListener('resize', updateSize);\n };\n }, []);\n\n // Bind and unbind chart events passed as prop\n useEffect(() => {\n const chart = chartElement.current;\n if (!chart || onEvents === undefined) return;\n bindEvents(chart, onEvents);\n return () => {\n if (chart === undefined) return;\n if (chart.isDisposed() === true) return;\n for (const event in onEvents) {\n chart.off(event);\n }\n };\n }, [onEvents]);\n\n useEffect(() => {\n const updateSize = debounce(() => {\n if (!chartElement.current) return;\n chartElement.current.resize();\n }, 200);\n updateSize();\n }, [sx]);\n\n return <Box ref={containerRef} sx={sx}></Box>;\n});\n\n// Validate event config and bind custom events\nfunction bindEvents<T>(instance: ECharts, events?: OnEventsType<T>) {\n if (events === undefined) return;\n\n function bindEvent(eventName: EventName, OnEventFunction: unknown) {\n if (typeof OnEventFunction === 'function') {\n if (isMouseEvent(eventName)) {\n instance.on(eventName, (params) => OnEventFunction(params, instance));\n } else if (isBatchEvent(eventName)) {\n instance.on(eventName, (params) => OnEventFunction(params));\n } else {\n instance.on(eventName, () => OnEventFunction(null, instance));\n }\n }\n }\n\n for (const eventName in events) {\n if (Object.prototype.hasOwnProperty.call(events, eventName)) {\n const customEvent = events[eventName as EventName] ?? null;\n if (customEvent) {\n bindEvent(eventName as EventName, customEvent);\n }\n }\n }\n}\n\nfunction isMouseEvent(eventName: EventName): eventName is MouseEventName {\n return (mouseEvents as readonly string[]).includes(eventName);\n}\n\nfunction isBatchEvent(eventName: EventName): eventName is BatchEventName {\n return (batchEvents as readonly string[]).includes(eventName);\n}\n"],"names":["React","useEffect","useLayoutEffect","useRef","init","Box","isEqual","debounce","mouseEvents","batchEvents","EChart","memo","option","theme","renderer","sx","onEvents","_instance","onChartInitialized","initialOption","prevOption","containerRef","chartElement","current","undefined","setOption","dispose","updateSize","resize","window","addEventListener","removeEventListener","chart","bindEvents","isDisposed","event","off","ref","instance","events","bindEvent","eventName","OnEventFunction","isMouseEvent","on","params","isBatchEvent","Object","prototype","hasOwnProperty","call","customEvent","includes"],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  /// <reference types="react" />
2
- import { LegendItem } from '../model';
3
- interface CompactLegendProps {
2
+ import { LegendItem, SelectedLegendItemState } from '../model';
3
+ import { ListLegendItemProps } from './ListLegendItem';
4
+ export interface CompactLegendProps {
4
5
  height: number;
5
6
  items: LegendItem[];
7
+ selectedItems: SelectedLegendItemState;
8
+ onLegendItemClick: ListLegendItemProps['onClick'];
6
9
  }
7
10
  /**
8
11
  * CompactLegend is default and used when legend items need to show side by side
@@ -10,6 +13,5 @@ interface CompactLegendProps {
10
13
  * number of items. The `ListLegend` is used for cases with large numbers of items
11
14
  * because it is virtualized.
12
15
  */
13
- export declare function CompactLegend({ height, items }: CompactLegendProps): JSX.Element;
14
- export {};
16
+ export declare function CompactLegend({ height, items, selectedItems, onLegendItemClick }: CompactLegendProps): JSX.Element;
15
17
  //# sourceMappingURL=CompactLegend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CompactLegend.d.ts","sourceRoot":"","sources":["../../src/Legend/CompactLegend.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,kBAAkB,eAgBlE"}
1
+ {"version":3,"file":"CompactLegend.d.ts","sourceRoot":"","sources":["../../src/Legend/CompactLegend.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAgC,MAAM,UAAU,CAAC;AAC7F,OAAO,EAAkB,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,aAAa,EAAE,uBAAuB,CAAC;IACvC,iBAAiB,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;CACnD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,EAAE,kBAAkB,eAkBpG"}
@@ -12,13 +12,14 @@
12
12
  // limitations under the License.
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
14
  import { Box } from '@mui/material';
15
+ import { isLegendItemVisuallySelected } from '../model';
15
16
  import { ListLegendItem } from './ListLegendItem';
16
17
  /**
17
18
  * CompactLegend is default and used when legend items need to show side by side
18
19
  * which corresponds to when legend.position is `bottom` with a relatively small
19
20
  * number of items. The `ListLegend` is used for cases with large numbers of items
20
21
  * because it is virtualized.
21
- */ export function CompactLegend({ height , items }) {
22
+ */ export function CompactLegend({ height , items , selectedItems , onLegendItemClick }) {
22
23
  return /*#__PURE__*/ _jsx(Box, {
23
24
  component: "ul",
24
25
  sx: {
@@ -35,6 +36,8 @@ import { ListLegendItem } from './ListLegendItem';
35
36
  },
36
37
  children: items.map((item)=>/*#__PURE__*/ _jsx(ListLegendItem, {
37
38
  item: item,
39
+ isVisuallySelected: isLegendItemVisuallySelected(item, selectedItems),
40
+ onClick: onLegendItemClick,
38
41
  sx: {
39
42
  width: 'auto',
40
43
  float: 'left',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/Legend/CompactLegend.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box } from '@mui/material';\nimport { LegendItem } from '../model';\nimport { ListLegendItem } from './ListLegendItem';\n\ninterface CompactLegendProps {\n height: number;\n items: LegendItem[];\n}\n\n/**\n * CompactLegend is default and used when legend items need to show side by side\n * which corresponds to when legend.position is `bottom` with a relatively small\n * number of items. The `ListLegend` is used for cases with large numbers of items\n * because it is virtualized.\n */\nexport function CompactLegend({ height, items }: CompactLegendProps) {\n return (\n <Box component=\"ul\" sx={{ width: '100%', height, padding: [0, 1, 0, 0], overflowY: 'scroll', margin: 0 }}>\n {items.map((item) => (\n <ListLegendItem\n key={item.id}\n item={item}\n sx={{\n width: 'auto',\n float: 'left',\n paddingRight: 1.5,\n }}\n />\n ))}\n </Box>\n );\n}\n"],"names":["Box","ListLegendItem","CompactLegend","height","items","component","sx","width","padding","overflowY","margin","map","item","float","paddingRight","id"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,GAAG,QAAQ,eAAe,CAAC;AAEpC,SAASC,cAAc,QAAQ,kBAAkB,CAAC;AAOlD;;;;;CAKC,GACD,OAAO,SAASC,aAAa,CAAC,EAAEC,MAAM,CAAA,EAAEC,KAAK,CAAA,EAAsB,EAAE;IACnE,qBACE,KAACJ,GAAG;QAACK,SAAS,EAAC,IAAI;QAACC,EAAE,EAAE;YAAEC,KAAK,EAAE,MAAM;YAAEJ,MAAM;YAAEK,OAAO,EAAE;AAAC,iBAAC;AAAE,iBAAC;AAAE,iBAAC;AAAE,iBAAC;aAAC;YAAEC,SAAS,EAAE,QAAQ;YAAEC,MAAM,EAAE,CAAC;SAAE;kBACrGN,KAAK,CAACO,GAAG,CAAC,CAACC,IAAI,iBACd,KAACX,cAAc;gBAEbW,IAAI,EAAEA,IAAI;gBACVN,EAAE,EAAE;oBACFC,KAAK,EAAE,MAAM;oBACbM,KAAK,EAAE,MAAM;oBACbC,YAAY,EAAE,GAAG;iBAClB;eANIF,IAAI,CAACG,EAAE,CAOZ,AACH,CAAC;MACE,CACN;AACJ,CAAC"}
1
+ {"version":3,"sources":["../../src/Legend/CompactLegend.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box } from '@mui/material';\nimport { LegendItem, SelectedLegendItemState, isLegendItemVisuallySelected } from '../model';\nimport { ListLegendItem, ListLegendItemProps } from './ListLegendItem';\n\nexport interface CompactLegendProps {\n height: number;\n items: LegendItem[];\n selectedItems: SelectedLegendItemState;\n onLegendItemClick: ListLegendItemProps['onClick'];\n}\n\n/**\n * CompactLegend is default and used when legend items need to show side by side\n * which corresponds to when legend.position is `bottom` with a relatively small\n * number of items. The `ListLegend` is used for cases with large numbers of items\n * because it is virtualized.\n */\nexport function CompactLegend({ height, items, selectedItems, onLegendItemClick }: CompactLegendProps) {\n return (\n <Box component=\"ul\" sx={{ width: '100%', height, padding: [0, 1, 0, 0], overflowY: 'scroll', margin: 0 }}>\n {items.map((item) => (\n <ListLegendItem\n key={item.id}\n item={item}\n isVisuallySelected={isLegendItemVisuallySelected(item, selectedItems)}\n onClick={onLegendItemClick}\n sx={{\n width: 'auto',\n float: 'left',\n paddingRight: 1.5,\n }}\n />\n ))}\n </Box>\n );\n}\n"],"names":["Box","isLegendItemVisuallySelected","ListLegendItem","CompactLegend","height","items","selectedItems","onLegendItemClick","component","sx","width","padding","overflowY","margin","map","item","isVisuallySelected","onClick","float","paddingRight","id"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,GAAG,QAAQ,eAAe,CAAC;AACpC,SAA8CC,4BAA4B,QAAQ,UAAU,CAAC;AAC7F,SAASC,cAAc,QAA6B,kBAAkB,CAAC;AASvE;;;;;CAKC,GACD,OAAO,SAASC,aAAa,CAAC,EAAEC,MAAM,CAAA,EAAEC,KAAK,CAAA,EAAEC,aAAa,CAAA,EAAEC,iBAAiB,CAAA,EAAsB,EAAE;IACrG,qBACE,KAACP,GAAG;QAACQ,SAAS,EAAC,IAAI;QAACC,EAAE,EAAE;YAAEC,KAAK,EAAE,MAAM;YAAEN,MAAM;YAAEO,OAAO,EAAE;AAAC,iBAAC;AAAE,iBAAC;AAAE,iBAAC;AAAE,iBAAC;aAAC;YAAEC,SAAS,EAAE,QAAQ;YAAEC,MAAM,EAAE,CAAC;SAAE;kBACrGR,KAAK,CAACS,GAAG,CAAC,CAACC,IAAI,iBACd,KAACb,cAAc;gBAEba,IAAI,EAAEA,IAAI;gBACVC,kBAAkB,EAAEf,4BAA4B,CAACc,IAAI,EAAET,aAAa,CAAC;gBACrEW,OAAO,EAAEV,iBAAiB;gBAC1BE,EAAE,EAAE;oBACFC,KAAK,EAAE,MAAM;oBACbQ,KAAK,EAAE,MAAM;oBACbC,YAAY,EAAE,GAAG;iBAClB;eARIJ,IAAI,CAACK,EAAE,CASZ,AACH,CAAC;MACE,CACN;AACJ,CAAC"}
@@ -1,19 +1,21 @@
1
1
  /// <reference types="react" />
2
- import { LegendOptions, LegendItem } from '../model';
3
- import { ListLegendProps } from './ListLegend';
2
+ import { LegendOptions, LegendItem, SelectedLegendItemState } from '../model';
4
3
  export interface LegendProps {
5
4
  width: number;
6
5
  height: number;
7
6
  data: LegendItem[];
8
7
  options: LegendOptions;
9
8
  /**
10
- * Additional props that will be passed to the list variation of the legend
11
- * that is used when:
12
- * - The legend is positioned on the right.
13
- * - The legend has a large number of items to display and requires virtualization
14
- * to render performantly.
9
+ * State of selected items in the legend.
10
+ *
11
+ * Selected legend item state is a controlled value that should be managed using a
12
+ * combination of this prop and `onSelectedChange`.
15
13
  */
16
- listProps?: Pick<ListLegendProps, 'initialRowHeight'>;
14
+ selectedItems: SelectedLegendItemState;
15
+ /**
16
+ * Callback fired when the selected items in the legend changes.
17
+ */
18
+ onSelectedItemsChange: (newSelected: SelectedLegendItemState) => void;
17
19
  }
18
- export declare function Legend({ width, height, options, data, listProps }: LegendProps): JSX.Element;
20
+ export declare function Legend({ width, height, options, data, selectedItems, onSelectedItemsChange }: LegendProps): JSX.Element;
19
21
  //# sourceMappingURL=Legend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Legend.d.ts","sourceRoot":"","sources":["../../src/Legend/Legend.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAc,eAAe,EAAE,MAAM,cAAc,CAAC;AAG3D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IAEvB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;CACvD;AASD,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,WAAW,eAsC9E"}
1
+ {"version":3,"file":"Legend.d.ts","sourceRoot":"","sources":["../../src/Legend/Legend.tsx"],"names":[],"mappings":";AAeA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAI9E,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IAEvB;;;;;OAKG;IACH,aAAa,EAAE,uBAAuB,CAAC;IAEvC;;OAEG;IACH,qBAAqB,EAAE,CAAC,WAAW,EAAE,uBAAuB,KAAK,IAAI,CAAC;CACvE;AASD,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,qBAAqB,EAAE,EAAE,WAAW,eAiFzG"}
@@ -12,6 +12,7 @@
12
12
  // limitations under the License.
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
14
  import { Box } from '@mui/material';
15
+ import { produce } from 'immer';
15
16
  import { ListLegend } from './ListLegend';
16
17
  import { CompactLegend } from './CompactLegend';
17
18
  // When the number of items to display is above this number, it is likely to
@@ -20,7 +21,45 @@ import { CompactLegend } from './CompactLegend';
20
21
  // Set this number based on testing, but it may need to be tuned a bit on the
21
22
  // future as people test this out on different machines.
22
23
  const NEED_VIRTUALIZATION_LIMIT = 500;
23
- export function Legend({ width , height , options , data , listProps }) {
24
+ export function Legend({ width , height , options , data , selectedItems , onSelectedItemsChange }) {
25
+ const onLegendItemClick = (e, seriesId)=>{
26
+ const isModifiedClick = e.metaKey || e.shiftKey;
27
+ const newSelected = produce(selectedItems, (draft)=>{
28
+ if (draft === 'ALL') {
29
+ return {
30
+ [seriesId]: true
31
+ };
32
+ }
33
+ const isSelected = !!draft[seriesId];
34
+ // Clicks with modifier key can select multiple items.
35
+ if (isModifiedClick) {
36
+ if (isSelected) {
37
+ // Modified click on already selected item. Remove that item.
38
+ delete draft[seriesId];
39
+ } else {
40
+ // Modified click on not-selected item. Add it.
41
+ draft[seriesId] = true;
42
+ }
43
+ return draft;
44
+ }
45
+ if (isSelected) {
46
+ // Clicked item was already selected. Unselect it and return to
47
+ // ALL state.
48
+ return 'ALL';
49
+ }
50
+ // Select clicked item.
51
+ return {
52
+ [seriesId]: true
53
+ };
54
+ });
55
+ onSelectedItemsChange(newSelected);
56
+ };
57
+ const commonLegendProps = {
58
+ height,
59
+ items: data,
60
+ selectedItems,
61
+ onLegendItemClick
62
+ };
24
63
  if (options.position === 'Right') {
25
64
  return /*#__PURE__*/ _jsx(Box, {
26
65
  sx: {
@@ -31,10 +70,8 @@ export function Legend({ width , height , options , data , listProps }) {
31
70
  right: 0
32
71
  },
33
72
  children: /*#__PURE__*/ _jsx(ListLegend, {
34
- items: data,
35
- width: width,
36
- height: height,
37
- ...listProps
73
+ ...commonLegendProps,
74
+ width: width
38
75
  })
39
76
  });
40
77
  }
@@ -51,13 +88,10 @@ export function Legend({ width , height , options , data , listProps }) {
51
88
  bottom: 0
52
89
  },
53
90
  children: needsVirtualization ? /*#__PURE__*/ _jsx(ListLegend, {
54
- items: data,
55
- width: width,
56
- height: height,
57
- ...listProps
91
+ ...commonLegendProps,
92
+ width: width
58
93
  }) : /*#__PURE__*/ _jsx(CompactLegend, {
59
- items: data,
60
- height: height
94
+ ...commonLegendProps
61
95
  })
62
96
  });
63
97
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/Legend/Legend.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box } from '@mui/material';\nimport { LegendOptions, LegendItem } from '../model';\nimport { ListLegend, ListLegendProps } from './ListLegend';\nimport { CompactLegend } from './CompactLegend';\n\nexport interface LegendProps {\n width: number;\n height: number;\n data: LegendItem[];\n options: LegendOptions;\n\n /**\n * Additional props that will be passed to the list variation of the legend\n * that is used when:\n * - The legend is positioned on the right.\n * - The legend has a large number of items to display and requires virtualization\n * to render performantly.\n */\n listProps?: Pick<ListLegendProps, 'initialRowHeight'>;\n}\n\n// When the number of items to display is above this number, it is likely to\n// cause performance issues in the browser. The legend will be displayed in a\n// format (list) that allows for virtualization to minimize the performance impact.\n// Set this number based on testing, but it may need to be tuned a bit on the\n// future as people test this out on different machines.\nconst NEED_VIRTUALIZATION_LIMIT = 500;\n\nexport function Legend({ width, height, options, data, listProps }: LegendProps) {\n if (options.position === 'Right') {\n return (\n <Box\n sx={{\n width: width,\n height: height,\n position: 'absolute',\n top: 0,\n right: 0,\n }}\n >\n <ListLegend items={data} width={width} height={height} {...listProps} />\n </Box>\n );\n }\n\n // The bottom legend is displayed as a list when the number of items is too\n // large and requires virtualization. Otherwise, it is rendered more compactly.\n // We do not need this check for the right-side legend because it is always\n // a virtualized list.\n const needsVirtualization = data.length >= NEED_VIRTUALIZATION_LIMIT;\n return (\n <Box\n sx={{\n width: width,\n height: height,\n position: 'absolute',\n bottom: 0,\n }}\n >\n {needsVirtualization ? (\n <ListLegend items={data} width={width} height={height} {...listProps} />\n ) : (\n <CompactLegend items={data} height={height} />\n )}\n </Box>\n );\n}\n"],"names":["Box","ListLegend","CompactLegend","NEED_VIRTUALIZATION_LIMIT","Legend","width","height","options","data","listProps","position","sx","top","right","items","needsVirtualization","length","bottom"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,GAAG,QAAQ,eAAe,CAAC;AAEpC,SAASC,UAAU,QAAyB,cAAc,CAAC;AAC3D,SAASC,aAAa,QAAQ,iBAAiB,CAAC;AAkBhD,4EAA4E;AAC5E,6EAA6E;AAC7E,mFAAmF;AACnF,6EAA6E;AAC7E,wDAAwD;AACxD,MAAMC,yBAAyB,GAAG,GAAG,AAAC;AAEtC,OAAO,SAASC,MAAM,CAAC,EAAEC,KAAK,CAAA,EAAEC,MAAM,CAAA,EAAEC,OAAO,CAAA,EAAEC,IAAI,CAAA,EAAEC,SAAS,CAAA,EAAe,EAAE;IAC/E,IAAIF,OAAO,CAACG,QAAQ,KAAK,OAAO,EAAE;QAChC,qBACE,KAACV,GAAG;YACFW,EAAE,EAAE;gBACFN,KAAK,EAAEA,KAAK;gBACZC,MAAM,EAAEA,MAAM;gBACdI,QAAQ,EAAE,UAAU;gBACpBE,GAAG,EAAE,CAAC;gBACNC,KAAK,EAAE,CAAC;aACT;sBAED,cAAA,KAACZ,UAAU;gBAACa,KAAK,EAAEN,IAAI;gBAAEH,KAAK,EAAEA,KAAK;gBAAEC,MAAM,EAAEA,MAAM;gBAAG,GAAGG,SAAS;cAAI;UACpE,CACN;IACJ,CAAC;IAED,2EAA2E;IAC3E,+EAA+E;IAC/E,2EAA2E;IAC3E,sBAAsB;IACtB,MAAMM,mBAAmB,GAAGP,IAAI,CAACQ,MAAM,IAAIb,yBAAyB,AAAC;IACrE,qBACE,KAACH,GAAG;QACFW,EAAE,EAAE;YACFN,KAAK,EAAEA,KAAK;YACZC,MAAM,EAAEA,MAAM;YACdI,QAAQ,EAAE,UAAU;YACpBO,MAAM,EAAE,CAAC;SACV;kBAEAF,mBAAmB,iBAClB,KAACd,UAAU;YAACa,KAAK,EAAEN,IAAI;YAAEH,KAAK,EAAEA,KAAK;YAAEC,MAAM,EAAEA,MAAM;YAAG,GAAGG,SAAS;UAAI,iBAExE,KAACP,aAAa;YAACY,KAAK,EAAEN,IAAI;YAAEF,MAAM,EAAEA,MAAM;UAAI,AAC/C;MACG,CACN;AACJ,CAAC"}
1
+ {"version":3,"sources":["../../src/Legend/Legend.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box } from '@mui/material';\nimport { produce } from 'immer';\nimport { LegendOptions, LegendItem, SelectedLegendItemState } from '../model';\nimport { ListLegend, ListLegendProps } from './ListLegend';\nimport { CompactLegend, CompactLegendProps } from './CompactLegend';\n\nexport interface LegendProps {\n width: number;\n height: number;\n data: LegendItem[];\n options: LegendOptions;\n\n /**\n * State of selected items in the legend.\n *\n * Selected legend item state is a controlled value that should be managed using a\n * combination of this prop and `onSelectedChange`.\n */\n selectedItems: SelectedLegendItemState;\n\n /**\n * Callback fired when the selected items in the legend changes.\n */\n onSelectedItemsChange: (newSelected: SelectedLegendItemState) => void;\n}\n\n// When the number of items to display is above this number, it is likely to\n// cause performance issues in the browser. The legend will be displayed in a\n// format (list) that allows for virtualization to minimize the performance impact.\n// Set this number based on testing, but it may need to be tuned a bit on the\n// future as people test this out on different machines.\nconst NEED_VIRTUALIZATION_LIMIT = 500;\n\nexport function Legend({ width, height, options, data, selectedItems, onSelectedItemsChange }: LegendProps) {\n const onLegendItemClick = (e: React.MouseEvent<HTMLElement, MouseEvent>, seriesId: string) => {\n const isModifiedClick = e.metaKey || e.shiftKey;\n\n const newSelected = produce(selectedItems, (draft) => {\n if (draft === 'ALL') {\n return {\n [seriesId]: true,\n };\n }\n\n const isSelected = !!draft[seriesId];\n\n // Clicks with modifier key can select multiple items.\n if (isModifiedClick) {\n if (isSelected) {\n // Modified click on already selected item. Remove that item.\n delete draft[seriesId];\n } else {\n // Modified click on not-selected item. Add it.\n draft[seriesId] = true;\n }\n return draft;\n }\n\n if (isSelected) {\n // Clicked item was already selected. Unselect it and return to\n // ALL state.\n return 'ALL' as const;\n }\n\n // Select clicked item.\n return { [seriesId]: true };\n });\n onSelectedItemsChange(newSelected);\n };\n\n const commonLegendProps: ListLegendProps | CompactLegendProps = {\n height,\n items: data,\n selectedItems,\n onLegendItemClick,\n };\n\n if (options.position === 'Right') {\n return (\n <Box\n sx={{\n width: width,\n height: height,\n position: 'absolute',\n top: 0,\n right: 0,\n }}\n >\n <ListLegend {...commonLegendProps} width={width} />\n </Box>\n );\n }\n\n // The bottom legend is displayed as a list when the number of items is too\n // large and requires virtualization. Otherwise, it is rendered more compactly.\n // We do not need this check for the right-side legend because it is always\n // a virtualized list.\n const needsVirtualization = data.length >= NEED_VIRTUALIZATION_LIMIT;\n return (\n <Box\n sx={{\n width: width,\n height: height,\n position: 'absolute',\n bottom: 0,\n }}\n >\n {needsVirtualization ? (\n <ListLegend {...commonLegendProps} width={width} />\n ) : (\n <CompactLegend {...commonLegendProps} />\n )}\n </Box>\n );\n}\n"],"names":["Box","produce","ListLegend","CompactLegend","NEED_VIRTUALIZATION_LIMIT","Legend","width","height","options","data","selectedItems","onSelectedItemsChange","onLegendItemClick","e","seriesId","isModifiedClick","metaKey","shiftKey","newSelected","draft","isSelected","commonLegendProps","items","position","sx","top","right","needsVirtualization","length","bottom"],"mappings":"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"}
@@ -1,15 +1,12 @@
1
1
  /// <reference types="react" />
2
- import { LegendItem } from '../model';
2
+ import { LegendItem, SelectedLegendItemState } from '../model';
3
+ import { ListLegendItemProps } from './ListLegendItem';
3
4
  export interface ListLegendProps {
4
5
  items: LegendItem[];
5
6
  height: number;
6
7
  width: number;
7
- /**
8
- * The height used when initially laying out items in the list. Once items
9
- * render, the height is determined based on the content. This is needed
10
- * because the list is virtualized.
11
- */
12
- initialRowHeight?: number;
8
+ selectedItems: SelectedLegendItemState;
9
+ onLegendItemClick: ListLegendItemProps['onClick'];
13
10
  }
14
11
  /**
15
12
  * ListLegend is used when legend.position is 'right' since legend items are
@@ -17,5 +14,5 @@ export interface ListLegendProps {
17
14
  * large number of items because it is virtualized and easier to visually scan
18
15
  * large numbers of items when there is a single item per row.
19
16
  */
20
- export declare function ListLegend({ items, height, width, initialRowHeight }: ListLegendProps): JSX.Element;
17
+ export declare function ListLegend({ items, height, width, selectedItems, onLegendItemClick }: ListLegendProps): JSX.Element;
21
18
  //# sourceMappingURL=ListLegend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ListLegend.d.ts","sourceRoot":"","sources":["../../src/Legend/ListLegend.tsx"],"names":[],"mappings":";AAgBA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAID;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAA6C,EAAE,EAAE,eAAe,eAgIlH"}
1
+ {"version":3,"file":"ListLegend.d.ts","sourceRoot":"","sources":["../../src/Legend/ListLegend.tsx"],"names":[],"mappings":";AAeA,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAgC,MAAM,UAAU,CAAC;AAC7F,OAAO,EAAkB,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,uBAAuB,CAAC;IACvC,iBAAiB,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;CACnD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,EAAE,eAAe,eA6CrG"}
@@ -11,91 +11,42 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
- import { useTheme } from '@mui/material';
15
- import { VariableSizeList } from 'react-window';
16
- import { useRef, useEffect, forwardRef, useCallback } from 'react';
14
+ import { useTheme, Box } from '@mui/material';
15
+ import { Virtuoso } from 'react-virtuoso';
16
+ import { isLegendItemVisuallySelected } from '../model';
17
17
  import { ListLegendItem } from './ListLegendItem';
18
- const DEFAULT_INITIAL_ROW_HEIGHT = 26;
19
18
  /**
20
19
  * ListLegend is used when legend.position is 'right' since legend items are
21
20
  * stacked. It is also used for `bottom` positioned legends when there are a
22
21
  * large number of items because it is virtualized and easier to visually scan
23
22
  * large numbers of items when there is a single item per row.
24
- */ export function ListLegend({ items , height , width , initialRowHeight =DEFAULT_INITIAL_ROW_HEIGHT }) {
25
- // Storing a ref to the react-window `VariableSizeList`, so we can call
26
- // `resetAfterIndex` to resize the list after mouseover/out events to account
27
- // for the change in list items on hover.
28
- const listRef = useRef(null);
29
- // Storing row heights, so we can use dynamic heights, which enables the
30
- // user the hover to show the full label, while still having a virtualized
31
- // list.
32
- const rowHeights = useRef({});
23
+ */ export function ListLegend({ items , height , width , selectedItems , onLegendItemClick }) {
33
24
  const theme = useTheme();
34
- // Padding value used throughout to adjust the react-window virtual layouts
35
- // to simulate padding per the guidance from:
36
- // https://github.com/bvaughn/react-window#can-i-add-padding-to-the-top-and-bottom-of-a-list
25
+ // Padding value used in the react virtuoso header/footer components to
26
+ // simulate top/bottom padding based on recommendation in this
27
+ // issue.
28
+ // https://github.com/petyosi/react-virtuoso/issues/238
37
29
  const LIST_PADDING = parseInt(theme.spacing(1), 10);
30
+ const mockPadding = /*#__PURE__*/ _jsx(Box, {
31
+ sx: {
32
+ width: '100%',
33
+ height: `${LIST_PADDING}px`
34
+ }
35
+ });
38
36
  // show full labels on hover when there are many total series
39
37
  const truncateLabels = items.length > 5;
40
- // Gets the row height for a given item to enable the virtualized list to
41
- // render the row properly.
42
- function getRowHeight(index) {
43
- const currentHeight = rowHeights.current[index];
44
- return currentHeight !== null && currentHeight !== void 0 ? currentHeight : initialRowHeight;
45
- }
46
- // Set the height for a given item to enable the virtualized list to
47
- // adjust to size changes.
48
- function setRowHeight(index, size) {
49
- var // Tell the virtualized list that items changed size and need to be
50
- // re-evaluated.
51
- ref;
52
- (ref = listRef.current) === null || ref === void 0 ? void 0 : ref.resetAfterIndex(0);
53
- rowHeights.current = {
54
- ...rowHeights.current,
55
- [index]: size
56
- };
57
- }
58
- // Renderer for virtualized rows in `VariableSizeList`.
59
- function ListLegendRow({ index , style }) {
60
- // Storing a ref to the row's `ListLegendItem`, so we can get the "real"
61
- // height and adjust the height of the row based on it, enabling the dynamic
62
- // heights on hover.
63
- const rowRef = useRef(null);
64
- // useCallback is important here to avoid constantly running the useEffect
65
- // that calls this in `ListLegendItem`.
66
- const handleRowLayoutChange = useCallback(()=>{
67
- // Handle size changes from hovering on a list item.
68
- if (rowRef.current) {
69
- setRowHeight(index, rowRef.current.clientHeight);
70
- }
71
- }, [
72
- index
73
- ]);
74
- // Adjust row heights when the row being rendered changes.
75
- useEffect(()=>{
76
- handleRowLayoutChange();
77
- }, [
78
- handleRowLayoutChange
79
- ]);
80
- const item = items[index];
81
- if (!item) {
82
- // This shouldn't happen if configured correctly, but covering
83
- // the case to appease the type checking and to cover any edge
84
- // cases.
85
- return null;
86
- }
87
- const originalTop = parseFloat(`${style.top}`);
88
- return /*#__PURE__*/ _jsx("div", {
89
- style: {
90
- ...style,
91
- // Adjust the top position to simulate top padding on the list.
92
- top: `${originalTop + LIST_PADDING}px`
93
- },
94
- children: /*#__PURE__*/ _jsx(ListLegendItem, {
95
- ref: rowRef,
38
+ return /*#__PURE__*/ _jsx(Virtuoso, {
39
+ style: {
40
+ height,
41
+ width
42
+ },
43
+ data: items,
44
+ itemContent: (index, item)=>{
45
+ return /*#__PURE__*/ _jsx(ListLegendItem, {
96
46
  item: item,
97
47
  truncateLabel: truncateLabels,
98
- onLayoutChange: handleRowLayoutChange,
48
+ isVisuallySelected: isLegendItemVisuallySelected(item, selectedItems),
49
+ onClick: onLegendItemClick,
99
50
  sx: {
100
51
  // Having an explicit width is important for the ellipsizing to
101
52
  // work correctly. Subtract padding to simulate padding.
@@ -103,33 +54,17 @@ const DEFAULT_INITIAL_ROW_HEIGHT = 26;
103
54
  wordBreak: 'break-word',
104
55
  overflow: 'hidden'
105
56
  }
106
- }, item.id)
107
- });
108
- }
109
- // Renderer for the inner container element of the `VariableSizeList` used
110
- // to adjust styles to simulate padding on the list per:
111
- // https://github.com/bvaughn/react-window#can-i-add-padding-to-the-top-and-bottom-of-a-list
112
- const InnerElementType = /*#__PURE__*/ forwardRef(function InnerElementType({ style , ...rest }, ref) {
113
- const originalHeight = (style === null || style === void 0 ? void 0 : style.height) ? parseFloat(`${style === null || style === void 0 ? void 0 : style.height}`) : 0;
114
- return /*#__PURE__*/ _jsx("div", {
115
- ref: ref,
116
- role: "list",
117
- style: {
118
- ...style,
119
- // Adjust height to account for simulated padding.
120
- height: `${originalHeight + LIST_PADDING * 2}px`
57
+ }, item.id);
58
+ },
59
+ role: "list",
60
+ components: {
61
+ Header: ()=>{
62
+ return mockPadding;
121
63
  },
122
- ...rest
123
- });
124
- });
125
- return /*#__PURE__*/ _jsx(VariableSizeList, {
126
- height: height,
127
- width: width,
128
- itemCount: items.length,
129
- itemSize: getRowHeight,
130
- innerElementType: InnerElementType,
131
- ref: listRef,
132
- children: ListLegendRow
64
+ Footer: ()=>{
65
+ return mockPadding;
66
+ }
67
+ }
133
68
  });
134
69
  }
135
70