@flowfuse/node-red-dashboard 0.7.1 → 0.7.2-1aface9-202311080934.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 (72) hide show
  1. package/nodes/config/locales/en-US/ui_base.json +1 -0
  2. package/nodes/config/ui_base.html +20 -9
  3. package/nodes/config/ui_page.js +8 -2
  4. package/nodes/widgets/locales/en-US/ui_chart.html +1 -1
  5. package/nodes/widgets/ui_chart.html +13 -1
  6. package/nodes/widgets/ui_chart.js +38 -2
  7. package/package.json +2 -2
  8. package/dist/css/app.a12b8d13.css +0 -1
  9. package/dist/css/chunk-vendors.d640933c.css +0 -24
  10. package/dist/fonts/materialdesignicons-webfont.015e7571.ttf +0 -0
  11. package/dist/fonts/materialdesignicons-webfont.43f2dfd1.woff2 +0 -0
  12. package/dist/fonts/materialdesignicons-webfont.52fd8e4e.woff +0 -0
  13. package/dist/fonts/materialdesignicons-webfont.85d55efc.eot +0 -0
  14. package/dist/index.html +0 -1
  15. package/dist/js/113.9435c05e.js +0 -2
  16. package/dist/js/113.9435c05e.js.map +0 -1
  17. package/dist/js/125.f44ecd48.js +0 -2
  18. package/dist/js/125.f44ecd48.js.map +0 -1
  19. package/dist/js/155.865607ad.js +0 -2
  20. package/dist/js/155.865607ad.js.map +0 -1
  21. package/dist/js/237.8be4f4fb.js +0 -2
  22. package/dist/js/237.8be4f4fb.js.map +0 -1
  23. package/dist/js/246.77cea976.js +0 -2
  24. package/dist/js/246.77cea976.js.map +0 -1
  25. package/dist/js/306.4f33ff03.js +0 -2
  26. package/dist/js/306.4f33ff03.js.map +0 -1
  27. package/dist/js/31.92ce1043.js +0 -7
  28. package/dist/js/31.92ce1043.js.map +0 -1
  29. package/dist/js/319.fae6367a.js +0 -2
  30. package/dist/js/319.fae6367a.js.map +0 -1
  31. package/dist/js/339.9940fe4a.js +0 -2
  32. package/dist/js/339.9940fe4a.js.map +0 -1
  33. package/dist/js/438.9fd1d179.js +0 -2
  34. package/dist/js/438.9fd1d179.js.map +0 -1
  35. package/dist/js/453.a0fa883a.js +0 -2
  36. package/dist/js/453.a0fa883a.js.map +0 -1
  37. package/dist/js/456.6f7a9e1d.js +0 -2
  38. package/dist/js/456.6f7a9e1d.js.map +0 -1
  39. package/dist/js/476.cfc3b521.js +0 -2
  40. package/dist/js/476.cfc3b521.js.map +0 -1
  41. package/dist/js/555.f63e7df7.js +0 -2
  42. package/dist/js/555.f63e7df7.js.map +0 -1
  43. package/dist/js/594.39ea89d6.js +0 -2
  44. package/dist/js/594.39ea89d6.js.map +0 -1
  45. package/dist/js/652.55d24c91.js +0 -2
  46. package/dist/js/652.55d24c91.js.map +0 -1
  47. package/dist/js/655.97235dc5.js +0 -2
  48. package/dist/js/655.97235dc5.js.map +0 -1
  49. package/dist/js/701.c2b2e3ac.js +0 -2
  50. package/dist/js/701.c2b2e3ac.js.map +0 -1
  51. package/dist/js/748.3df08143.js +0 -2
  52. package/dist/js/748.3df08143.js.map +0 -1
  53. package/dist/js/750.7bc3d542.js +0 -2
  54. package/dist/js/750.7bc3d542.js.map +0 -1
  55. package/dist/js/753.e630e04c.js +0 -2
  56. package/dist/js/753.e630e04c.js.map +0 -1
  57. package/dist/js/850.ee07f2c9.js +0 -2
  58. package/dist/js/850.ee07f2c9.js.map +0 -1
  59. package/dist/js/861.c063f0f8.js +0 -2
  60. package/dist/js/861.c063f0f8.js.map +0 -1
  61. package/dist/js/866.1af22532.js +0 -2
  62. package/dist/js/866.1af22532.js.map +0 -1
  63. package/dist/js/874.0002f35c.js +0 -2
  64. package/dist/js/874.0002f35c.js.map +0 -1
  65. package/dist/js/910.1b89871d.js +0 -2
  66. package/dist/js/910.1b89871d.js.map +0 -1
  67. package/dist/js/994.09b3e0e9.js +0 -2
  68. package/dist/js/994.09b3e0e9.js.map +0 -1
  69. package/dist/js/app.e255b134.js +0 -2
  70. package/dist/js/app.e255b134.js.map +0 -1
  71. package/dist/js/chunk-vendors.a7618205.js +0 -50
  72. package/dist/js/chunk-vendors.a7618205.js.map +0 -1
@@ -7,6 +7,7 @@
7
7
  "layout": {
8
8
  "pages": "Pages",
9
9
  "edit": "Edit",
10
+ "focus": "Focus",
10
11
  "collapse": "Collapse",
11
12
  "expand": "Expand"
12
13
  },
@@ -79,6 +79,8 @@
79
79
  .nrdb2-sb-list-header-button-group {
80
80
  position: absolute;
81
81
  right: 1rem;
82
+ display: flex;
83
+ gap: 4px;
82
84
  }
83
85
  .nrdb2-sb-list-header-button-group,
84
86
  .nrdb2-sb-list-handle {
@@ -110,7 +112,7 @@
110
112
 
111
113
  // convert to i18 text
112
114
  function c_ (x) {
113
- return RED._('@flowforge/node-red-dashboard/ui-base:ui-base.' + x)
115
+ return RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.' + x)
114
116
  }
115
117
 
116
118
  function hasProperty (obj, prop) {
@@ -258,10 +260,19 @@
258
260
  * @param {Object} row - The page/group/widget that these actions are bound to
259
261
  */
260
262
  function addRowActions (row, item) {
263
+ const configNodes = ['ui-base', 'ui-page', 'ui-group']
261
264
  const btnGroup = $('<div>', { class: 'nrdb2-sb-list-header-button-group', id: item.id }).appendTo(row)
262
- const editButton = $('<a href="#" class="nr-db-sb-tab-edit-button editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-pencil"></i> ' + c_('layout.edit') + '</a>').appendTo(btnGroup)
265
+ if (!configNodes.includes(item.type)) {
266
+ const focusButton = $('<a href="#" class="nr-db-sb-tab-focus-button editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-bullseye"></i> ' + c_('layout.focus') + '</a>').appendTo(btnGroup)
267
+ focusButton.on('click', function (evt) {
268
+ RED.view.reveal(item.id)
269
+ evt.stopPropagation()
270
+ evt.preventDefault()
271
+ })
272
+ }
273
+ const editButton = $('<a href="#" class="nr-db-sb-tab-edit-button editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-pencil"></i> ' + c_('layout.edit') + '</a>').appendTo(btnGroup)
263
274
  editButton.on('click', function (evt) {
264
- if (item.type === 'ui-page' || item.type === 'ui-group') {
275
+ if (configNodes.includes(item.type)) {
265
276
  RED.editor.editConfig('', item.type, item.id)
266
277
  } else {
267
278
  RED.editor.edit(item)
@@ -348,8 +359,8 @@
348
359
  const titleRow = $('<div>', { class: 'nrdb2-sb-list-header nrdb2-sb-widgets-list-header' }).appendTo(container)
349
360
  $('<i class="nrdb2-sb-list-handle nrdb2-sb-widget-list-handle fa fa-bars"></i>').appendTo(titleRow)
350
361
 
351
- const groupicon = 'fa-image'
352
- $('<i>', { class: 'nrdb2-sb-icon nrdb2-sb-widget-icon fa ' + groupicon }).appendTo(titleRow)
362
+ const widgeticon = 'fa-image'
363
+ $('<i>', { class: 'nrdb2-sb-icon nrdb2-sb-widget-icon fa ' + widgeticon }).appendTo(titleRow)
353
364
  $('<span>', { class: 'nrdb2-sb-title' }).text(widget.name || widget.label || widget.type || widget.id).appendTo(titleRow)
354
365
 
355
366
  addRowActions(titleRow, widget)
@@ -572,7 +583,7 @@
572
583
  pinned: true,
573
584
  disableOnEdit: true,
574
585
  iconClass: 'fa fa-bar-chart',
575
- action: '@flowforge/node-red-dashboard:show-dashboard-2.0-tab',
586
+ action: '@flowfuse/node-red-dashboard:show-dashboard-2.0-tab',
576
587
  onchange: function () {
577
588
  sidebar.empty()
578
589
  RED.nodes.eachConfig(function (n) {
@@ -586,8 +597,8 @@
586
597
  }
587
598
  })
588
599
 
589
- RED.actions.add('@flowforge/node-red-dashboard:show-dashboard-2.0-tab', function () {
590
- RED.sidebar.show('flowforge-nr-tools')
600
+ RED.actions.add('@flowfuse/node-red-dashboard:show-dashboard-2.0-tab', function () {
601
+ RED.sidebar.show('flowfuse-nr-tools')
591
602
  })
592
603
 
593
604
  /**
@@ -597,7 +608,7 @@
597
608
  _create: function () {
598
609
  // convert to i18 text
599
610
  function c_ (x) {
600
- return RED._(`@flowforge/node-red-dashboard/ui-base:ui-base.${x}`)
611
+ return RED._(`@flowfuse/node-red-dashboard/ui-base:ui-base.${x}`)
601
612
  }
602
613
 
603
614
  const thisWidget = this
@@ -21,12 +21,18 @@ module.exports = function (RED) {
21
21
  node.register = function (group, widgetNode, widgetConfig, widgetEvents) {
22
22
  const ui = RED.nodes.getNode(config.ui)
23
23
  const page = config
24
- ui.register(page, group, widgetNode, widgetConfig, widgetEvents)
24
+ if (ui) {
25
+ ui.register(page, group, widgetNode, widgetConfig, widgetEvents)
26
+ } else {
27
+ node.error(`Error registering Widget - ${widgetNode.name || widgetNode.id}. No parent ui-base node found for ui-page node: ${(page.name || page.id)}`)
28
+ }
25
29
  }
26
30
  node.deregister = function (group, widgetNode) {
27
31
  const ui = RED.nodes.getNode(config.ui)
28
32
  const page = config
29
- ui.deregister(page, group, widgetNode)
33
+ if (ui) {
34
+ ui.deregister(page, group, widgetNode)
35
+ }
30
36
  }
31
37
  }
32
38
  RED.nodes.registerType('ui-page', UIPageNode)
@@ -16,7 +16,7 @@
16
16
  </dd>
17
17
  <dt>Properties <span class="property-type">string</span></dt>
18
18
  <dd>
19
- <p><b>Series:</b> Controls how you want to set the Series of data stream into this widget. The default is <code>msg.topic</code>, where separate topics will render to a new line/bar in their respective plots.</p>
19
+ <p><b>Series:</b> Controls how you want to set the Series of data stream into this widget. The default is <code>msg.topic</code>, where separate topics will render to a new line/bar in their respective plots. You can also provide a JSON array, which will plot multiple data points from a single msg object.</p>
20
20
  <p><b>X:</b> Only available for Line & Scatter Charts. This defines the key (which can be nested) of the value that should be plotted onto the x-axis. If left blank, the x-value will be calculated as the current timestamp.</p>
21
21
  <p><b>Y:</b> Defines the key (which can be nested, e.g. <code>'nested.value'</code>) of the value that should be plotted onto the x-axis. This value is ignored if injecting single numerical values into the chart.</p>
22
22
  </dd>
@@ -130,7 +130,7 @@
130
130
  $('#node-input-category').typedInput({
131
131
  default: 'msg',
132
132
  typeField: $('#node-input-categoryType'),
133
- types: ['msg', 'str', propertyType]
133
+ types: ['msg', 'str', 'json', propertyType]
134
134
  })
135
135
  $('#node-input-xAxisProperty').typedInput({
136
136
  default: propertyType.value,
@@ -178,6 +178,18 @@
178
178
  $('#x-axis-show').hide()
179
179
  }
180
180
  })
181
+
182
+ // handle event when chart's type is changed
183
+ $('#node-input-category').change((evt) => {
184
+ const categoryType = $('#node-input-categoryType').val()
185
+
186
+ if (categoryType === 'json') {
187
+ // hide y-axis proepty setting as category will now control that
188
+ $('#node-container-yAxisProperty').hide()
189
+ } else {
190
+ $('#node-container-yAxisProperty').show()
191
+ }
192
+ })
181
193
 
182
194
  // Series Color Pickers
183
195
  const setColor = function (id, value) {
@@ -21,6 +21,8 @@ module.exports = function (RED) {
21
21
  }
22
22
 
23
23
  const evts = {
24
+ // beforeSend will run before messages are sent client-side, as well as before sending on within Node-RED
25
+ // here, we use it to pre-process chart data to format it ready for plotting
24
26
  beforeSend: function (msg) {
25
27
  const p = msg.payload
26
28
 
@@ -46,7 +48,19 @@ module.exports = function (RED) {
46
48
  })
47
49
  } else {
48
50
  // single point
49
- msg._datapoint = addToLine(p, series)
51
+ if (config.categoryType === 'json') {
52
+ // we can produce multiple datapoints from a single object/value here
53
+ const points = []
54
+ series.forEach((s) => {
55
+ if (s in p) {
56
+ const datapoint = addToLine(p, s)
57
+ points.push(datapoint)
58
+ }
59
+ })
60
+ msg._datapoint = points
61
+ } else {
62
+ msg._datapoint = addToLine(p, series)
63
+ }
50
64
  }
51
65
  } else if (config.chartType === 'bar') {
52
66
  // single point or array of data?
@@ -66,6 +80,7 @@ module.exports = function (RED) {
66
80
 
67
81
  // function to process a data point being appended to a line/scatter chart
68
82
  function addToLine (payload, series) {
83
+ console.log(payload, series)
69
84
  const datapoint = {}
70
85
  datapoint.category = series
71
86
  // construct our datapoint
@@ -76,11 +91,21 @@ module.exports = function (RED) {
76
91
  } else if (typeof payload === 'object') {
77
92
  // may have been given an x/y object already
78
93
  let x = getProperty(payload, config.xAxisProperty)
94
+ let y = payload.y
79
95
  if (x === undefined || x === null) {
80
96
  x = (new Date()).getTime()
81
97
  }
98
+ if (Array.isArray(series)) {
99
+ if (series.length > 1) {
100
+ y = series.map((s) => {
101
+ return getProperty(payload, s)
102
+ })
103
+ } else {
104
+ y = getProperty(payload, series[0])
105
+ }
106
+ }
82
107
  datapoint.x = x
83
- datapoint.y = payload.y
108
+ datapoint.y = y
84
109
  }
85
110
  return datapoint
86
111
  }
@@ -92,6 +117,17 @@ module.exports = function (RED) {
92
117
  if (typeof payload === 'number') {
93
118
  datapoint.y = payload
94
119
  }
120
+ if (Array.isArray(series)) {
121
+ let y = null
122
+ if (series.length > 1) {
123
+ y = series.map((s) => {
124
+ return getProperty(payload, s)
125
+ })
126
+ } else {
127
+ y = getProperty(payload, series[0])
128
+ }
129
+ datapoint.y = y
130
+ }
95
131
  return datapoint
96
132
  }
97
133
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@flowfuse/node-red-dashboard",
3
3
  "homepage": "https://dashboard.flowfuse.com",
4
- "version": "0.7.1",
4
+ "version": "0.7.2-1aface9-202311080934.0",
5
5
  "description": "A collection of Node-RED nodes that provide functionality to build your own UI applications (inc. forms, buttons, charts) within Node-RED.",
6
6
  "author": {
7
7
  "name": "Joe Pavitt",
@@ -99,7 +99,7 @@
99
99
  },
100
100
  "overrides": {
101
101
  "node-red-node-test-helper": {
102
- "semver": "^7.5.4"
102
+ "semver": "^7.5.4"
103
103
  }
104
104
  },
105
105
  "browserslist": [
@@ -1 +0,0 @@
1
- :deep(.v-field__input){--v-field-input-min-height:calc(var(--widget-row-height) - 4px);--v-field-input-padding-top:12px;--v-field-input-padding-bottom:12px}:deep(.v-input--horizontal){grid-template-areas:"prepend control append";grid-template-rows:auto}.nr-db-layout-group--grid{grid-auto-rows:minmax(var(--widget-row-height),auto);padding:0;grid-template-columns:repeat(6,1fr);display:grid;flex-wrap:wrap;padding:var(--layout-gap);gap:var(--layout-gap)}.nrdb-layout--flex[data-v-194d4b32]{--layout-card-width:320px;--layout-gap:12px;display:flex;flex-wrap:wrap;padding:var(--layout-gap);gap:var(--layout-gap)}.nrdb-layout--flex>div[data-v-194d4b32]{width:var(--layout-card-width);max-width:100%}.v-card[data-v-194d4b32]{width:100%}.nrdb-layout--grid[data-v-6b3c6e9c]{--layout-card-width:320px;--layout-gap:12px;--widget-row-height:48px;display:grid;grid-template-columns:repeat(12,1fr);flex-wrap:wrap;padding:var(--layout-gap);gap:var(--layout-gap)}.nrdb-layout--grid>div[data-v-6b3c6e9c],.v-card[data-v-6b3c6e9c]{width:100%}@media only screen and (max-width:1024px){.nrdb-layout--grid[data-v-6b3c6e9c]{grid-template-columns:repeat(9,1fr)}}@media only screen and (max-width:768px){.nrdb-layout--grid[data-v-6b3c6e9c]{grid-template-columns:repeat(6,1fr)}}.nrdb-layout--notebook[data-v-a95d5376]{--layout-card-width:1024px;--layout-gap:12px;margin:auto;width:100%;max-width:var(--layout-card-width);min-height:100%;flex-wrap:wrap;padding:var(--layout-gap)}.nrdb-layout--notebook>div[data-v-a95d5376]{width:100%;margin-bottom:var(--layout-gap)}.v-card[data-v-a95d5376]{width:100%}.nrdb-table-nodata{text-align:center}.nrdb-table-nodata td{opacity:.5}.nrdb-switch{display:flex;align-items:center;justify-content:space-between}.nrdb-switch label{flex-grow:1}.nrdb-switch .v-selection-control{justify-content:flex-end}.nrdb-switch.nrdb-nolabel .v-selection-control{justify-content:center}.nrdb-ui-notification{padding-top:64px}.nrdb-ui-notification .v-snackbar__wrapper{background-color:rgb(var(--v-theme-group-background));color:rgb(var(--v-theme-on-group-background));border-left:6px solid var(--nrdb-ui-notification-color)}.nrdb-ui-notification .v-snackbar__content{padding-left:8px}.nrdb-ui-notification-countdown{position:absolute;width:calc(100% + 6px);top:0;left:0;margin-left:-6px;border-top-left-radius:4px}.nrdb-ui-notification h1,.nrdb-ui-notification h2,.nrdb-ui-notification h3,.nrdb-ui-notification h4{margin:.5rem 0}.nrdb-ui-text[data-v-14b9f4fa]{display:flex;flex-direction:row;gap:2px}.nrdb-ui-text-value[data-v-14b9f4fa]{font-weight:600}.nrdb-ui-text--row-left[data-v-14b9f4fa]{align-items:center;justify-content:flex-start}.nrdb-ui-text--row-center[data-v-14b9f4fa]{align-items:center;justify-content:center}.nrdb-ui-text--row-center label[data-v-14b9f4fa],.nrdb-ui-text--row-center span[data-v-14b9f4fa]{text-align:center}.nrdb-ui-text--row-right[data-v-14b9f4fa]{align-items:center;justify-content:flex-end}.nrdb-ui-text--row-spread[data-v-14b9f4fa]{align-items:center;justify-content:space-between}.nrdb-ui-text--col-center[data-v-14b9f4fa]{align-items:center;justify-content:center;flex-direction:column}:root{--nrdb-bg-color:#222;--nrdb-text-color:#fff;--nrdb-font-family:Helvtiva;--nrdb-header-bg:red;--nrdb-header-padding:6px 12px;--nrdb-header-text-color:#fff;--nrdb-main-padding:12px;--widget-row-height:42px}body{margin:0;font-family:Helvetica;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:var(--nrdb-bg-color);color:var(--nrdb-text-color)}main{padding:var(--nrdb-main-padding)}.nrdb-ui-widget{min-height:var(--widget-row-height)}.v-btn{text-transform:none}.nrdb-ui-form-label{font-weight:700;margin-bottom:1rem}.nrdb-ui-form-rows{display:grid;gap:.5rem}.nrdb-ui-form-rows--split{grid-template-columns:1fr 1fr}.nrdb-ui-form-row{margin-bottom:.25rem;display:flex;align-items:center}.nrdb-ui-form-row .nrdb-ui-widget,.nrdb-ui-form-row .v-selection-control{min-height:0}.nrdb-ui-form-actions{margin-top:1rem}.nrdb-ui-form-actions button{margin-right:1rem}.nrdb-ui-form-row .v-text-field .v-input__details{-webkit-padding-start:0;padding-inline-start:0}.nrdb-ui-radio-group .v-selection-control-group{display:grid}.nrdb-ui-radio-group .v-selection-control-group .v-selection-control{grid-area:initial}.nrdb-ui-radio-group.nrdb-ui-radio-group--cols-2 .v-selection-control-group{grid-template-columns:repeat(2,1fr)}.nrdb-ui-radio-group.nrdb-ui-radio-group--cols-3 .v-selection-control-group{grid-template-columns:repeat(3,1fr)}.nrdb-ui-radio-group.nrdb-ui-radio-group--cols-4 .v-selection-control-group{grid-template-columns:repeat(4,1fr)}.nrdb-ui-radio-group.nrdb-ui-radio-group--cols-5 .v-selection-control-group{grid-template-columns:repeat(5,1fr)}.nrdb-ui-markdown h1{margin:.67em 0}.nrdb-ui-markdown p{margin:1em 0}.nrdb-ui-markdown>:first-child{margin-top:0!important}.nrdb-ui-markdown blockquote,.nrdb-ui-markdown details,.nrdb-ui-markdown dl,.nrdb-ui-markdown ol,.nrdb-ui-markdown p,.nrdb-ui-markdown pre,.nrdb-ui-markdown table,.nrdb-ui-markdown ul{margin-top:0;margin-bottom:1rem}.nrdb-ui-markdown h1,.nrdb-ui-markdown h2,.nrdb-ui-markdown h3,.nrdb-ui-markdown h4,.nrdb-ui-markdown h5,.nrdb-ui-markdown h6{margin-top:1.5rem;margin-bottom:1rem;font-weight:600;line-height:1.25}.nrdb-ui-markdown ol,.nrdb-ui-markdown ul{padding-left:2em}.nrdb-ui-markdown hr{margin:1rem 0}.nrdb-ui-markdown ol ol,.nrdb-ui-markdown ol ul,.nrdb-ui-markdown ul ol,.nrdb-ui-markdown ul ul{margin-top:0;margin-bottom:0}.nrdb-ui-markdown code{background:#f3f3f3;font-size:.85rem}.nrdb-ui-markdown pre code{overflow:auto;line-height:1.25rem;border-radius:6px}.nrdb-ui-markdown blockquote{padding-left:1em;border-left:4px solid #d1d1d1;color:gray}.nrdb-ui-markdown table{border-collapse:collapse;border-spacing:0;margin:.5em 0;width:100%;overflow:auto;width:-moz-max-content;width:max-content}.nrdb-ui-markdown table th{font-weight:700}.nrdb-ui-markdown table td,.nrdb-ui-markdown table th{padding:.5em .5em;border:1px solid #d1d1d1}.v-list-item--active{background-color:var(--v-theme-background)}.v-btn--variant-elevated,.v-btn--variant-flat,.v-btn-group .v-btn--variant-elevated.v-btn--active,.v-btn-group .v-btn--variant-flat.v-btn--active{background-color:rgb(var(--v-theme-primary));color:rgb(var(--v-theme-on-primary))}.v-btn-group .v-btn--variant-elevated,.v-btn-group .v-btn--variant-flat{background-color:rgb(var(--v-theme-surface));color:rgb(var(--v-theme-on-surface))}.v-btn-group .v-btn{flex-grow:1}.v-card{border:1px solid rgb(var(--v-theme-group-outline))}.v-field--variant-outlined.v-field--focused .v-field__outline__end,.v-field--variant-outlined.v-field--focused .v-field__outline__notch:after,.v-field--variant-outlined.v-field--focused .v-field__outline__notch:before,.v-field--variant-outlined.v-field--focused .v-field__outline__start{border-color:rgb(var(--v-theme-primary))}.v-menu>.v-overlay__content>.v-card,.v-menu>.v-overlay__content>.v-list,.v-menu>.v-overlay__content>.v-sheet{background:rgb(var(--v-theme-background));color:rgb(var(--v-theme-on-background))}.v-slider-thumb__surface,.v-slider-track__background,.v-slider-track__fill,.v-slider-track__tick{background-color:rgb(var(--v-theme-primary))}.v-switch__track{opacity:.3}.v-switch__thumb{color:rgb(var(--v-theme-surface-variant))}.active .v-switch__track{opacity:.6}.active .v-switch__thumb{opacity:1}.v-table{background:rgb(var(--v-theme-group-background))}.v-table,.v-table .v-table__wrapper>table>thead>tr>th{color:rgb(var(--v-theme-on-group-background))}.v-table .v-table__wrapper>table>thead>tr>th{font-weight:600}