@mongoosejs/studio 0.3.5 → 0.3.7

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 (37) hide show
  1. package/backend/actions/ChatThread/createChatMessage.js +12 -2
  2. package/backend/actions/ChatThread/streamChatMessage.js +12 -2
  3. package/backend/actions/Model/createChatMessage.js +12 -2
  4. package/backend/actions/Model/streamChatMessage.js +13 -2
  5. package/backend/actions/Task/getTasksOverTime.js +66 -0
  6. package/backend/actions/Task/index.js +1 -0
  7. package/frontend/public/app.js +809 -110
  8. package/frontend/public/tw.css +19 -16
  9. package/frontend/src/api.js +6 -0
  10. package/frontend/src/chat/chat.html +19 -12
  11. package/frontend/src/chat/chat.js +9 -3
  12. package/frontend/src/create-document/create-document.js +3 -1
  13. package/frontend/src/dashboard-result/dashboard-primitive/dashboard-primitive.html +2 -2
  14. package/frontend/src/dashboard-result/dashboard-primitive/dashboard-primitive.js +13 -1
  15. package/frontend/src/dashboard-result/dashboard-result.html +1 -1
  16. package/frontend/src/dashboard-result/dashboard-table/dashboard-table.html +21 -1
  17. package/frontend/src/dashboard-result/dashboard-table/dashboard-table.js +52 -0
  18. package/frontend/src/detail-date/detail-date.html +1 -0
  19. package/frontend/src/detail-date/detail-date.js +123 -0
  20. package/frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.html +26 -0
  21. package/frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.js +41 -0
  22. package/frontend/src/document-details/document-property/document-property.html +13 -5
  23. package/frontend/src/document-details/document-property/document-property.js +14 -1
  24. package/frontend/src/getCurrentDateTimeContext.js +17 -0
  25. package/frontend/src/list-json/list-json.js +0 -7
  26. package/frontend/src/modal/modal.js +25 -1
  27. package/frontend/src/models/document-search/document-search.js +3 -0
  28. package/frontend/src/models/models.html +25 -5
  29. package/frontend/src/models/models.js +1 -1
  30. package/frontend/src/navbar/navbar.html +6 -1
  31. package/frontend/src/navbar/navbar.js +1 -6
  32. package/frontend/src/pro-upgrade-modal/pro-upgrade-modal.html +38 -0
  33. package/frontend/src/pro-upgrade-modal/pro-upgrade-modal.js +23 -0
  34. package/frontend/src/tasks/tasks.html +34 -20
  35. package/frontend/src/tasks/tasks.js +158 -5
  36. package/local.js +2 -1
  37. package/package.json +2 -1
@@ -814,6 +814,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
814
814
  getTaskOverview: function getTaskOverview(params) {
815
815
  return client.post('', { action: 'Task.getTaskOverview', ...params }).then(res => res.data);
816
816
  },
817
+ getTasksOverTime: function getTasksOverTime(params) {
818
+ return client.post('', { action: 'Task.getTasksOverTime', ...params }).then(res => res.data);
819
+ },
817
820
  rescheduleTask: function rescheduleTask(params) {
818
821
  return client.post('', { action: 'Task.rescheduleTask', ...params }).then(res => res.data);
819
822
  },
@@ -1154,6 +1157,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
1154
1157
  getTaskOverview: function getTaskOverview(params) {
1155
1158
  return client.post('/Task/getTaskOverview', params).then(res => res.data);
1156
1159
  },
1160
+ getTasksOverTime: function getTasksOverTime(params) {
1161
+ return client.post('/Task/getTasksOverTime', params).then(res => res.data);
1162
+ },
1157
1163
  rescheduleTask: function rescheduleTask(params) {
1158
1164
  return client.post('/Task/rescheduleTask', params).then(res => res.data);
1159
1165
  },
@@ -1637,6 +1643,7 @@ module.exports = app => app.component('chat-message', {
1637
1643
 
1638
1644
 
1639
1645
  const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
1646
+ const getCurrentDateTimeContext = __webpack_require__(/*! ../getCurrentDateTimeContext */ "./frontend/src/getCurrentDateTimeContext.js");
1640
1647
  const template = __webpack_require__(/*! ./chat.html */ "./frontend/src/chat/chat.html");
1641
1648
 
1642
1649
  module.exports = {
@@ -1651,7 +1658,8 @@ module.exports = {
1651
1658
  chatMessages: [],
1652
1659
  hideSidebar: null,
1653
1660
  sharingThread: false,
1654
- threadSearch: ''
1661
+ threadSearch: '',
1662
+ showProUpgradeModal: false
1655
1663
  }),
1656
1664
  methods: {
1657
1665
  async sendMessage() {
@@ -1680,7 +1688,11 @@ module.exports = {
1680
1688
  }
1681
1689
  });
1682
1690
 
1683
- const params = { chatThreadId: this.chatThreadId, content };
1691
+ const params = {
1692
+ chatThreadId: this.chatThreadId,
1693
+ content,
1694
+ currentDateTime: getCurrentDateTimeContext()
1695
+ };
1684
1696
  let userChatMessage = null;
1685
1697
  let assistantChatMessage = null;
1686
1698
  for await (const event of api.ChatThread.streamChatMessage(params)) {
@@ -1787,7 +1799,7 @@ module.exports = {
1787
1799
  },
1788
1800
  async toggleShareThread() {
1789
1801
  if (!this.chatThreadId || !this.hasWorkspace) {
1790
- return;
1802
+ throw new Error('Cannot share thread: chatThreadId or hasWorkspace is missing');
1791
1803
  }
1792
1804
  this.sharingThread = true;
1793
1805
  try {
@@ -2001,6 +2013,7 @@ const ObjectId = new Proxy(BSON.ObjectId, {
2001
2013
  });
2002
2014
 
2003
2015
  const appendCSS = __webpack_require__(/*! ../appendCSS */ "./frontend/src/appendCSS.js");
2016
+ const getCurrentDateTimeContext = __webpack_require__(/*! ../getCurrentDateTimeContext */ "./frontend/src/getCurrentDateTimeContext.js");
2004
2017
 
2005
2018
  appendCSS(__webpack_require__(/*! ./create-document.css */ "./frontend/src/create-document/create-document.css"));
2006
2019
 
@@ -2039,7 +2052,8 @@ module.exports = app => app.component('create-document', {
2039
2052
  for await (const event of api.Model.streamChatMessage({
2040
2053
  model: this.currentModel,
2041
2054
  content: prompt,
2042
- documentData: this.aiOriginalDocument
2055
+ documentData: this.aiOriginalDocument,
2056
+ currentDateTime: getCurrentDateTimeContext()
2043
2057
  })) {
2044
2058
  if (event?.textPart) {
2045
2059
  this.aiSuggestion += event.textPart;
@@ -2434,16 +2448,28 @@ module.exports = app => app.component('dashboard-primitive', {
2434
2448
  props: ['value'],
2435
2449
  computed: {
2436
2450
  header() {
2437
- if (this.value != null && this.value.$primitive.header) {
2451
+ if (this.value != null && this.value.$primitive?.header) {
2438
2452
  return this.value.$primitive.header;
2439
2453
  }
2440
2454
  return null;
2441
2455
  },
2442
2456
  displayValue() {
2443
2457
  if (this.value != null && this.value.$primitive) {
2458
+ if (this.value.$primitive.value === null) {
2459
+ return 'null';
2460
+ }
2444
2461
  return this.value.$primitive.value;
2445
2462
  }
2463
+ if (this.value === null) {
2464
+ return 'null';
2465
+ }
2446
2466
  return this.value;
2467
+ },
2468
+ displayClass() {
2469
+ if (this.value == null) {
2470
+ return 'text-content-tertiary';
2471
+ }
2472
+ return null;
2447
2473
  }
2448
2474
  }
2449
2475
  });
@@ -2512,6 +2538,7 @@ module.exports = app => app.component('dashboard-result', {
2512
2538
  (module, __unused_webpack_exports, __webpack_require__) {
2513
2539
 
2514
2540
  "use strict";
2541
+ /* global Blob, URL, document */
2515
2542
 
2516
2543
 
2517
2544
  const template = __webpack_require__(/*! ./dashboard-table.html */ "./frontend/src/dashboard-result/dashboard-table/dashboard-table.html");
@@ -2519,6 +2546,11 @@ const template = __webpack_require__(/*! ./dashboard-table.html */ "./frontend/s
2519
2546
  module.exports = app => app.component('dashboard-table', {
2520
2547
  template,
2521
2548
  props: ['value'],
2549
+ data() {
2550
+ return {
2551
+ showDropdown: false
2552
+ };
2553
+ },
2522
2554
  computed: {
2523
2555
  columns() {
2524
2556
  return Array.isArray(this.value?.$table?.columns) ? this.value.$table.columns : [];
@@ -2534,6 +2566,46 @@ module.exports = app => app.component('dashboard-table', {
2534
2566
  }
2535
2567
  },
2536
2568
  methods: {
2569
+ toggleDropdown() {
2570
+ this.showDropdown = !this.showDropdown;
2571
+ },
2572
+ handleBodyClick(event) {
2573
+ const dropdownRefs = this.$refs.dropdown;
2574
+ const dropdowns = Array.isArray(dropdownRefs) ? dropdownRefs : [dropdownRefs];
2575
+ const hasClickInsideDropdown = dropdowns
2576
+ .filter(dropdown => dropdown && typeof dropdown.contains === 'function')
2577
+ .some(dropdown => dropdown.contains(event.target));
2578
+
2579
+ if (!hasClickInsideDropdown) {
2580
+ this.showDropdown = false;
2581
+ }
2582
+ },
2583
+ neutralizeCsvCell(cell) {
2584
+ const value = this.displayValue(cell);
2585
+ return /^\s*[=+\-@]/.test(value) ? `'${value}` : value;
2586
+ },
2587
+ escapeCsvCell(cell) {
2588
+ const escapedCell = this.neutralizeCsvCell(cell).replaceAll('"', '""');
2589
+ return `"${escapedCell}"`;
2590
+ },
2591
+ downloadCsv() {
2592
+ const header = this.columns.map(this.escapeCsvCell).join(',');
2593
+ const rows = this.rows
2594
+ .map(row => row.map(this.escapeCsvCell).join(','))
2595
+ .join('\n');
2596
+
2597
+ const csv = [header, rows].filter(v => v.length > 0).join('\n');
2598
+ const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
2599
+ const url = URL.createObjectURL(blob);
2600
+ const anchor = document.createElement('a');
2601
+ anchor.href = url;
2602
+ anchor.download = 'table.csv';
2603
+ document.body.appendChild(anchor);
2604
+ anchor.click();
2605
+ document.body.removeChild(anchor);
2606
+ URL.revokeObjectURL(url);
2607
+ this.$toast.success('CSV downloaded!');
2608
+ },
2537
2609
  displayValue(cell) {
2538
2610
  if (cell == null) {
2539
2611
  return '';
@@ -2547,6 +2619,12 @@ module.exports = app => app.component('dashboard-table', {
2547
2619
  }
2548
2620
  return String(cell);
2549
2621
  }
2622
+ },
2623
+ mounted() {
2624
+ document.body.addEventListener('click', this.handleBodyClick);
2625
+ },
2626
+ unmounted() {
2627
+ document.body.removeEventListener('click', this.handleBodyClick);
2550
2628
  }
2551
2629
  });
2552
2630
 
@@ -2932,6 +3010,140 @@ module.exports = app => app.component('detail-array', {
2932
3010
  }
2933
3011
  });
2934
3012
 
3013
+ /***/ },
3014
+
3015
+ /***/ "./frontend/src/detail-date/detail-date.js"
3016
+ /*!*************************************************!*\
3017
+ !*** ./frontend/src/detail-date/detail-date.js ***!
3018
+ \*************************************************/
3019
+ (module, __unused_webpack_exports, __webpack_require__) {
3020
+
3021
+ "use strict";
3022
+
3023
+
3024
+ const template = __webpack_require__(/*! ./detail-date.html */ "./frontend/src/detail-date/detail-date.html");
3025
+
3026
+ module.exports = app => app.component('detail-date', {
3027
+ template,
3028
+ props: ['value', 'viewMode'],
3029
+ emits: ['updated'],
3030
+ watch: {
3031
+ displayValue: {
3032
+ immediate: true,
3033
+ handler(val) {
3034
+ this.$emit('updated', val);
3035
+ }
3036
+ }
3037
+ },
3038
+ computed: {
3039
+ format() {
3040
+ if (this.viewMode != null && typeof this.viewMode === 'object') {
3041
+ return this.viewMode.format;
3042
+ }
3043
+ return this.viewMode;
3044
+ },
3045
+ timezone() {
3046
+ if (this.viewMode != null && typeof this.viewMode === 'object') {
3047
+ return this.viewMode.timezone || '';
3048
+ }
3049
+ return '';
3050
+ },
3051
+ parsedDate() {
3052
+ if (this.value == null) {
3053
+ return null;
3054
+ }
3055
+ const date = new Date(this.value);
3056
+ return Number.isNaN(date.getTime()) ? null : date;
3057
+ },
3058
+ displayValue() {
3059
+ if (this.value == null) {
3060
+ return String(this.value);
3061
+ }
3062
+ if (!this.parsedDate) {
3063
+ return 'Invalid Date';
3064
+ }
3065
+ return this.formatDateForDisplay(this.parsedDate);
3066
+ }
3067
+ },
3068
+ methods: {
3069
+ formatDateForDisplay(date) {
3070
+ if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
3071
+ return 'Invalid Date';
3072
+ }
3073
+
3074
+ if (this.format === 'utc_iso') {
3075
+ return date.toISOString();
3076
+ }
3077
+
3078
+ if (this.format === 'local_browser') {
3079
+ return date.toLocaleString();
3080
+ }
3081
+
3082
+ if (this.format === 'unix_ms') {
3083
+ return String(date.getTime());
3084
+ }
3085
+
3086
+ if (this.format === 'unix_seconds') {
3087
+ return String(Math.floor(date.getTime() / 1000));
3088
+ }
3089
+
3090
+ if (this.format === 'duration_relative') {
3091
+ return this.formatRelativeDuration(date);
3092
+ }
3093
+
3094
+ if (this.format === 'custom_tz') {
3095
+ return this.formatCustomTimezone(date);
3096
+ }
3097
+
3098
+ return date.toISOString();
3099
+ },
3100
+ formatRelativeDuration(date) {
3101
+ const diffMs = date.getTime() - Date.now();
3102
+ const absMs = Math.abs(diffMs);
3103
+ const rtf = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' });
3104
+ const units = [
3105
+ { unit: 'year', ms: 365 * 24 * 60 * 60 * 1000 },
3106
+ { unit: 'month', ms: 30 * 24 * 60 * 60 * 1000 },
3107
+ { unit: 'day', ms: 24 * 60 * 60 * 1000 },
3108
+ { unit: 'hour', ms: 60 * 60 * 1000 },
3109
+ { unit: 'minute', ms: 60 * 1000 },
3110
+ { unit: 'second', ms: 1000 }
3111
+ ];
3112
+
3113
+ for (const { unit, ms } of units) {
3114
+ if (absMs >= ms || unit === 'second') {
3115
+ const value = Math.round(diffMs / ms);
3116
+ return rtf.format(value, unit);
3117
+ }
3118
+ }
3119
+
3120
+ return 'now';
3121
+ },
3122
+ formatCustomTimezone(date) {
3123
+ const tz = (this.timezone || '').trim();
3124
+ if (!tz) {
3125
+ return `${date.toISOString()} (enter an IANA timezone)`;
3126
+ }
3127
+
3128
+ try {
3129
+ return new Intl.DateTimeFormat(undefined, {
3130
+ timeZone: tz,
3131
+ year: 'numeric',
3132
+ month: '2-digit',
3133
+ day: '2-digit',
3134
+ hour: '2-digit',
3135
+ minute: '2-digit',
3136
+ second: '2-digit',
3137
+ timeZoneName: 'short'
3138
+ }).format(date);
3139
+ } catch (err) {
3140
+ return `Invalid timezone: ${tz}`;
3141
+ }
3142
+ }
3143
+ }
3144
+ });
3145
+
3146
+
2935
3147
  /***/ },
2936
3148
 
2937
3149
  /***/ "./frontend/src/detail-default/detail-default.js"
@@ -4056,6 +4268,58 @@ module.exports = app => app.component('detail-default', {
4056
4268
  });
4057
4269
 
4058
4270
 
4271
+ /***/ },
4272
+
4273
+ /***/ "./frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.js"
4274
+ /*!**************************************************************************************!*\
4275
+ !*** ./frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.js ***!
4276
+ \**************************************************************************************/
4277
+ (module, __unused_webpack_exports, __webpack_require__) {
4278
+
4279
+ "use strict";
4280
+
4281
+
4282
+ const template = __webpack_require__(/*! ./date-view-mode-picker.html */ "./frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.html");
4283
+
4284
+ module.exports = app => app.component('date-view-mode-picker', {
4285
+ template,
4286
+ props: ['viewMode', 'path'],
4287
+ emits: ['update:viewMode'],
4288
+ computed: {
4289
+ format() {
4290
+ if (this.viewMode != null && typeof this.viewMode === 'object') {
4291
+ return this.viewMode.format;
4292
+ }
4293
+ return this.viewMode;
4294
+ },
4295
+ timezone() {
4296
+ if (this.viewMode != null && typeof this.viewMode === 'object') {
4297
+ return this.viewMode.timezone || '';
4298
+ }
4299
+ return '';
4300
+ },
4301
+ timezoneDatalistId() {
4302
+ return `timezone-options-${String(this.path?.path || '').replace(/[^a-zA-Z0-9_-]/g, '-')}`;
4303
+ },
4304
+ timezones() {
4305
+ return Intl.supportedValuesOf('timeZone');
4306
+ }
4307
+ },
4308
+ methods: {
4309
+ onFormatChange(newFormat) {
4310
+ if (newFormat === 'custom_tz') {
4311
+ this.$emit('update:viewMode', { format: 'custom_tz', timezone: this.timezone });
4312
+ } else {
4313
+ this.$emit('update:viewMode', newFormat);
4314
+ }
4315
+ },
4316
+ onTimezoneChange(newTimezone) {
4317
+ this.$emit('update:viewMode', { format: 'custom_tz', timezone: newTimezone });
4318
+ }
4319
+ }
4320
+ });
4321
+
4322
+
4059
4323
  /***/ },
4060
4324
 
4061
4325
  /***/ "./frontend/src/document-details/document-details.js"
@@ -4520,11 +4784,15 @@ const appendCSS = __webpack_require__(/*! ../../appendCSS */ "./frontend/src/app
4520
4784
 
4521
4785
  appendCSS(__webpack_require__(/*! ./document-property.css */ "./frontend/src/document-details/document-property/document-property.css"));
4522
4786
 
4787
+ const UNSET = Symbol('unset');
4788
+
4523
4789
  module.exports = app => app.component('document-property', {
4524
4790
  template,
4525
4791
  data: function() {
4526
4792
  return {
4527
4793
  dateType: 'picker', // picker, iso
4794
+ dateViewMode: 'utc_iso',
4795
+ renderedValue: UNSET,
4528
4796
  isCollapsed: false, // Start uncollapsed by default
4529
4797
  isValueExpanded: false, // Track if the value is expanded
4530
4798
  detailViewMode: 'text',
@@ -4541,8 +4809,14 @@ module.exports = app => app.component('document-property', {
4541
4809
  },
4542
4810
  props: ['path', 'document', 'schemaPaths', 'editting', 'changes', 'invalid', 'highlight'],
4543
4811
  computed: {
4812
+ isDatePath() {
4813
+ return this.path?.instance === 'Date';
4814
+ },
4815
+ rawValue() {
4816
+ return this.getValueForPath(this.path.path);
4817
+ },
4544
4818
  valueAsString() {
4545
- const value = this.getValueForPath(this.path.path);
4819
+ const value = this.renderedValue !== UNSET ? this.renderedValue : this.rawValue;
4546
4820
  if (value == null) {
4547
4821
  return String(value);
4548
4822
  }
@@ -4674,6 +4948,9 @@ module.exports = app => app.component('document-property', {
4674
4948
  if (schemaPath.instance === 'Array') {
4675
4949
  return 'detail-array';
4676
4950
  }
4951
+ if (schemaPath.instance === 'Date') {
4952
+ return 'detail-date';
4953
+ }
4677
4954
  return 'detail-default';
4678
4955
  },
4679
4956
  getEditComponentForPath(path) {
@@ -5887,6 +6164,34 @@ exports.isoToLongDateTime = function isoToLongDateTime(str) {
5887
6164
  };
5888
6165
 
5889
6166
 
6167
+ /***/ },
6168
+
6169
+ /***/ "./frontend/src/getCurrentDateTimeContext.js"
6170
+ /*!***************************************************!*\
6171
+ !*** ./frontend/src/getCurrentDateTimeContext.js ***!
6172
+ \***************************************************/
6173
+ (module, __unused_webpack_exports, __webpack_require__) {
6174
+
6175
+ "use strict";
6176
+
6177
+
6178
+ const time = __webpack_require__(/*! time-commando */ "./node_modules/time-commando/index.js");
6179
+
6180
+ module.exports = function getCurrentDateTimeContext() {
6181
+ const date = time.now();
6182
+ const components = [
6183
+ date.getFullYear(),
6184
+ date.getMonth() + 1,
6185
+ date.getDate(),
6186
+ date.getHours(),
6187
+ date.getMinutes(),
6188
+ date.getSeconds()
6189
+ ].map(num => num.toString().padStart(2, '0'));
6190
+ const [yyyy, mm, dd, hh, mi, ss] = components;
6191
+ return `${yyyy}-${mm}-${dd}T${hh}:${mi}:${ss}`;
6192
+ };
6193
+
6194
+
5890
6195
  /***/ },
5891
6196
 
5892
6197
  /***/ "./frontend/src/index.js"
@@ -6551,13 +6856,6 @@ module.exports = app => app.component('list-json', {
6551
6856
  topLevelExpanded: false
6552
6857
  };
6553
6858
  },
6554
- watch: {
6555
- value: {
6556
- handler() {
6557
- this.resetCollapse();
6558
- }
6559
- }
6560
- },
6561
6859
  created() {
6562
6860
  this.resetCollapse();
6563
6861
  for (const field of this.expandedFields) {
@@ -6758,7 +7056,31 @@ appendCSS(__webpack_require__(/*! ./modal.css */ "./frontend/src/modal/modal.css
6758
7056
 
6759
7057
  module.exports = app => app.component('modal', {
6760
7058
  template,
6761
- props: ['containerClass']
7059
+ props: ['containerClass'],
7060
+ mounted() {
7061
+ window.addEventListener('keydown', this.onEscape);
7062
+ },
7063
+ beforeUnmount() {
7064
+ window.removeEventListener('keydown', this.onEscape);
7065
+ },
7066
+ methods: {
7067
+ onEscape(event) {
7068
+ if (event.key !== 'Escape') {
7069
+ return;
7070
+ }
7071
+
7072
+ const modalMasks = Array.from(document.querySelectorAll('.modal-mask'));
7073
+ const currentMask = this.$el?.classList?.contains('modal-mask') ? this.$el : this.$el?.querySelector('.modal-mask') || this.$el;
7074
+ const isTopMostModal = modalMasks.length > 0 && modalMasks[modalMasks.length - 1] === currentMask;
7075
+
7076
+ if (!isTopMostModal) {
7077
+ return;
7078
+ }
7079
+
7080
+ const closeButton = currentMask.querySelector('.modal-exit, [data-modal-close]');
7081
+ closeButton?.click();
7082
+ }
7083
+ }
6762
7084
  });
6763
7085
 
6764
7086
 
@@ -6814,6 +7136,9 @@ module.exports = app => app.component('document-search', {
6814
7136
  created() {
6815
7137
  this.buildAutocompleteTrie();
6816
7138
  },
7139
+ mounted() {
7140
+ this.$refs.searchInput.focus();
7141
+ },
6817
7142
  methods: {
6818
7143
  emitSearch() {
6819
7144
  this.$emit('input', this.searchText);
@@ -7312,7 +7637,7 @@ module.exports = app => app.component('models', {
7312
7637
  computed: {
7313
7638
  referenceMap() {
7314
7639
  const map = {};
7315
- for (const path of this.filteredPaths) {
7640
+ for (const path of this.schemaPaths) {
7316
7641
  if (path?.ref) {
7317
7642
  map[path.path] = path.ref;
7318
7643
  }
@@ -8789,12 +9114,7 @@ module.exports = app => app.component('navbar', {
8789
9114
  return this.roles && this.roles[0] === 'dashboards' ? 'dashboards' : 'root';
8790
9115
  },
8791
9116
  hasTaskVisualizer() {
8792
- if (window.MONGOOSE_STUDIO_CONFIG.enableTaskVisualizer) {
8793
- return '#/tasks';
8794
- } else {
8795
- return 'https://www.npmjs.com/package/@mongoosejs/task';
8796
- }
8797
-
9117
+ return !!window.MONGOOSE_STUDIO_CONFIG.enableTaskVisualizer;
8798
9118
  }
8799
9119
  },
8800
9120
  methods: {
@@ -8848,6 +9168,40 @@ module.exports = app => app.component('navbar', {
8848
9168
  });
8849
9169
 
8850
9170
 
9171
+ /***/ },
9172
+
9173
+ /***/ "./frontend/src/pro-upgrade-modal/pro-upgrade-modal.js"
9174
+ /*!*************************************************************!*\
9175
+ !*** ./frontend/src/pro-upgrade-modal/pro-upgrade-modal.js ***!
9176
+ \*************************************************************/
9177
+ (module, __unused_webpack_exports, __webpack_require__) {
9178
+
9179
+ "use strict";
9180
+
9181
+
9182
+ const template = __webpack_require__(/*! ./pro-upgrade-modal.html */ "./frontend/src/pro-upgrade-modal/pro-upgrade-modal.html");
9183
+
9184
+ module.exports = app => app.component('pro-upgrade-modal', {
9185
+ template,
9186
+ props: {
9187
+ show: { type: Boolean, default: false },
9188
+ featureDescription: { type: String, default: 'This feature is available on the Pro plan.' }
9189
+ },
9190
+ emits: ['close'],
9191
+ watch: {
9192
+ show(val) {
9193
+ if (val) {
9194
+ this.$nextTick(() => {
9195
+ if (this.$refs.overlay) {
9196
+ this.$refs.overlay.focus();
9197
+ }
9198
+ });
9199
+ }
9200
+ }
9201
+ }
9202
+ });
9203
+
9204
+
8851
9205
  /***/ },
8852
9206
 
8853
9207
  /***/ "./frontend/src/routes.js"
@@ -9666,6 +10020,39 @@ const template = __webpack_require__(/*! ./tasks.html */ "./frontend/src/tasks/t
9666
10020
  const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
9667
10021
  const { DATE_FILTERS, getDateRangeForRange } = __webpack_require__(/*! ../_util/dateRange */ "./frontend/src/_util/dateRange.js");
9668
10022
 
10023
+ /** Returns the bucket size in ms for the given date range. */
10024
+ function getBucketSizeMs(range) {
10025
+ switch (range) {
10026
+ case 'last_hour': return 5 * 60 * 1000; // 5 minutes
10027
+ case 'today':
10028
+ case 'yesterday': return 60 * 60 * 1000; // 1 hour
10029
+ case 'thisWeek':
10030
+ case 'lastWeek': return 24 * 60 * 60 * 1000; // 1 day
10031
+ case 'thisMonth':
10032
+ case 'lastMonth': return 24 * 60 * 60 * 1000; // 1 day
10033
+ default: return 5 * 60 * 1000;
10034
+ }
10035
+ }
10036
+
10037
+ /** Formats a bucket timestamp for the x-axis label based on the date range. */
10038
+ function formatBucketLabel(timestamp, range) {
10039
+ const date = new Date(timestamp);
10040
+ switch (range) {
10041
+ case 'last_hour':
10042
+ return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
10043
+ case 'today':
10044
+ case 'yesterday':
10045
+ return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
10046
+ case 'thisWeek':
10047
+ case 'lastWeek':
10048
+ case 'thisMonth':
10049
+ case 'lastMonth':
10050
+ return date.toLocaleDateString([], { month: 'short', day: 'numeric' });
10051
+ default:
10052
+ return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
10053
+ }
10054
+ }
10055
+
9669
10056
  module.exports = app => app.component('tasks', {
9670
10057
  data: () => ({
9671
10058
  status: 'init',
@@ -9693,10 +10080,22 @@ module.exports = app => app.component('tasks', {
9693
10080
  scheduledAt: '',
9694
10081
  parameters: '',
9695
10082
  repeatInterval: ''
9696
- }
10083
+ },
10084
+ // Chart over time
10085
+ overTimeChart: null,
10086
+ overTimeBuckets: [],
10087
+ // Toggled with v-if on the canvas so Chart.js is torn down and remounted on
10088
+ // filter changes. Updating Chart.js in place during a big Vue re-render was
10089
+ // freezing the page (dropdowns unresponsive, chart stale).
10090
+ showOverTimeChart: true
9697
10091
  }),
9698
10092
  methods: {
9699
10093
  async getTasks() {
10094
+ // Hide chart canvas + teardown Chart.js immediately on filter changes
10095
+ // (see showOverTimeChart + v-if on the canvas in tasks.html).
10096
+ this.showOverTimeChart = false;
10097
+ this.destroyOverTimeChart();
10098
+
9700
10099
  const params = {};
9701
10100
  if (this.selectedStatus == 'all') {
9702
10101
  params.status = null;
@@ -9715,9 +10114,105 @@ module.exports = app => app.component('tasks', {
9715
10114
  params.name = this.searchQuery.trim();
9716
10115
  }
9717
10116
 
9718
- const { statusCounts, tasksByName } = await api.Task.getTaskOverview(params);
9719
- this.statusCounts = statusCounts || this.statusCounts;
9720
- this.tasksByName = tasksByName || [];
10117
+ const [overviewResult, overTimeResult] = await Promise.all([
10118
+ api.Task.getTaskOverview(params),
10119
+ api.Task.getTasksOverTime({
10120
+ start: params.start,
10121
+ end: params.end,
10122
+ bucketSizeMs: getBucketSizeMs(this.selectedRange)
10123
+ })
10124
+ ]);
10125
+
10126
+ this.statusCounts = overviewResult.statusCounts || this.statusCounts;
10127
+ this.tasksByName = overviewResult.tasksByName || [];
10128
+ this.overTimeBuckets = overTimeResult || [];
10129
+ if (this.overTimeBuckets.length === 0) {
10130
+ this.showOverTimeChart = false;
10131
+ this.destroyOverTimeChart();
10132
+ } else {
10133
+ this.showOverTimeChart = true;
10134
+ await this.$nextTick();
10135
+ this.renderOverTimeChart();
10136
+ }
10137
+ },
10138
+
10139
+ /** Build or update the stacked bar chart showing tasks over time. */
10140
+ renderOverTimeChart() {
10141
+ const Chart = typeof window !== 'undefined' && window.Chart;
10142
+ if (!Chart) {
10143
+ throw new Error('Chart.js not found');
10144
+ }
10145
+ const canvas = this.$refs.overTimeChart;
10146
+ if (!canvas || typeof canvas.getContext !== 'function') return;
10147
+
10148
+ const buckets = this.overTimeBuckets;
10149
+ const labels = buckets.map(b => formatBucketLabel(b.timestamp, this.selectedRange));
10150
+ const succeeded = buckets.map(b => b.succeeded || 0);
10151
+ const failed = buckets.map(b => b.failed || 0);
10152
+ const cancelled = buckets.map(b => b.cancelled || 0);
10153
+
10154
+ const isDark = typeof document !== 'undefined' && document.documentElement.classList.contains('dark');
10155
+ const tickColor = isDark ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.6)';
10156
+ const gridColor = isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)';
10157
+
10158
+ const chartData = {
10159
+ labels,
10160
+ datasets: [
10161
+ { label: 'Succeeded', data: succeeded, backgroundColor: '#22c55e', stack: 'tasks' },
10162
+ { label: 'Failed', data: failed, backgroundColor: '#ef4444', stack: 'tasks' },
10163
+ { label: 'Cancelled', data: cancelled, backgroundColor: '#6b7280', stack: 'tasks' }
10164
+ ]
10165
+ };
10166
+
10167
+ if (this.overTimeChart) {
10168
+ try {
10169
+ this.overTimeChart.data.labels = labels;
10170
+ this.overTimeChart.data.datasets[0].data = succeeded;
10171
+ this.overTimeChart.data.datasets[1].data = failed;
10172
+ this.overTimeChart.data.datasets[2].data = cancelled;
10173
+ this.overTimeChart.update('none');
10174
+ } finally {
10175
+ this.destroyOverTimeChart();
10176
+ }
10177
+ }
10178
+
10179
+ this.overTimeChart = new Chart(canvas, {
10180
+ type: 'bar',
10181
+ data: chartData,
10182
+ options: {
10183
+ responsive: true,
10184
+ maintainAspectRatio: false,
10185
+ animation: false,
10186
+ scales: {
10187
+ x: {
10188
+ stacked: true,
10189
+ ticks: { color: tickColor, maxRotation: 45, minRotation: 0 },
10190
+ grid: { color: gridColor }
10191
+ },
10192
+ y: {
10193
+ stacked: true,
10194
+ beginAtZero: true,
10195
+ ticks: { color: tickColor, precision: 0 },
10196
+ grid: { color: gridColor }
10197
+ }
10198
+ },
10199
+ plugins: {
10200
+ legend: {
10201
+ display: true,
10202
+ position: 'top',
10203
+ labels: { color: tickColor }
10204
+ },
10205
+ tooltip: { mode: 'index', intersect: false }
10206
+ }
10207
+ }
10208
+ });
10209
+ },
10210
+
10211
+ destroyOverTimeChart() {
10212
+ if (this.overTimeChart) {
10213
+ this.overTimeChart.destroy();
10214
+ this.overTimeChart = null;
10215
+ }
9721
10216
  },
9722
10217
  openTaskGroupDetails(group) {
9723
10218
  const query = { dateRange: this.selectedRange || 'last_hour' };
@@ -9893,11 +10388,23 @@ module.exports = app => app.component('tasks', {
9893
10388
  }
9894
10389
  },
9895
10390
  mounted: async function() {
10391
+ // Load initial data while showing the loader state.
9896
10392
  await this.updateDateRange();
9897
- await this.getTasks();
10393
+
10394
+ // Once data is loaded, switch to the main view.
9898
10395
  this.status = 'loaded';
10396
+ await this.$nextTick();
10397
+
10398
+ // Ensure the chart renders now that the canvas exists in the DOM.
10399
+ if (this.showOverTimeChart && this.overTimeBuckets.length > 0) {
10400
+ this.renderOverTimeChart();
10401
+ }
10402
+
9899
10403
  this.setDefaultCreateTaskValues();
9900
10404
  },
10405
+ beforeUnmount() {
10406
+ this.destroyOverTimeChart();
10407
+ },
9901
10408
  template: template
9902
10409
  });
9903
10410
 
@@ -10200,9 +10707,15 @@ var map = {
10200
10707
  "./detail-array/detail-array": "./frontend/src/detail-array/detail-array.js",
10201
10708
  "./detail-array/detail-array.html": "./frontend/src/detail-array/detail-array.html",
10202
10709
  "./detail-array/detail-array.js": "./frontend/src/detail-array/detail-array.js",
10710
+ "./detail-date/detail-date": "./frontend/src/detail-date/detail-date.js",
10711
+ "./detail-date/detail-date.html": "./frontend/src/detail-date/detail-date.html",
10712
+ "./detail-date/detail-date.js": "./frontend/src/detail-date/detail-date.js",
10203
10713
  "./detail-default/detail-default": "./frontend/src/detail-default/detail-default.js",
10204
10714
  "./detail-default/detail-default.html": "./frontend/src/detail-default/detail-default.html",
10205
10715
  "./detail-default/detail-default.js": "./frontend/src/detail-default/detail-default.js",
10716
+ "./document-details/date-view-mode-picker/date-view-mode-picker": "./frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.js",
10717
+ "./document-details/date-view-mode-picker/date-view-mode-picker.html": "./frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.html",
10718
+ "./document-details/date-view-mode-picker/date-view-mode-picker.js": "./frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.js",
10206
10719
  "./document-details/document-details": "./frontend/src/document-details/document-details.js",
10207
10720
  "./document-details/document-details.css": "./frontend/src/document-details/document-details.css",
10208
10721
  "./document-details/document-details.html": "./frontend/src/document-details/document-details.html",
@@ -10252,6 +10765,8 @@ var map = {
10252
10765
  "./export-query-results/export-query-results.js": "./frontend/src/export-query-results/export-query-results.js",
10253
10766
  "./format": "./frontend/src/format.js",
10254
10767
  "./format.js": "./frontend/src/format.js",
10768
+ "./getCurrentDateTimeContext": "./frontend/src/getCurrentDateTimeContext.js",
10769
+ "./getCurrentDateTimeContext.js": "./frontend/src/getCurrentDateTimeContext.js",
10255
10770
  "./index": "./frontend/src/index.js",
10256
10771
  "./index.js": "./frontend/src/index.js",
10257
10772
  "./json-node/json-node": "./frontend/src/json-node/json-node.js",
@@ -10302,6 +10817,9 @@ var map = {
10302
10817
  "./navbar/navbar.css": "./frontend/src/navbar/navbar.css",
10303
10818
  "./navbar/navbar.html": "./frontend/src/navbar/navbar.html",
10304
10819
  "./navbar/navbar.js": "./frontend/src/navbar/navbar.js",
10820
+ "./pro-upgrade-modal/pro-upgrade-modal": "./frontend/src/pro-upgrade-modal/pro-upgrade-modal.js",
10821
+ "./pro-upgrade-modal/pro-upgrade-modal.html": "./frontend/src/pro-upgrade-modal/pro-upgrade-modal.html",
10822
+ "./pro-upgrade-modal/pro-upgrade-modal.js": "./frontend/src/pro-upgrade-modal/pro-upgrade-modal.js",
10305
10823
  "./routes": "./frontend/src/routes.js",
10306
10824
  "./routes.js": "./frontend/src/routes.js",
10307
10825
  "./splash/splash": "./frontend/src/splash/splash.js",
@@ -10416,7 +10934,7 @@ __webpack_require__.r(__webpack_exports__);
10416
10934
  /* harmony export */ });
10417
10935
  /* harmony import */ var _vue_shared__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
10418
10936
  /**
10419
- * @vue/reactivity v3.5.31
10937
+ * @vue/reactivity v3.5.32
10420
10938
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
10421
10939
  * @license MIT
10422
10940
  **/
@@ -12563,7 +13081,7 @@ __webpack_require__.r(__webpack_exports__);
12563
13081
  /* harmony import */ var _vue_reactivity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/reactivity */ "./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js");
12564
13082
  /* harmony import */ var _vue_shared__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
12565
13083
  /**
12566
- * @vue/runtime-core v3.5.31
13084
+ * @vue/runtime-core v3.5.32
12567
13085
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
12568
13086
  * @license MIT
12569
13087
  **/
@@ -13510,6 +14028,7 @@ function createPathGetter(ctx, path) {
13510
14028
  };
13511
14029
  }
13512
14030
 
14031
+ const pendingMounts = /* @__PURE__ */ new WeakMap();
13513
14032
  const TeleportEndKey = /* @__PURE__ */ Symbol("_vte");
13514
14033
  const isTeleport = (type) => type.__isTeleport;
13515
14034
  const isTeleportDisabled = (props) => props && (props.disabled || props.disabled === "");
@@ -13551,91 +14070,86 @@ const TeleportImpl = {
13551
14070
  o: { insert, querySelector, createText, createComment }
13552
14071
  } = internals;
13553
14072
  const disabled = isTeleportDisabled(n2.props);
13554
- let { shapeFlag, children, dynamicChildren } = n2;
14073
+ let { dynamicChildren } = n2;
13555
14074
  if ( true && isHmrUpdating) {
13556
14075
  optimized = false;
13557
14076
  dynamicChildren = null;
13558
14077
  }
14078
+ const mount = (vnode, container2, anchor2) => {
14079
+ if (vnode.shapeFlag & 16) {
14080
+ mountChildren(
14081
+ vnode.children,
14082
+ container2,
14083
+ anchor2,
14084
+ parentComponent,
14085
+ parentSuspense,
14086
+ namespace,
14087
+ slotScopeIds,
14088
+ optimized
14089
+ );
14090
+ }
14091
+ };
14092
+ const mountToTarget = (vnode = n2) => {
14093
+ const disabled2 = isTeleportDisabled(vnode.props);
14094
+ const target = vnode.target = resolveTarget(vnode.props, querySelector);
14095
+ const targetAnchor = prepareAnchor(target, vnode, createText, insert);
14096
+ if (target) {
14097
+ if (namespace !== "svg" && isTargetSVG(target)) {
14098
+ namespace = "svg";
14099
+ } else if (namespace !== "mathml" && isTargetMathML(target)) {
14100
+ namespace = "mathml";
14101
+ }
14102
+ if (parentComponent && parentComponent.isCE) {
14103
+ (parentComponent.ce._teleportTargets || (parentComponent.ce._teleportTargets = /* @__PURE__ */ new Set())).add(target);
14104
+ }
14105
+ if (!disabled2) {
14106
+ mount(vnode, target, targetAnchor);
14107
+ updateCssVars(vnode, false);
14108
+ }
14109
+ } else if ( true && !disabled2) {
14110
+ warn$1("Invalid Teleport target on mount:", target, `(${typeof target})`);
14111
+ }
14112
+ };
14113
+ const queuePendingMount = (vnode) => {
14114
+ const mountJob = () => {
14115
+ if (pendingMounts.get(vnode) !== mountJob) return;
14116
+ pendingMounts.delete(vnode);
14117
+ if (isTeleportDisabled(vnode.props)) {
14118
+ mount(vnode, container, vnode.anchor);
14119
+ updateCssVars(vnode, true);
14120
+ }
14121
+ mountToTarget(vnode);
14122
+ };
14123
+ pendingMounts.set(vnode, mountJob);
14124
+ queuePostRenderEffect(mountJob, parentSuspense);
14125
+ };
13559
14126
  if (n1 == null) {
13560
14127
  const placeholder = n2.el = true ? createComment("teleport start") : 0;
13561
14128
  const mainAnchor = n2.anchor = true ? createComment("teleport end") : 0;
13562
14129
  insert(placeholder, container, anchor);
13563
14130
  insert(mainAnchor, container, anchor);
13564
- const mount = (container2, anchor2) => {
13565
- if (shapeFlag & 16) {
13566
- mountChildren(
13567
- children,
13568
- container2,
13569
- anchor2,
13570
- parentComponent,
13571
- parentSuspense,
13572
- namespace,
13573
- slotScopeIds,
13574
- optimized
13575
- );
13576
- }
13577
- };
13578
- const mountToTarget = () => {
13579
- const target = n2.target = resolveTarget(n2.props, querySelector);
13580
- const targetAnchor = prepareAnchor(target, n2, createText, insert);
13581
- if (target) {
13582
- if (namespace !== "svg" && isTargetSVG(target)) {
13583
- namespace = "svg";
13584
- } else if (namespace !== "mathml" && isTargetMathML(target)) {
13585
- namespace = "mathml";
13586
- }
13587
- if (parentComponent && parentComponent.isCE) {
13588
- (parentComponent.ce._teleportTargets || (parentComponent.ce._teleportTargets = /* @__PURE__ */ new Set())).add(target);
13589
- }
13590
- if (!disabled) {
13591
- mount(target, targetAnchor);
13592
- updateCssVars(n2, false);
13593
- }
13594
- } else if ( true && !disabled) {
13595
- warn$1(
13596
- "Invalid Teleport target on mount:",
13597
- target,
13598
- `(${typeof target})`
13599
- );
13600
- }
13601
- };
14131
+ if (isTeleportDeferred(n2.props) || parentSuspense && parentSuspense.pendingBranch) {
14132
+ queuePendingMount(n2);
14133
+ return;
14134
+ }
13602
14135
  if (disabled) {
13603
- mount(container, mainAnchor);
14136
+ mount(n2, container, mainAnchor);
13604
14137
  updateCssVars(n2, true);
13605
14138
  }
13606
- if (isTeleportDeferred(n2.props) || parentSuspense && parentSuspense.pendingBranch) {
13607
- n2.el.__isMounted = false;
13608
- queuePostRenderEffect(() => {
13609
- if (n2.el.__isMounted !== false) return;
13610
- mountToTarget();
13611
- delete n2.el.__isMounted;
13612
- }, parentSuspense);
13613
- } else {
13614
- mountToTarget();
13615
- }
14139
+ mountToTarget();
13616
14140
  } else {
13617
14141
  n2.el = n1.el;
13618
- n2.targetStart = n1.targetStart;
13619
14142
  const mainAnchor = n2.anchor = n1.anchor;
13620
- const target = n2.target = n1.target;
13621
- const targetAnchor = n2.targetAnchor = n1.targetAnchor;
13622
- if (n1.el.__isMounted === false) {
13623
- queuePostRenderEffect(() => {
13624
- TeleportImpl.process(
13625
- n1,
13626
- n2,
13627
- container,
13628
- anchor,
13629
- parentComponent,
13630
- parentSuspense,
13631
- namespace,
13632
- slotScopeIds,
13633
- optimized,
13634
- internals
13635
- );
13636
- }, parentSuspense);
14143
+ const pendingMount = pendingMounts.get(n1);
14144
+ if (pendingMount) {
14145
+ pendingMount.flags |= 8;
14146
+ pendingMounts.delete(n1);
14147
+ queuePendingMount(n2);
13637
14148
  return;
13638
14149
  }
14150
+ n2.targetStart = n1.targetStart;
14151
+ const target = n2.target = n1.target;
14152
+ const targetAnchor = n2.targetAnchor = n1.targetAnchor;
13639
14153
  const wasDisabled = isTeleportDisabled(n1.props);
13640
14154
  const currentContainer = wasDisabled ? container : target;
13641
14155
  const currentAnchor = wasDisabled ? mainAnchor : targetAnchor;
@@ -13726,13 +14240,19 @@ const TeleportImpl = {
13726
14240
  target,
13727
14241
  props
13728
14242
  } = vnode;
14243
+ let shouldRemove = doRemove || !isTeleportDisabled(props);
14244
+ const pendingMount = pendingMounts.get(vnode);
14245
+ if (pendingMount) {
14246
+ pendingMount.flags |= 8;
14247
+ pendingMounts.delete(vnode);
14248
+ shouldRemove = false;
14249
+ }
13729
14250
  if (target) {
13730
14251
  hostRemove(targetStart);
13731
14252
  hostRemove(targetAnchor);
13732
14253
  }
13733
14254
  doRemove && hostRemove(anchor);
13734
14255
  if (shapeFlag & 16) {
13735
- const shouldRemove = doRemove || !isTeleportDisabled(props);
13736
14256
  for (let i = 0; i < children.length; i++) {
13737
14257
  const child = children[i];
13738
14258
  unmount(
@@ -19941,6 +20461,7 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe
19941
20461
  if (instance.isUnmounted || suspense.isUnmounted || suspense.pendingId !== instance.suspenseId) {
19942
20462
  return;
19943
20463
  }
20464
+ unsetCurrentInstance();
19944
20465
  instance.asyncResolved = true;
19945
20466
  const { vnode: vnode2 } = instance;
19946
20467
  if (true) {
@@ -21147,7 +21668,7 @@ function isMemoSame(cached, memo) {
21147
21668
  return true;
21148
21669
  }
21149
21670
 
21150
- const version = "3.5.31";
21671
+ const version = "3.5.32";
21151
21672
  const warn = true ? warn$1 : 0;
21152
21673
  const ErrorTypeStrings = ErrorTypeStrings$1 ;
21153
21674
  const devtools = true ? devtools$1 : 0;
@@ -21358,7 +21879,7 @@ __webpack_require__.r(__webpack_exports__);
21358
21879
  /* harmony import */ var _vue_runtime_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/runtime-core */ "./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js");
21359
21880
  /* harmony import */ var _vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
21360
21881
  /**
21361
- * @vue/runtime-dom v3.5.31
21882
+ * @vue/runtime-dom v3.5.32
21362
21883
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
21363
21884
  * @license MIT
21364
21885
  **/
@@ -23430,7 +23951,7 @@ __webpack_require__.r(__webpack_exports__);
23430
23951
  /* harmony export */ toTypeString: () => (/* binding */ toTypeString)
23431
23952
  /* harmony export */ });
23432
23953
  /**
23433
- * @vue/shared v3.5.31
23954
+ * @vue/shared v3.5.32
23434
23955
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
23435
23956
  * @license MIT
23436
23957
  **/
@@ -48767,6 +49288,151 @@ module.exports = function stringToParts(str) {
48767
49288
 
48768
49289
  !function(t,e){ true?module.exports=e():0}(this,()=>(()=>{"use strict";var t={242(t,e,n){const r=n(714),{ArrayPrototypeMap:o}=r;e.h=class{hexSlice(t=0,e){return o(this.slice(t,e),t=>("00"+t.toString(16)).slice(-2)).join("")}}},702(t,e,n){const r=n(714),{AggregateError:o,AggregateErrorPrototype:i,Array:s,ArrayBuffer:l,ArrayBufferPrototype:c,ArrayIsArray:a,ArrayPrototype:u,ArrayPrototypeFilter:f,ArrayPrototypeForEach:p,ArrayPrototypeIncludes:y,ArrayPrototypeIndexOf:g,ArrayPrototypeJoin:h,ArrayPrototypeMap:d,ArrayPrototypePop:m,ArrayPrototypePush:b,ArrayPrototypePushApply:$,ArrayPrototypeSlice:S,ArrayPrototypeSort:x,ArrayPrototypeSplice:P,ArrayPrototypeUnshift:A,BigIntPrototypeValueOf:v,Boolean:_,BooleanPrototype:w,BooleanPrototypeValueOf:E,DataView:O,DataViewPrototype:L,Date:R,DatePrototype:k,DatePrototypeGetTime:I,DatePrototypeToISOString:j,DatePrototypeToString:B,Error:T,ErrorPrototype:z,ErrorPrototypeToString:M,Function:N,FunctionPrototype:C,FunctionPrototypeBind:F,FunctionPrototypeCall:D,FunctionPrototypeSymbolHasInstance:W,FunctionPrototypeToString:H,JSONStringify:U,Map:G,MapPrototype:V,MapPrototypeEntries:Z,MapPrototypeGetSize:Y,MathFloor:q,MathMax:J,MathMin:K,MathRound:Q,MathSqrt:X,MathTrunc:tt,Number:et,NumberIsFinite:nt,NumberIsNaN:rt,NumberParseFloat:ot,NumberParseInt:it,NumberPrototype:st,NumberPrototypeToString:lt,NumberPrototypeValueOf:ct,Object:at,ObjectAssign:ut,ObjectDefineProperty:ft,ObjectGetOwnPropertyDescriptor:pt,ObjectGetOwnPropertyNames:yt,ObjectGetOwnPropertySymbols:gt,ObjectGetPrototypeOf:ht,ObjectIs:dt,ObjectKeys:mt,ObjectPrototype:bt,ObjectPrototypeHasOwnProperty:$t,ObjectPrototypePropertyIsEnumerable:St,ObjectPrototypeToString:xt,ObjectSeal:Pt,ObjectSetPrototypeOf:At,Promise:vt,PromisePrototype:_t,RangeError:wt,RangeErrorPrototype:Et,ReflectApply:Ot,ReflectOwnKeys:Lt,RegExp:Rt,RegExpPrototype:kt,RegExpPrototypeExec:It,RegExpPrototypeSymbolReplace:jt,RegExpPrototypeSymbolSplit:Bt,RegExpPrototypeToString:Tt,SafeMap:zt,SafeSet:Mt,SafeStringIterator:Nt,Set:Ct,SetPrototype:Ft,SetPrototypeGetSize:Dt,SetPrototypeValues:Wt,String:Ht,StringPrototype:Ut,StringPrototypeCharCodeAt:Gt,StringPrototypeCodePointAt:Vt,StringPrototypeEndsWith:Zt,StringPrototypeIncludes:Yt,StringPrototypeIndexOf:qt,StringPrototypeLastIndexOf:Jt,StringPrototypeNormalize:Kt,StringPrototypePadEnd:Qt,StringPrototypePadStart:Xt,StringPrototypeRepeat:te,StringPrototypeReplace:ee,StringPrototypeReplaceAll:ne,StringPrototypeSlice:re,StringPrototypeSplit:oe,StringPrototypeStartsWith:ie,StringPrototypeToLowerCase:se,StringPrototypeValueOf:le,SymbolIterator:ce,SymbolPrototypeToString:ae,SymbolPrototypeValueOf:ue,SymbolToPrimitive:fe,SymbolToStringTag:pe,TypeError:ye,TypeErrorPrototype:ge,TypedArray:he,TypedArrayPrototype:de,TypedArrayPrototypeGetLength:me,TypedArrayPrototypeGetSymbolToStringTag:be,Uint8Array:$e,WeakMap:Se,WeakMapPrototype:xe,WeakSet:Pe,WeakSetPrototype:Ae,globalThis:ve,internalBinding:_e,uncurryThis:we}=r,{constants:{ALL_PROPERTIES:Ee,ONLY_ENUMERABLE:Oe,kPending:Le,kRejected:Re},getOwnNonIndexProperties:ke,getPromiseDetails:Ie,getProxyDetails:je,previewEntries:Be,getConstructorName:Te,getExternalValue:ze,Proxy:Me}=n(596),{customInspectSymbol:Ne,isError:Ce,join:Fe,removeColors:De}=n(992),{isStackOverflowError:We}=n(923),{isAsyncFunction:He,isGeneratorFunction:Ue,isAnyArrayBuffer:Ge,isArrayBuffer:Ve,isArgumentsObject:Ze,isBoxedPrimitive:Ye,isDataView:qe,isExternal:Je,isMap:Ke,isMapIterator:Qe,isModuleNamespaceObject:Xe,isNativeError:tn,isPromise:en,isSet:nn,isSetIterator:rn,isWeakMap:on,isWeakSet:sn,isRegExp:ln,isDate:cn,isTypedArray:an,isStringObject:un,isNumberObject:fn,isBooleanObject:pn,isBigIntObject:yn}=n(134),gn=n(146),{BuiltinModule:hn}=n(996),{validateObject:dn,validateString:mn,kValidateObjectAllowArray:bn}=n(63);let $n,Sn,xn;function Pn(t){return Sn=Sn||n(511),Sn.pathToFileURL(t).href}const An=new Mt(f(yt(ve),t=>null!==It(/^[A-Z][a-zA-Z0-9]+$/,t))),vn=t=>void 0===t&&void 0!==t,_n=Pt({showHidden:!1,depth:2,colors:!1,customInspect:!0,showProxy:!1,maxArrayLength:100,maxStringLength:1e4,breakLength:80,compact:3,sorted:!1,getters:!1,numericSeparator:!1}),wn=/[\x00-\x1f\x27\x5c\x7f-\x9f]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/,En=/[\x00-\x1f\x27\x5c\x7f-\x9f]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/g,On=/[\x00-\x1f\x5c\x7f-\x9f]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/,Ln=/[\x00-\x1f\x5c\x7f-\x9f]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/g,Rn=/^[a-zA-Z_][a-zA-Z_0-9]*$/,kn=/^(0|[1-9][0-9]*)$/,In=/^ {4}at (?:[^/\\(]+ \(|)node:(.+):\d+:\d+\)?$/,jn=/^(\s+[^(]*?)\s*{/,Bn=/(\/\/.*?\n)|(\/\*(.|\n)*?\*\/)/g,Tn=["\\x00","\\x01","\\x02","\\x03","\\x04","\\x05","\\x06","\\x07","\\b","\\t","\\n","\\x0B","\\f","\\r","\\x0E","\\x0F","\\x10","\\x11","\\x12","\\x13","\\x14","\\x15","\\x16","\\x17","\\x18","\\x19","\\x1A","\\x1B","\\x1C","\\x1D","\\x1E","\\x1F","","","","","","","","\\'","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\\\\","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\\x7F","\\x80","\\x81","\\x82","\\x83","\\x84","\\x85","\\x86","\\x87","\\x88","\\x89","\\x8A","\\x8B","\\x8C","\\x8D","\\x8E","\\x8F","\\x90","\\x91","\\x92","\\x93","\\x94","\\x95","\\x96","\\x97","\\x98","\\x99","\\x9A","\\x9B","\\x9C","\\x9D","\\x9E","\\x9F"],zn=new Rt("[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/\\#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/\\#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))","g");let Mn;function Nn(t,e){const n={budget:{},indentationLvl:0,seen:[],currentDepth:0,stylize:Zn,showHidden:_n.showHidden,depth:_n.depth,colors:_n.colors,customInspect:_n.customInspect,showProxy:_n.showProxy,maxArrayLength:_n.maxArrayLength,maxStringLength:_n.maxStringLength,breakLength:_n.breakLength,compact:_n.compact,sorted:_n.sorted,getters:_n.getters,numericSeparator:_n.numericSeparator};if(arguments.length>1)if(arguments.length>2&&(void 0!==arguments[2]&&(n.depth=arguments[2]),arguments.length>3&&void 0!==arguments[3]&&(n.colors=arguments[3])),"boolean"==typeof e)n.showHidden=e;else if(e){const t=mt(e);for(let r=0;r<t.length;++r){const o=t[r];$t(_n,o)||"stylize"===o?n[o]=e[o]:void 0===n.userOptions&&(n.userOptions=e)}}return n.colors&&(n.stylize=Vn),null===n.maxArrayLength&&(n.maxArrayLength=1/0),null===n.maxStringLength&&(n.maxStringLength=1/0),nr(n,t,0)}Nn.custom=Ne,ft(Nn,"defaultOptions",{__proto__:null,get:()=>_n,set:t=>(dn(t,"options"),ut(_n,t))});const Cn=39,Fn=49;function Dn(t,e){ft(Nn.colors,e,{__proto__:null,get(){return this[t]},set(e){this[t]=e},configurable:!0,enumerable:!1})}Nn.colors={__proto__:null,reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],blink:[5,25],inverse:[7,27],hidden:[8,28],strikethrough:[9,29],doubleunderline:[21,24],black:[30,Cn],red:[31,Cn],green:[32,Cn],yellow:[33,Cn],blue:[34,Cn],magenta:[35,Cn],cyan:[36,Cn],white:[37,Cn],bgBlack:[40,Fn],bgRed:[41,Fn],bgGreen:[42,Fn],bgYellow:[43,Fn],bgBlue:[44,Fn],bgMagenta:[45,Fn],bgCyan:[46,Fn],bgWhite:[47,Fn],framed:[51,54],overlined:[53,55],gray:[90,Cn],redBright:[91,Cn],greenBright:[92,Cn],yellowBright:[93,Cn],blueBright:[94,Cn],magentaBright:[95,Cn],cyanBright:[96,Cn],whiteBright:[97,Cn],bgGray:[100,Fn],bgRedBright:[101,Fn],bgGreenBright:[102,Fn],bgYellowBright:[103,Fn],bgBlueBright:[104,Fn],bgMagentaBright:[105,Fn],bgCyanBright:[106,Fn],bgWhiteBright:[107,Fn]},Dn("gray","grey"),Dn("gray","blackBright"),Dn("bgGray","bgGrey"),Dn("bgGray","bgBlackBright"),Dn("dim","faint"),Dn("strikethrough","crossedout"),Dn("strikethrough","strikeThrough"),Dn("strikethrough","crossedOut"),Dn("hidden","conceal"),Dn("inverse","swapColors"),Dn("inverse","swapcolors"),Dn("doubleunderline","doubleUnderline"),Nn.styles=ut({__proto__:null},{special:"cyan",number:"yellow",bigint:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",symbol:"green",date:"magenta",regexp:function t(e){let n="",r=0,o=0,i=!1;const s=(t.colors?.length>0?t.colors:Wn).reduce((t,e)=>{const n=Nn.colors[e];return n&&t.push([`[${n[0]}m`,`[${n[1]}m`]),t},[]);function l(t,n,i=1){let s="";for(r++;r<e.length&&e[r]!==n;)s+=e[r++];r<e.length?(o-=i,c(t),a(s,1,1),c(n),o+=i):a(t,1,-s.length)}const c=t=>{const e=o%s.length,r=s[e]??s[0];return n+=r[0]+t+r[1],e};function a(t,e,n){o+=e,c(t),o-=e,r+=n}for(c("/"),o++,r=1;r<e.length;){const t=e[r];if(i)if("\\"===t){let t="\\";if(r++,r<e.length){t+=e[r++];const n=t[1];if("u"===n&&"{"===e[r]){l(`${t}{`,"}",0);continue}if(("p"===n||"P"===n)&&"{"===e[r]){l(`${t}{`,"}",0);continue}"x"===t[1]&&(t+=e.slice(r,r+2),r+=2)}c(t)}else"]"===t?(o--,c("]"),r++,i=!1):"-"===t&&"["!==e[r-1]&&r+1<e.length&&"]"!==e[r+1]?a("-",1,1):(c(t),r++);else if("["===t)c("["),o++,r++,i=!0;else if("("===t){if(c("("),o++,r++,r<e.length&&"?"===e[r]){r++;const t=r<e.length?e[r]:"";if(":"===t||"="===t||"!"===t)a(`?${t}`,-1,1);else{const n=r+1<e.length?e[r+1]:"";if("<"!==t||"="!==n&&"!"!==n)if("<"===t){r++;const t=r;for(;r<e.length&&">"!==e[r];)r++;const n=e.slice(t,r);r<e.length&&">"===e[r]?(o--,c("?<"),a(n,1,0),c(">"),o++,r++):(a("?<",-1,0),c(n))}else c("?");else a(`?<${n}`,-1,2)}}}else if(")"===t)o--,c(")"),r++;else if("\\"===t){let t="\\";if(r++,r<e.length){t+=e[r++];const n=t[1];if(r<e.length){if("u"===n&&"{"===e[r]){l(`${t}{`,"}",0);continue}if("x"===n)t+=e.slice(r,r+2),r+=2;else if(n>="0"&&n<="9")for(;r<e.length&&e[r]>="0"&&e[r]<="9";)t+=e[r++];else{if("k"===n&&"<"===e[r]){l(`${t}<`,">");continue}if(("p"===n||"P"===n)&&"{"===e[r]){l(`${t}{`,"}",0);continue}}}}a(t,1,0)}else if("|"===t||"+"===t||"*"===t||"?"===t||","===t||"^"===t||"$"===t)a(t,3,1);else if("{"===t){r++;let t="";for(;r<e.length&&e[r]>="0"&&e[r]<="9";)t+=e[r++];if(t&&(c("{"),o++,a(t,1,0)),r<e.length)if(","===e[r])t||(c("{"),o++),c(","),r++;else if(!t){o+=1,c("{"),o-=1;continue}let n="";for(;r<e.length&&e[r]>="0"&&e[r]<="9";)n+=e[r++];n&&a(n,1,0),r<e.length&&"}"===e[r]&&(o--,c("}"),r++),r<e.length&&"?"===e[r]&&a("?",3,1)}else if("."===t)a(t,2,1);else{if("/"===t)break;a(t,1,1)}}return a("/",-1,1),r<e.length&&c(e.slice(r)),n},module:"underline"}),Nn.styles.regexp.colors=["green","red","yellow","cyan","magenta"];const Wn=Nn.styles.regexp.colors.slice();function Hn(t,e){return-1===e?`"${t}"`:-2===e?`\`${t}\``:`'${t}'`}function Un(t){const e=Gt(t);return Tn.length>e?Tn[e]:`\\u${lt(e,16)}`}function Gn(t){let e=wn,n=En,r=39;if(Yt(t,"'")&&(Yt(t,'"')?Yt(t,"`")||Yt(t,"${")||(r=-2):r=-1,39!==r&&(e=On,n=Ln)),t.length<5e3&&null===It(e,t))return Hn(t,r);if(t.length>100)return Hn(t=jt(n,t,Un),r);let o="",i=0;for(let e=0;e<t.length;e++){const n=Gt(t,e);if(n===r||92===n||n<32||n>126&&n<160)o+=i===e?Tn[n]:`${re(t,i,e)}${Tn[n]}`,i=e+1;else if(n>=55296&&n<=57343){if(n<=56319&&e+1<t.length){const n=Gt(t,e+1);if(n>=56320&&n<=57343){e++;continue}}o+=`${re(t,i,e)}\\u${lt(n,16)}`,i=e+1}}return i!==t.length&&(o+=re(t,i)),Hn(o,r)}function Vn(t,e){const n=Nn.styles[e];if(void 0!==n){const e=Nn.colors[n];if(void 0!==e)return`[${e[0]}m${t}[${e[1]}m`;if("function"==typeof n)return n(t)}return t}function Zn(t){return t}function Yn(){return[]}function qn(t,e){try{return t instanceof e}catch{return!1}}const Jn=(new zt).set(u,{name:"Array",constructor:s}).set(c,{name:"ArrayBuffer",constructor:l}).set(C,{name:"Function",constructor:N}).set(V,{name:"Map",constructor:G}).set(Ft,{name:"Set",constructor:Ct}).set(bt,{name:"Object",constructor:at}).set(de,{name:"TypedArray",constructor:he}).set(kt,{name:"RegExp",constructor:Rt}).set(k,{name:"Date",constructor:R}).set(L,{name:"DataView",constructor:O}).set(z,{name:"Error",constructor:T}).set(i,{name:"AggregateError",constructor:o}).set(Et,{name:"RangeError",constructor:wt}).set(ge,{name:"TypeError",constructor:ye}).set(w,{name:"Boolean",constructor:_}).set(st,{name:"Number",constructor:et}).set(Ut,{name:"String",constructor:Ht}).set(_t,{name:"Promise",constructor:vt}).set(xe,{name:"WeakMap",constructor:Se}).set(Ae,{name:"WeakSet",constructor:Pe});function Kn(t,e,n,r){let o;const i=t;for(;t||vn(t);){const s=Jn.get(t);if(void 0!==s){const{name:l,constructor:c}=s;if(W(c,i))return void 0!==r&&o!==t&&Qn(e,i,o||i,n,r),l}const l=pt(t,"constructor");if(void 0!==l&&"function"==typeof l.value&&""!==l.value.name&&qn(i,l.value))return void 0===r||o===t&&An.has(l.value.name)||Qn(e,i,o||i,n,r),Ht(l.value.name);t=ht(t),void 0===o&&(o=t)}if(null===o)return null;const s=Te(i);if(n>e.depth&&null!==e.depth)return`${s} <Complex prototype>`;const l=Kn(o,e,n+1,r);return null===l?`${s} <${Nn(o,{...e,customInspect:!1,depth:-1})}>`:`${s} <${l}>`}function Qn(t,e,n,r,o){let i,s,l=0;do{if(0!==l||e===n){if(null===(n=ht(n)))return;const t=pt(n,"constructor");if(void 0!==t&&"function"==typeof t.value&&An.has(t.value.name))return}0===l?s=new Mt:p(i,t=>s.add(t)),i=Lt(n),b(t.seen,e);for(const c of i){if("constructor"===c||$t(e,c)||0!==l&&s.has(c))continue;const i=pt(n,c);if("function"==typeof i.value)continue;const a=Or(t,n,r,c,0,i,e);t.colors?b(o,`${a}`):b(o,a)}m(t.seen)}while(3!==++l)}function Xn(t,e,n,r=""){if(null===t)return""!==e&&n!==e?`[${n}${r}: null prototype] [${e}] `:`[${n}${r}: null prototype] `;let o=`${t}${r} `;if(""!==e){const n=t.indexOf(e);if(-1===n)o+=`[${e}] `;else{const r=n+e.length;r!==t.length&&t[r]===t[r].toLowerCase()&&(o+=`[${e}] `)}}return o}function tr(t,e){let n;const r=gt(t);if(e)n=yt(t),0!==r.length&&$(n,r);else{try{n=mt(t)}catch(e){gn(tn(e)&&"ReferenceError"===e.name&&Xe(t)),n=yt(t)}0!==r.length&&$(n,f(r,e=>St(t,e)))}return n}function er(t,e,n){let r="";return null===e&&(r=Te(t),r===n&&(r="Object")),Xn(e,n,r)}function nr(t,e,o,i){if("object"!=typeof e&&"function"!=typeof e&&!vn(e))return pr(t.stylize,e,t);if(null===e)return t.stylize("null","null");const s=e,l=je(e,!!t.showProxy);if(void 0!==l){if(null===l||null===l[0])return t.stylize("<Revoked Proxy>","special");if(t.showProxy)return function(t,e,n){if(n>t.depth&&null!==t.depth)return t.stylize("Proxy [Array]","special");n+=1,t.indentationLvl+=2;const r=[nr(t,e[0],n),nr(t,e[1],n)];return t.indentationLvl-=2,Rr(t,r,"",["Proxy [","]"],2,n)}(t,l,o);e=l}if(t.customInspect){const n=e[Ne];if("function"==typeof n&&n!==Nn&&pt(e,"constructor")?.value?.prototype!==e){const e=null===t.depth?null:t.depth-o,r=void 0!==l||!W(at,s),i=D(n,s,e,function(t,e){const n={stylize:t.stylize,showHidden:t.showHidden,depth:t.depth,colors:t.colors,customInspect:t.customInspect,showProxy:t.showProxy,maxArrayLength:t.maxArrayLength,maxStringLength:t.maxStringLength,breakLength:t.breakLength,compact:t.compact,sorted:t.sorted,getters:t.getters,numericSeparator:t.numericSeparator,...t.userOptions};if(e){At(n,null);for(const t of mt(n))"object"!=typeof n[t]&&"function"!=typeof n[t]||null===n[t]||delete n[t];n.stylize=At((e,n)=>{let r;try{r=`${t.stylize(e,n)}`}catch{}return"string"!=typeof r?e:r},null)}return n}(t,r),Nn);if(i!==s)return"string"!=typeof i?nr(t,i,o):ne(i,"\n",`\n${te(" ",t.indentationLvl)}`)}}if(t.seen.includes(e)){let n=1;return void 0===t.circular?(t.circular=new zt,t.circular.set(e,n)):(n=t.circular.get(e),void 0===n&&(n=t.circular.size+1,t.circular.set(e,n))),t.stylize(`[Circular *${n}]`,"special")}return function(t,e,o,i){let s,l;t.showHidden&&(o<=t.depth||null===t.depth)&&(l=[]);const c=Kn(e,t,o,l);void 0!==l&&0===l.length&&(l=void 0);let u="";try{u=e[pe]}catch{}("string"!=typeof u||""!==u&&(t.showHidden?$t:St)(e,pe))&&(u="");let f,p,d="",m=Yn,_=!0;const w=t.showHidden?Ee:Oe;let O,L,R=0;if(ce in e||null===c)if(_=!1,a(e)){const t="Array"!==c||""!==u?Xn(c,u,"Array",`(${e.length})`):"";if(s=ke(e,w),f=[`${t}[`,"]"],0===e.length&&0===s.length&&void 0===l)return`${f[0]}]`;R=2,m=dr}else if(nn(e)){const n=Dt(e),r=Xn(c,u,"Set",`(${n})`);if(s=tr(e,t.showHidden),m=F(br,null,null!==c?e:Wt(e)),0===n&&0===s.length&&void 0===l)return`${r}{}`;f=[`${r}{`,"}"]}else if(Ke(e)){const n=Y(e),r=Xn(c,u,"Map",`(${n})`);if(s=tr(e,t.showHidden),m=F($r,null,null!==c?e:Z(e)),0===n&&0===s.length&&void 0===l)return`${r}{}`;f=[`${r}{`,"}"]}else if(an(e)){s=ke(e,w);let n=e,o="";null===c&&(o=be(e),n=new r[o](e));const l=me(e);if(f=[`${Xn(c,u,o,`(${l})`)}[`,"]"],0===e.length&&0===s.length&&!t.showHidden)return`${f[0]}]`;m=F(mr,null,n,l),R=2,t.showHidden&&(O=["BYTES_PER_ELEMENT","length","byteLength","byteOffset","buffer"],i=!0)}else Qe(e)?(s=tr(e,t.showHidden),f=rr("Map",u),m=F(_r,null,f)):rn(e)?(s=tr(e,t.showHidden),f=rr("Set",u),m=F(_r,null,f)):_=!0;if(_)if(s=tr(e,t.showHidden),f=["{","}"],"function"==typeof e){if(d=function(t,e,n,r){const o=H(e);if(ie(o,"class")&&"}"===o[o.length-1]){const t=re(o,5,-1),i=qt(t,"{");if(-1!==i&&(!Yt(re(t,0,i),"(")||null!==It(jn,jt(Bn,t))))return function(t,e,n){let r=`class ${$t(t,"name")&&t.name||"(anonymous)"}`;if("Function"!==e&&null!==e&&(r+=` [${e}]`),""!==n&&e!==n&&(r+=` [${n}]`),null!==e){const e=ht(t).name;e&&(r+=` extends ${e}`)}else r+=" extends [null prototype]";return`[${r}]`}(e,n,r)}let i="Function";Ue(e)&&(i=`Generator${i}`),He(e)&&(i=`Async${i}`);let s=`[${i}`;return null===n&&(s+=" (null prototype)"),""===e.name?s+=" (anonymous)":s+=`: ${"string"==typeof e.name?e.name:nr(t,e.name)}`,s+="]",n!==i&&null!==n&&(s+=` ${n}`),""!==r&&n!==r&&(s+=` [${r}]`),s}(t,e,c,u),0===s.length&&void 0===l)return t.stylize(d,"special")}else if("Object"===c){if(Ze(e)?f[0]="[Arguments] {":""!==u&&(f[0]=`${Xn(c,u,"Object")}{`),0===s.length&&void 0===l)return`${f[0]}}`}else if(ln(e)){d=Tt(null!==c?e:new Rt(e));const n=Xn(c,u,"RegExp");if("RegExp "!==n&&(d=`${n}${d}`),d=t.stylize(d,"regexp"),0===s.length&&void 0===l||o>t.depth&&null!==t.depth)return d}else if(cn(e)){d=rt(I(e))?B(e):j(e);const n=Xn(c,u,"Date");if("Date "!==n&&(d=`${n}${d}`),0===s.length&&void 0===l)return t.stylize(d,"date")}else if(Ce(e)){if(d=function(t,e,n,r,o){let i,s,l;try{l=ir(r,t)}catch{return xt(t)}let c=!1;try{i=t.message}catch{c=!0}let u=!1;try{s=t.name}catch{u=!0}if(!r.showHidden&&0!==o.length){const t=g(o,"stack");if(-1!==t&&P(o,t,1),!c){const t=g(o,"message");-1===t||"string"==typeof i&&!Yt(l,i)||P(o,t,1)}if(!u){const t=g(o,"name");-1===t||"string"==typeof s&&!Yt(l,s)||P(o,t,1)}}s=null==s?"Error":s,!$t(t,"cause")||0!==o.length&&y(o,"cause")||b(o,"cause");try{const e=t.errors;!a(e)||!$t(t,"errors")||0!==o.length&&y(o,"errors")||b(o,"errors")}catch{}l=function(t,e,n,r){let o=n.length;if("string"!=typeof n&&(t=ee(t,`${n}`,`${n} [${re(Xn(e,r,"Error"),0,-1)}]`)),null===e||Zt(n,"Error")&&ie(t,n)&&(t.length===o||":"===t[o]||"\n"===t[o])){let i="Error";if(null===e){const e=It(/^([A-Z][a-z_ A-Z0-9[\]()-]+)(?::|\n {4}at)/,t)||It(/^([a-z_A-Z0-9-]*Error)$/,t);i=e?.[1]||"",o=i.length,i=i||"Error"}const s=re(Xn(e,r,i),0,-1);n!==s&&(t=Yt(s,n)?0===o?`${s}: ${t}`:`${s}${re(t,o)}`:`${s} [${n}]${re(t,o)}`)}return t}(l,e,s,n);let f=i&&qt(l,i)||-1;-1!==f&&(f+=i.length);const p=qt(l,"\n at",f);if(-1===p)l=`[${l}]`;else{let e=re(l,0,p);const n=function(t,e,n){const r=oe(n,"\n");let o;try{({cause:o}=e)}catch{}if(null!=o&&Ce(o)){const e=ir(t,o),n=qt(e,"\n at");if(-1!==n){const o=oe(re(e,n+1),"\n"),{0:i,1:s}=or(r,o);if(i>0){const e=i-2,n=` ... ${e} lines matching cause stack trace ...`;r.splice(s+1,e,t.stylize(n,"undefined"))}}}if(r.length>10){const e=function(t){const e=[],n=new zt;for(let e=0;e<t.length;e++){const r=n.get(t[e]);void 0===r?n.set(t[e],[e]):r[r.length]=e}if(t.length-n.size<=3)return e;for(let r=0;r<t.length-3;r++){const o=n.get(t[r]);if(1===o.length||o[o.length-1]===r)continue;const i=o.indexOf(r)+1;if(i===o.length)continue;let s,l=o[o.length-1]-r;if(l<3)continue;if(i+1<o.length){let t=0;for(let e=i;e<o.length;e++){let n=o[e]-r;for(;0!==n;){const e=t%n;0!==t&&(s=s||new Mt,s.add(t)),t=n,n=e}if(1===t)break}l=t,s&&(s.delete(l),s=[...s])}let c=l,a=0,u=0;for(let e=r+l;;e+=l){let n=0;for(let o=0;o<l&&t[r+o]===t[e+o];o++)n++;if(n===l)u++;else{if(!s?.length)break;0!==u&&c*a<l*u&&(c=l,a=u),l=s.pop(),e=r,u=0}}0!==a&&c*a>=l*u&&(l=c,u=a),u*l>=3&&(e.push(r+l,l,u),r+=l*(u+1)-1)}return e}(r);for(let n=e.length-3;n>=0;n-=3){const o=e[n],i=e[n+1],s=e[n+2],l=` ... collapsed ${i*s} duplicate lines matching above `+(s>1?`${i} lines ${s} times...`:"lines ...");r.splice(o,i*s,t.stylize(l,"undefined"))}}return r}(r,t,re(l,p+1));if(r.colors){const t=function(){let t;try{t=process.cwd()}catch{return}return t}();let o;for(let i of n){const n=It(In,i);if(null!==n&&hn.exists(n[1]))e+=`\n${r.stylize(i,"undefined")}`;else{if(e+="\n",i=sr(r,i),void 0!==t){let e=lr(r,i,t);e===i&&(o=o||Pn(t),e=lr(r,i,o)),i=e}e+=i}}}else e+=`\n${h(n,"\n")}`;l=e}if(0!==r.indentationLvl){const t=te(" ",r.indentationLvl);l=ne(l,"\n",`\n${t}`)}return l}(e,c,u,t,s),0===s.length&&void 0===l)return d}else if(Ge(e)){const n=Xn(c,u,Ve(e)?"ArrayBuffer":"SharedArrayBuffer");if(void 0===i)m=hr;else if(0===s.length&&void 0===l)return n+`{ [byteLength]: ${ur(t.stylize,e.byteLength,!1)} }`;f[0]=`${n}{`,O=["byteLength"]}else if(qe(e))f[0]=`${Xn(c,u,"DataView")}{`,O=["byteLength","byteOffset","buffer"];else if(en(e))f[0]=`${Xn(c,u,"Promise")}{`,m=wr;else if(sn(e))f[0]=`${Xn(c,u,"WeakSet")}{`,m=t.showHidden?Ar:Pr;else if(on(e))f[0]=`${Xn(c,u,"WeakMap")}{`,m=t.showHidden?vr:Pr;else if(Xe(e))f[0]=`${Xn(c,u,"Module")}{`,m=yr.bind(null,s);else if(Ye(e)){if(d=function(t,e,n,r,o){let i,s;fn(t)?(i=ct,s="Number"):un(t)?(i=le,s="String",n.splice(0,t.length)):pn(t)?(i=E,s="Boolean"):yn(t)?(i=v,s="BigInt"):(i=ue,s="Symbol");let l=`[${s}`;return s!==r&&(l+=null===r?" (null prototype)":` (${r})`),l+=`: ${pr(Zn,i(t),e)}]`,""!==o&&o!==r&&(l+=` [${o}]`),0!==n.length||e.stylize===Zn?l:e.stylize(l,se(s))}(e,t,s,c,u),0===s.length&&void 0===l)return d}else if(!function(t){return Sn=Sn||n(511),"string"==typeof t.href&&t instanceof Sn.URL}(e)||o>t.depth&&null!==t.depth){if(0===s.length&&void 0===l){if(Je(e)){const n=ze(e).toString(16);return t.stylize(`[External: ${n}]`,"special")}return`${er(e,c,u)}{}`}f[0]=`${er(e,c,u)}{`}else if(s=function(t){return xn=xn||gt(new Sn.URL("http://user:pass@localhost:8080/?foo=bar#baz")),t.filter(t=>-1===xn[t])}(s),d=e.href,0===s.length&&void 0===l)return d;if(o>t.depth&&null!==t.depth){let n=re(er(e,c,u),0,-1);return null!==c&&(n=`[${n}]`),t.stylize(n,"special")}o+=1,t.seen.push(e),t.currentDepth=o;const k=t.indentationLvl;try{if(L=m(t,e,o),void 0!==O)for(p=0;p<O.length;p++){let n;try{n=Er(t,e,o,O[p],i)}catch{n=Er(t,{[O[p]]:e.buffer[O[p]]},o,O[p],i)}b(L,n)}for(p=0;p<s.length;p++)b(L,Or(t,e,o,s[p],R));void 0!==l&&$(L,l)}catch(n){if(!We(n))throw n;return function(t,e,n,r){return t.seen.pop(),t.indentationLvl=r,t.stylize(`[${n}: Inspection interrupted prematurely. Maximum call stack size exceeded.]`,"special")}(t,0,re(er(e,c,u),0,-1),k)}if(void 0!==t.circular){const n=t.circular.get(e);if(void 0!==n){const e=t.stylize(`<ref *${n}>`,"special");!0!==t.compact?d=""===d?e:`${e} ${d}`:f[0]=`${e} ${f[0]}`}}if(t.seen.pop(),t.sorted){const e=!0===t.sorted?void 0:t.sorted;if(0===R)x(L,e);else if(s.length>1){const t=x(S(L,L.length-s.length),e);A(t,L,L.length-s.length,s.length),Ot(P,null,t)}}const T=Rr(t,L,d,f,R,o,e),z=(t.budget[t.indentationLvl]||0)+T.length;return t.budget[t.indentationLvl]=z,z>2**27&&(t.depth=-1),T}(t,e,o,i)}function rr(t,e){return e!==`${t} Iterator`&&(""!==e&&(e+="] ["),e+=`${t} Iterator`),[`[${e}] {`,"}"]}function or(t,e){for(let n=0;n<t.length-3;n++){const r=g(e,t[n]);if(-1!==r){const o=e.length-r;if(o>3){let i=1;const s=K(t.length-n,o);for(;s>i&&t[n+i]===e[r+i];)i++;if(i>3)return[i,n]}}}return[0,0]}function ir(t,e){let n;try{n=e.stack}catch{}if(n){if("string"==typeof n)return n;t.seen.push(e),t.indentationLvl+=4;const r=nr(t,n);return t.indentationLvl-=4,t.seen.pop(),`${M(e)}\n ${r}`}return M(e)}function sr(t,e){let n="",r=0,o=0;for(;;){const i=qt(e,"node_modules",o);if(-1===i)break;const s=e[i-1],l=e[i+12];if("/"!==l&&"\\"!==l||"/"!==s&&"\\"!==s){o=i+1;continue}const c=i+13;n+=re(e,r,c);let a=qt(e,s,c);"@"===e[c]&&(a=qt(e,s,a+1));const u=re(e,c,a);n+=t.stylize(u,"module"),r=a,o=a}return 0!==r&&(e=n+re(e,r)),e}function lr(t,e,n){let r=qt(e,n),o="",i=n.length;if(-1!==r){"file://"===re(e,r-7,r)&&(i+=7,r-=7);const n="("===e[r-1]?r-1:r,s=n!==r&&Zt(e,")")?-1:e.length,l=r+i+1,c=re(e,n,l);o+=re(e,0,n),o+=t.stylize(c,"undefined"),o+=re(e,l,s),-1===s&&(o+=t.stylize(")","undefined"))}else o+=e;return o}function cr(t){let e="",n=t.length;gn(0!==n);const r="-"===t[0]?1:0;for(;n>=r+4;n-=3)e=`_${re(t,n-3,n)}${e}`;return n===t.length?t:`${re(t,0,n)}${e}`}const ar=t=>`... ${t} more item${t>1?"s":""}`;function ur(t,e,n){if(!n)return dt(e,-0)?t("-0","number"):t(`${e}`,"number");const r=Ht(e);if(tt(e)===e)return!nt(e)||Yt(r,"e")?t(r,"number"):t(cr(r),"number");if(rt(e))return t(r,"number");const o=qt(r,"."),i=re(r,0,o),s=re(r,o+1);return t(`${cr(i)}.${function(t){let e="",n=0;for(;n<t.length-3;n+=3)e+=`${re(t,n,n+3)}_`;return 0===n?t:`${e}${re(t,n)}`}(s)}`,"number")}function fr(t,e,n){const r=Ht(e);return t(n?`${cr(r)}n`:`${r}n`,"bigint")}function pr(t,e,n){if("string"==typeof e){let r="";if(e.length>n.maxStringLength){const t=e.length-n.maxStringLength;e=re(e,0,n.maxStringLength),r=`... ${t} more character${t>1?"s":""}`}return!0!==n.compact&&e.length>16&&e.length>n.breakLength-n.indentationLvl-4?h(d(Bt(/(?<=\n)/,e),e=>t(Gn(e),"string")),` +\n${te(" ",n.indentationLvl+2)}`)+r:t(Gn(e),"string")+r}return"number"==typeof e?ur(t,e,n.numericSeparator):"bigint"==typeof e?fr(t,e,n.numericSeparator):"boolean"==typeof e?t(`${e}`,"boolean"):void 0===e?t("undefined","undefined"):t(ae(e),"symbol")}function yr(t,e,n,r){const o=new s(t.length);for(let i=0;i<t.length;i++)try{o[i]=Or(e,n,r,t[i],0)}catch(n){gn(tn(n)&&"ReferenceError"===n.name);const s={[t[i]]:""};o[i]=Or(e,s,r,t[i],0);const l=Jt(o[i]," ");o[i]=re(o[i],0,l+1)+e.stylize("<uninitialized>","special")}return t.length=0,o}function gr(t,e,n,r,o,i){const s=mt(e);let l=i;for(;i<s.length&&o.length<r;i++){const c=s[i],a=+c;if(a>2**32-2)break;if(`${l}`!==c){if(null===It(kn,c))break;const e=a-l,n=`<${e} empty item${e>1?"s":""}>`;if(b(o,t.stylize(n,"undefined")),l=a,o.length===r)break}b(o,Or(t,e,n,c,1)),l++}const c=e.length-l;if(o.length!==r){if(c>0){const e=`<${c} empty item${c>1?"s":""}>`;b(o,t.stylize(e,"undefined"))}}else c>0&&b(o,ar(c));return o}function hr(t,e){let r;try{r=new $e(e)}catch{return[t.stylize("(detached)","special")]}void 0===$n&&($n=we(n(242).h.prototype.hexSlice));const o=$n(r,0,K(t.maxArrayLength,r.length));let i="",s=0;for(;s<o.length-2;s+=2)i+=`${o[s]}${o[s+1]} `;o.length>0&&(i+=`${o[s]}${o[s+1]}`);const l=r.length-t.maxArrayLength;return l>0&&(i+=` ... ${l} more byte${l>1?"s":""}`),[`${t.stylize("[Uint8Contents]","special")}: <${i}>`]}function dr(t,e,n){const r=e.length,o=K(J(0,t.maxArrayLength),r),i=r-o,s=[];for(let r=0;r<o;r++){const i=pt(e,r);if(void 0===i)return gr(t,e,n,o,s,r);b(s,Or(t,e,n,r,1,i))}return i>0&&b(s,ar(i)),s}function mr(t,e,n){const r=K(J(0,n.maxArrayLength),e),o=t.length-r,i=new s(r),l=t.length>0&&"number"==typeof t[0]?ur:fr;for(let e=0;e<r;++e)i[e]=l(n.stylize,t[e],n.numericSeparator);return o>0&&(i[r]=ar(o)),i}function br(t,e,n,r){const o=t.size,i=K(J(0,e.maxArrayLength),o),s=o-i,l=[];e.indentationLvl+=2;let c=0;for(const n of t){if(c>=i)break;b(l,nr(e,n,r)),c++}return s>0&&b(l,ar(s)),e.indentationLvl-=2,l}function $r(t,e,n,r){const o=t.size,i=K(J(0,e.maxArrayLength),o),s=o-i,l=[];e.indentationLvl+=2;let c=0;for(const{0:n,1:o}of t){if(c>=i)break;b(l,`${nr(e,n,r)} => ${nr(e,o,r)}`),c++}return s>0&&b(l,ar(s)),e.indentationLvl-=2,l}function Sr(t,e,n,r){const o=J(t.maxArrayLength,0),i=K(o,n.length),l=new s(i);t.indentationLvl+=2;for(let r=0;r<i;r++)l[r]=nr(t,n[r],e);t.indentationLvl-=2,0!==r||t.sorted||x(l);const c=n.length-i;return c>0&&b(l,ar(c)),l}function xr(t,e,n,r){const o=J(t.maxArrayLength,0),i=n.length/2,l=i-o,c=K(o,i),a=new s(c);let u=0;if(t.indentationLvl+=2,0===r){for(;u<c;u++){const r=2*u;a[u]=`${nr(t,n[r],e)} => ${nr(t,n[r+1],e)}`}t.sorted||x(a)}else for(;u<c;u++){const r=2*u,o=[nr(t,n[r],e),nr(t,n[r+1],e)];a[u]=Rr(t,o,"",["[","]"],2,e)}return t.indentationLvl-=2,l>0&&b(a,ar(l)),a}function Pr(t){return[t.stylize("<items unknown>","special")]}function Ar(t,e,n){return Sr(t,n,Be(e),0)}function vr(t,e,n){return xr(t,n,Be(e),0)}function _r(t,e,n,r){const{0:o,1:i}=Be(n,!0);return i?(t[0]=jt(/ Iterator] {$/,t[0]," Entries] {"),xr(e,r,o,2)):Sr(e,r,o,1)}function wr(t,e,n){let r;const{0:o,1:i}=Ie(e);if(o===Le)r=[t.stylize("<pending>","special")];else{t.indentationLvl+=2;const e=nr(t,i,n);t.indentationLvl-=2,r=[o===Re?`${t.stylize("<rejected>","special")} ${e}`:e]}return r}function Er(t,e,n,r,o){t.indentationLvl+=2;const i=nr(t,e[r],n,o);return t.indentationLvl-=2,`${t.stylize(`[${r}]`,"string")}: ${i}`}function Or(t,e,n,r,o,i,s=e){let l,c,a=" ";if(void 0!==(i=i||pt(e,r)).value){const e=!0!==t.compact||0!==o?2:3;t.indentationLvl+=e,c=nr(t,i.value,n),3===e&&t.breakLength<Mn(c,t.colors)&&(a=`\n${te(" ",t.indentationLvl)}`),t.indentationLvl-=e}else if(void 0!==i.get){const e=void 0!==i.set?"Getter/Setter":"Getter",r=t.stylize,o="special";if(t.getters&&(!0===t.getters||"get"===t.getters&&void 0===i.set||"set"===t.getters&&void 0!==i.set)){t.indentationLvl+=2;try{const l=D(i.get,s);if(null===l)c=`${r(`[${e}:`,o)} ${r("null","null")}${r("]",o)}`;else if("object"==typeof l)c=`${r(`[${e}]`,o)} ${nr(t,l,n)}`;else{const n=pr(r,l,t);c=`${r(`[${e}:`,o)} ${n}${r("]",o)}`}}catch(i){const s=`<Inspection threw (${nr(t,i,n)})>`;c=`${r(`[${e}:`,o)} ${s}${r("]",o)}`}t.indentationLvl-=2}else c=t.stylize(`[${e}]`,o)}else c=void 0!==i.set?t.stylize("[Setter]","special"):t.stylize("undefined","undefined");if(1===o)return c;if("symbol"==typeof r){const e=jt(En,ae(r),Un);l=t.stylize(e,"symbol")}else l=null!==It(Rn,r)?"__proto__"===r?"['__proto__']":t.stylize(r,"name"):t.stylize(Gn(r),"string");return!1===i.enumerable&&(l=`[${l}]`),`${l}:${a}${c}`}function Lr(t,e,n,r){let o=e.length+n;if(o+e.length>t.breakLength)return!1;for(let n=0;n<e.length;n++)if(t.colors?o+=De(e[n]).length:o+=e[n].length,o>t.breakLength)return!1;return""===r||!Yt(r,"\n")}function Rr(t,e,n,r,o,i,l){if(!0!==t.compact){if("number"==typeof t.compact&&t.compact>=1){const c=e.length;if(2===o&&c>6&&(e=function(t,e,n){let r=0,o=0,i=0,l=e.length;t.maxArrayLength<e.length&&l--;const c=new s(l);for(;i<l;i++){const n=Mn(e[i],t.colors);c[i]=n,r+=n+2,o<n&&(o=n)}const a=o+2;if(3*a+t.indentationLvl<t.breakLength&&(r/a>5||o<=6)){const o=2.5,i=X(a-r/e.length),s=J(a-3-i,1),u=K(Q(X(o*s*l)/s),q((t.breakLength-t.indentationLvl)/a),4*t.compact,15);if(u<=1)return e;const f=[],p=[];for(let t=0;t<u;t++){let n=0;for(let r=t;r<e.length;r+=u)c[r]>n&&(n=c[r]);n+=2,p[t]=n}let y=Xt;if(void 0!==n)for(let t=0;t<e.length;t++)if("number"!=typeof n[t]&&"bigint"!=typeof n[t]){y=Qt;break}for(let t=0;t<l;t+=u){const n=K(t+u,l);let r="",o=t;for(;o<n-1;o++){const n=p[o-t]+e[o].length-c[o];r+=y(`${e[o]}, `,n," ")}if(y===Xt){const n=p[o-t]+e[o].length-c[o]-2;r+=Xt(e[o],n," ")}else r+=e[o];b(f,r)}t.maxArrayLength<e.length&&b(f,e[l]),e=f}return e}(t,e,l)),t.currentDepth-i<t.compact&&c===e.length&&Lr(t,e,e.length+t.indentationLvl+r[0].length+n.length+10,n)){const t=Fe(e,", ");if(!Yt(t,"\n"))return`${n?`${n} `:""}${r[0]} ${t} ${r[1]}`}}const c=`\n${te(" ",t.indentationLvl)}`;return`${n?`${n} `:""}${r[0]}${c} ${Fe(e,`,${c} `)}${c}${r[1]}`}if(Lr(t,e,0,n))return`${r[0]}${n?` ${n}`:""} ${Fe(e,", ")} `+r[1];const c=te(" ",t.indentationLvl),a=""===n&&1===r[0].length?" ":`${n?` ${n}`:""}\n${c} `;return`${r[0]}${a}${Fe(e,`,\n${c} `)} ${r[1]}`}function kr(t){const e=je(t,!1);if(void 0!==e){if(null===e)return!0;t=e}let n=$t,r=$t;if("function"!=typeof t.toString){if("function"!=typeof t[fe])return!0;if($t(t,fe))return!1;n=Ir}else{if($t(t,"toString"))return!1;if("function"!=typeof t[fe])r=Ir;else if($t(t,fe))return!1}let o=t;do{o=ht(o)}while(!n(o,"toString")&&!r(o,fe));const i=pt(o,"constructor");return void 0!==i&&"function"==typeof i.value&&An.has(i.value.name)}function Ir(){return!1}const jr=t=>oe(t.message,"\n",1)[0];let Br;function Tr(t){try{return U(t)}catch(t){if(!Br)try{const t={};t.a=t,U(t)}catch(t){Br=jr(t)}if("TypeError"===t.name&&jr(t)===Br)return"[Circular]";throw t}}function zr(t,e){return ur(Zn,t,e?.numericSeparator??_n.numericSeparator)}function Mr(t,e){return fr(Zn,t,e?.numericSeparator??_n.numericSeparator)}function Nr(t,e){const n=e[0];let r=0,o="",i="";if("string"==typeof n){if(1===e.length)return n;let s,l=0;for(let i=0;i<n.length-1;i++)if(37===Gt(n,i)){const c=Gt(n,++i);if(r+1!==e.length){switch(c){case 115:{const n=e[++r];s="number"==typeof n?zr(n,t):"bigint"==typeof n?Mr(n,t):"object"==typeof n&&null!==n&&kr(n)?Nn(n,{...t,compact:3,colors:!1,depth:0}):Ht(n);break}case 106:s=Tr(e[++r]);break;case 100:{const n=e[++r];s="bigint"==typeof n?Mr(n,t):"symbol"==typeof n?"NaN":zr(et(n),t);break}case 79:s=Nn(e[++r],t);break;case 111:s=Nn(e[++r],{...t,showHidden:!0,showProxy:!0,depth:4});break;case 105:{const n=e[++r];s="bigint"==typeof n?Mr(n,t):"symbol"==typeof n?"NaN":zr(it(n),t);break}case 102:{const n=e[++r];s="symbol"==typeof n?"NaN":zr(ot(n),t);break}case 99:r+=1,s="";break;case 37:o+=re(n,l,i),l=i+1;continue;default:continue}l!==i-1&&(o+=re(n,l,i-1)),o+=s,l=i+1}else 37===c&&(o+=re(n,l,i),l=i+1)}0!==l&&(r++,i=" ",l<n.length&&(o+=re(n,l)))}for(;r<e.length;){const n=e[r];o+=i,o+="string"!=typeof n?Nn(n,t):n,i=" ",r++}return o}function Cr(t){return t<=31||t>=127&&t<=159||t>=768&&t<=879||t>=8203&&t<=8207||t>=8400&&t<=8447||t>=65024&&t<=65039||t>=65056&&t<=65071||t>=917760&&t<=917999}if(_e("config").hasIntl)gn(!1);else{Mn=function(e,n=!0){let r=0;n&&(e=Fr(e)),e=Kt(e,"NFC");for(const n of new Nt(e)){const e=Vt(n,0);t(e)?r+=2:Cr(e)||r++}return r};const t=t=>t>=4352&&(t<=4447||9001===t||9002===t||t>=11904&&t<=12871&&12351!==t||t>=12880&&t<=19903||t>=19968&&t<=42182||t>=43360&&t<=43388||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65040&&t<=65049||t>=65072&&t<=65131||t>=65281&&t<=65376||t>=65504&&t<=65510||t>=110592&&t<=110593||t>=127488&&t<=127569||t>=127744&&t<=128591||t>=131072&&t<=262141)}function Fr(t){return mn(t,"str"),-1===qt(t,"")&&-1===qt(t,"›")?t:jt(zn,t,"")}const Dr={34:"&quot;",38:"&amp;",39:"&apos;",60:"&lt;",62:"&gt;",160:"&nbsp;"};function Wr(t){return t.replace(/[\u0000-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u00FF]/g,t=>{const e=Ht(t.charCodeAt(0));return Dr[e]||"&#"+e+";"})}t.exports={identicalSequenceRange:or,inspect:Nn,inspectDefaultOptions:_n,format:function(...t){return Nr(void 0,t)},formatWithOptions:function(t,...e){return dn(t,"inspectOptions",bn),Nr(t,e)},getStringWidth:Mn,stripVTControlCharacters:Fr,isZeroWidthCodePoint:Cr,stylizeWithColor:Vn,stylizeWithHTML(t,e){const n=Nn.styles[e];return void 0!==n?`<span style="color:${n};">${Wr(t)}</span>`:Wr(t)},Proxy:Me}},146(t,e,n){let r;function o(){return r=null!=r?r:n(923).codes.ERR_INTERNAL_ASSERTION}function i(t,e){if(!t)throw new(o())(e)}i.fail=function(t){throw new(o())(t)},t.exports=i},996(t){const e=["_http_agent","_http_client","_http_common","_http_incoming","_http_outgoing","_http_server","_stream_duplex","_stream_passthrough","_stream_readable","_stream_transform","_stream_wrap","_stream_writable","_tls_common","_tls_wrap","assert","assert/strict","async_hooks","buffer","child_process","cluster","console","constants","crypto","dgram","diagnostics_channel","dns","dns/promises","domain","events","fs","fs/promises","http","http2","https","inspector","module","Module","net","os","path","path/posix","path/win32","perf_hooks","process","punycode","querystring","readline","readline/promises","repl","stream","stream/consumers","stream/promises","stream/web","string_decoder","sys","timers","timers/promises","tls","trace_events","tty","url","util","util/types","v8","vm","wasi","worker_threads","zlib"];t.exports.BuiltinModule={exists:t=>"internal/modules/cjs/foo"!==t&&(t.startsWith("internal/")||-1!==e.indexOf(t))}},575(t){t.exports={CHAR_DOT:46,CHAR_FORWARD_SLASH:47,CHAR_BACKWARD_SLASH:92}},923(t,e,n){const r=n(714),{ArrayIsArray:o,ArrayPrototypeIncludes:i,ArrayPrototypeIndexOf:s,ArrayPrototypeJoin:l,ArrayPrototypePush:c,ArrayPrototypeSlice:a,ArrayPrototypeSplice:u,Error:f,ErrorCaptureStackTrace:p,JSONStringify:y,ObjectDefineProperty:g,ReflectApply:h,RegExpPrototypeExec:d,SafeMap:m,SafeWeakMap:b,String:$,StringPrototypeEndsWith:S,StringPrototypeIncludes:x,StringPrototypeIndexOf:P,StringPrototypeSlice:A,StringPrototypeToLowerCase:v,Symbol:_,TypeError:w}=r,E=_("kIsNodeError"),O=new m,L={},R=/^[A-Z][a-zA-Z0-9]*$/,k=["string","function","number","object","Function","Object","boolean","bigint","symbol"],I=new b,j=n(146);let B,T,z=null;function M(t,e,n){O.set(t,e);const r=(o=n,i=t,class extends o{code=i;constructor(...t){super(),g(this,"message",{__proto__:null,value:N(i,t,this),enumerable:!1,writable:!0,configurable:!0})}toString(){return`${this.name} [${i}]: ${this.message}`}});var o,i;L[t]=r}function N(t,e,n){const r=O.get(t);if("function"==typeof r)return j(r.length<=e.length,`Code: ${t}; The provided arguments length (${e.length}) does not match the required ones (${r.length}).`),h(r,n,e)}const C=_("kEnhanceStackBeforeInspector");function F(t){if(null===t)return"null";if(void 0===t)return"undefined";switch(typeof t){case"bigint":return`type bigint (${t}n)`;case"number":return 0===t?1/t==-1/0?"type number (-0)":"type number (0)":t!=t?"type number (NaN)":t===1/0?"type number (Infinity)":t===-1/0?"type number (-Infinity)":`type number (${t})`;case"boolean":return t?"type boolean (true)":"type boolean (false)";case"symbol":return`type symbol (${$(t)})`;case"function":return`function ${t.name}`;case"object":return t.constructor&&"name"in t.constructor?`an instance of ${t.constructor.name}`:`${(z=z||n(702),z).inspect(t,{depth:-1})}`;case"string":return t.length>28&&(t=`${A(t,0,25)}...`),-1===P(t,"'")?`type string ('${t}')`:`type string (${y(t)})`}}function D(t,e="and"){switch(t.length){case 0:return"";case 1:return`${t[0]}`;case 2:return`${t[0]} ${e} ${t[1]}`;case 3:return`${t[0]}, ${t[1]}, ${e} ${t[2]}`;default:return`${l(a(t,0,-1),", ")}, ${e} ${t[t.length-1]}`}}t.exports={codes:L,determineSpecificType:F,E:M,formatList:D,getMessage:N,hideStackFrames:function(t){function e(...n){try{return h(t,this,n)}catch(t){throw f.stackTraceLimit&&p(t,e),t}}return e.withoutStackTrace=t,e},isStackOverflowError:function(t){if(void 0===T)try{function e(){e()}e()}catch(t){T=t.message,B=t.name}return t&&t.name===B&&t.message===T},kEnhanceStackBeforeInspector:C,kIsNodeError:E,overrideStackTrace:I},M("ERR_INTERNAL_ASSERTION",t=>{const e="This is caused by either a bug in Node.js or incorrect usage of Node.js internals.\nPlease open an issue with this stack trace at https://github.com/nodejs/node/issues\n";return void 0===t?e:`${t}\n${e}`},f),M("ERR_INVALID_ARG_TYPE",(t,e,n)=>{j("string"==typeof t,"'name' must be a string"),o(e)||(e=[e]);let r="The ";S(t," argument")?r+=`${t} `:r+=`"${t}" ${x(t,".")?"property":"argument"} `,r+="must be ";const l=[],a=[],f=[];for(const t of e)j("string"==typeof t,"All expected entries have to be of type string"),i(k,t)?c(l,v(t)):null!==d(R,t)?c(a,t):(j("object"!==t,'The value "object" should be written as "Object"'),c(f,t));if(a.length>0){const t=s(l,"object");-1!==t&&(u(l,t,1),c(a,"Object"))}return l.length>0&&(r+=`${l.length>1?"one of type":"of type"} ${D(l,"or")}`,(a.length>0||f.length>0)&&(r+=" or ")),a.length>0&&(r+=`an instance of ${D(a,"or")}`,f.length>0&&(r+=" or ")),f.length>0&&(f.length>1?r+=`one of ${D(f,"or")}`:(v(f[0])!==f[0]&&(r+="an "),r+=`${f[0]}`)),r+=`. Received ${F(n)}`,r},w)},511(t,e,n){const{StringPrototypeCharCodeAt:r,StringPrototypeIncludes:o,StringPrototypeReplace:i}=n(714),s=n(851),{CHAR_FORWARD_SLASH:l}=n(575),c=n(811),a=/%/g,u=/\\/g,f=/\n/g,p=/\r/g,y=/\t/g;t.exports={pathToFileURL:function(t){const e=new s("file://");let n=c.resolve(t);return r(t,t.length-1)===l&&n[n.length-1]!==c.sep&&(n+="/"),e.pathname=function(t){return o(t,"%")&&(t=i(t,a,"%25")),o(t,"\\")&&(t=i(t,u,"%5C")),o(t,"\n")&&(t=i(t,f,"%0A")),o(t,"\r")&&(t=i(t,p,"%0D")),o(t,"\t")&&(t=i(t,y,"%09")),t}(n),e},URL:s}},992(t,e,n){const r=n(714),{ArrayPrototypeJoin:o,Error:i,ErrorIsError:s,FunctionPrototypeSymbolHasInstance:l,StringPrototypeReplace:c,SymbolFor:a}=r,u=/\u001b\[\d\d?m/g;t.exports={customInspectSymbol:a("nodejs.util.inspect.custom"),isError:t=>s?.(t)||l(i,t),join:o,removeColors:t=>c(t,u,"")}},134(t,e,n){const r=n(714),{ArrayIsArray:o,BigInt:i,Boolean:s,DatePrototype:l,Error:c,FunctionPrototype:a,MapPrototypeHas:u,Number:f,ObjectDefineProperty:p,ObjectGetOwnPropertyDescriptor:y,ObjectGetPrototypeOf:g,ObjectIsFrozen:h,ObjectPrototype:d,SetPrototypeHas:m,String:b,Symbol:$,SymbolToStringTag:S,globalThis:x}=r,{getConstructorName:P}=n(596);function A(t,...e){for(const n of e){const e=x[n];if(e&&t instanceof e)return!0}for(;t;){if("object"!=typeof t)return!1;if(e.indexOf(P(t))>=0)return!0;t=g(t)}return!1}function v(t){return e=>{if(!A(e,t.name))return!1;try{t.prototype.valueOf.call(e)}catch{return!1}return!0}}"object"!=typeof x&&(p(d,"__magic__",{get:function(){return this},configurable:!0}),__magic__.globalThis=__magic__,delete d.__magic__);const _=v(b),w=v(f),E=v(s),O=v(i),L=v($);t.exports={isAsyncFunction:t=>"function"==typeof t&&a.toString.call(t).startsWith("async"),isGeneratorFunction:t=>"function"==typeof t&&a.toString.call(t).match(/^(async\s+)?function *\*/),isAnyArrayBuffer:t=>A(t,"ArrayBuffer","SharedArrayBuffer"),isArrayBuffer:t=>A(t,"ArrayBuffer"),isArgumentsObject(t){if(null!==t&&"object"==typeof t&&!o(t)&&"number"==typeof t.length&&t.length===(0|t.length)&&t.length>=0){const e=y(t,"callee");return e&&!e.enumerable}return!1},isBoxedPrimitive:t=>w(t)||_(t)||E(t)||O(t)||L(t),isDataView:t=>A(t,"DataView"),isExternal:t=>"object"==typeof t&&h(t)&&null==g(t),isMap(t){if(!A(t,"Map"))return!1;try{u(t)}catch{return!1}return!0},isMapIterator:t=>"[object Map Iterator]"===d.toString.call(g(t)),isModuleNamespaceObject(t){try{return t&&"object"==typeof t&&"Module"===t[S]}catch{return!1}},isNativeError:t=>t instanceof c&&A(t,"Error","EvalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError","AggregateError"),isPromise:t=>A(t,"Promise"),isSet(t){if(!A(t,"Set"))return!1;try{m(t)}catch{return!1}return!0},isSetIterator:t=>"[object Set Iterator]"===d.toString.call(g(t)),isWeakMap:t=>A(t,"WeakMap"),isWeakSet:t=>A(t,"WeakSet"),isRegExp:t=>A(t,"RegExp"),isDate(t){if(A(t,"Date"))try{return l.getTime.call(t),!0}catch{}return!1},isTypedArray:t=>A(t,"Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Uint16Array","Int32Array","Uint32Array","Float32Array","Float64Array","BigInt64Array","BigUint64Array"),isStringObject:_,isNumberObject:w,isBooleanObject:E,isBigIntObject:O,isSymbolObject:L}},63(t,e,n){const{ArrayIsArray:r}=n(714),{hideStackFrames:o,codes:{ERR_INVALID_ARG_TYPE:i}}=n(923),s=o((t,e,n=0)=>{if(0===n){if(null===t||r(t))throw new i(e,"Object",t);if("object"!=typeof t)throw new i(e,"Object",t)}else{if(!(1&n)&&null===t)throw new i(e,"Object",t);if(!(2&n)&&r(t))throw new i(e,"Object",t);const o=typeof t;if(!("object"===o||4&n&&"function"===o))throw new i(e,"Object",t)}});t.exports={kValidateObjectNone:0,kValidateObjectAllowNullable:1,kValidateObjectAllowArray:2,kValidateObjectAllowFunction:4,validateObject:s,validateString:function(t,e){if("string"!=typeof t)throw new i(e,"string",t)}}},811(t,e,n){const{StringPrototypeCharCodeAt:r,StringPrototypeLastIndexOf:o,StringPrototypeSlice:i}=n(714),{CHAR_DOT:s,CHAR_FORWARD_SLASH:l}=n(575),{validateString:c}=n(63);function a(t){return t===l}function u(t,e,n,c){let a="",u=0,f=-1,p=0,y=0;for(let g=0;g<=t.length;++g){if(g<t.length)y=r(t,g);else{if(c(y))break;y=l}if(c(y)){if(f===g-1||1===p);else if(2===p){if(a.length<2||2!==u||r(a,a.length-1)!==s||r(a,a.length-2)!==s){if(a.length>2){const t=o(a,n);-1===t?(a="",u=0):(a=i(a,0,t),u=a.length-1-o(a,n)),f=g,p=0;continue}if(0!==a.length){a="",u=0,f=g,p=0;continue}}e&&(a+=a.length>0?`${n}..`:"..",u=2)}else a.length>0?a+=`${n}${i(t,f+1,g)}`:a=i(t,f+1,g),u=g-f-1;f=g,p=0}else y===s&&-1!==p?++p:p=-1}return a}t.exports={isPosixPathSeparator:a,normalizeString:u,resolve:function(...t){if(0===t.length||1===t.length&&(""===t[0]||"."===t[0])){const t="/";if(r(t,0)===l)return t}let e="",n=!1;for(let o=t.length-1;o>=0&&!n;o--){const i=t[o];c(i,`paths[${o}]`),0!==i.length&&(e=`${i}/${e}`,n=r(i,0)===l)}if(!n){const t="/";e=`${t}/${e}`,n=r(t,0)===l}return e=u(e,!n,"/",a),n?`/${e}`:e.length>0?e:"."}}},714(t){const e={__proto__:null},{defineProperty:n,getOwnPropertyDescriptor:r,ownKeys:o}=Reflect,{apply:i,bind:s,call:l}=Function.prototype,c=s.bind(l);e.uncurryThis=c;const a=s.bind(i);e.applyBind=a;const u=["ArrayOf","ArrayPrototypePush","ArrayPrototypeUnshift","MathHypot","MathMax","MathMin","StringFromCharCode","StringFromCodePoint","StringPrototypeConcat","TypedArrayOf"];function f(t){return"symbol"==typeof t?`Symbol${t.description[7].toUpperCase()}${t.description.slice(8)}`:`${t[0].toUpperCase()}${t.slice(1)}`}function p(t,e,r,{enumerable:o,get:i,set:s}){n(t,`${e}Get${r}`,{__proto__:null,value:c(i),enumerable:o}),void 0!==s&&n(t,`${e}Set${r}`,{__proto__:null,value:c(s),enumerable:o})}function y(t,e,i){for(const s of o(t)){const o=f(s),l=r(t,s);if("get"in l)p(e,i,o,l);else{const r=`${i}${o}`;n(e,r,{__proto__:null,...l}),u.includes(r)&&n(e,`${r}Apply`,{__proto__:null,value:a(l.value,t)})}}}function g(t,e,i){for(const s of o(t)){const o=f(s),l=r(t,s);if("get"in l)p(e,i,o,l);else{const{value:t}=l;"function"==typeof t&&(l.value=c(t));const r=`${i}${o}`;n(e,r,{__proto__:null,...l}),u.includes(r)&&n(e,`${r}Apply`,{__proto__:null,value:a(t)})}}}["Proxy","globalThis"].forEach(t=>{e[t]=globalThis[t]}),[decodeURI,decodeURIComponent,encodeURI,encodeURIComponent].forEach(t=>{e[t.name]=t}),[escape,eval,unescape].forEach(t=>{e[t.name]=t}),["Atomics","JSON","Math","Proxy","Reflect"].forEach(t=>{y(globalThis[t],e,t)}),["AggregateError","Array","ArrayBuffer","BigInt","BigInt64Array","BigUint64Array","Boolean","DataView","Date","Error","EvalError","FinalizationRegistry","Float32Array","Float64Array","Function","Int16Array","Int32Array","Int8Array","Map","Number","Object","RangeError","ReferenceError","RegExp","Set","String","Symbol","SyntaxError","TypeError","URIError","Uint16Array","Uint32Array","Uint8Array","Uint8ClampedArray","WeakMap","WeakRef","WeakSet"].forEach(t=>{const n=globalThis[t];n&&(e[t]=n,y(n,e,t),g(n.prototype,e,`${t}Prototype`))}),["Promise"].forEach(t=>{const i=globalThis[t];e[t]=i,function(t,e,i){for(const s of o(t)){const o=f(s),l=r(t,s);if("get"in l)p(e,i,o,l);else{const{value:r}=l;"function"==typeof r&&(l.value=r.bind(t)),n(e,`${i}${o}`,{__proto__:null,...l})}}}(i,e,t),g(i.prototype,e,`${t}Prototype`)}),[{name:"TypedArray",original:Reflect.getPrototypeOf(Uint8Array)},{name:"ArrayIterator",original:{prototype:Reflect.getPrototypeOf(Array.prototype[Symbol.iterator]())}},{name:"StringIterator",original:{prototype:Reflect.getPrototypeOf(String.prototype[Symbol.iterator]())}}].forEach(({name:t,original:n})=>{e[t]=n,g(n,e,t),g(n.prototype,e,`${t}Prototype`)}),e.IteratorPrototype=Reflect.getPrototypeOf(e.ArrayIteratorPrototype);const{ArrayPrototypeForEach:h,ArrayPrototypePushApply:d,ArrayPrototypeSlice:m,FinalizationRegistry:b,FunctionPrototypeCall:$,Map:S,ObjectFreeze:x,ObjectSetPrototypeOf:P,RegExp:A,Set:v,SymbolIterator:_,WeakMap:w,WeakRef:E,WeakSet:O}=e,L=(t,e)=>{class n{constructor(e){this._iterator=t(e)}next(){return e(this._iterator)}[_](){return this}}return P(n.prototype,null),x(n.prototype),x(n),n};e.SafeArrayIterator=L(e.ArrayPrototypeSymbolIterator,e.ArrayIteratorPrototypeNext),e.SafeStringIterator=L(e.StringPrototypeSymbolIterator,e.StringIteratorPrototypeNext);const R=(t,e)=>{h(o(t),o=>{r(e,o)||n(e,o,{__proto__:null,...r(t,o)})})},k=(t,e)=>{if(_ in t.prototype){const i=new t;let s;h(o(t.prototype),o=>{if(!r(e.prototype,o)){const l=r(t.prototype,o);if("function"==typeof l.value&&0===l.value.length&&_ in($(l.value,i)??{})){const t=c(l.value);s=s||c(t(i).next);const e=L(t,s);l.value=function(){return new e(this)}}n(e.prototype,o,{__proto__:null,...l})}})}else R(t.prototype,e.prototype);return R(t,e),P(e.prototype,null),x(e.prototype),x(e),e};e.makeSafe=k,e.SafeMap=k(S,class extends S{}),e.SafeWeakMap=k(w,class extends w{}),e.SafeSet=k(v,class extends v{}),e.SafeWeakSet=k(O,class extends O{}),e.SafeFinalizationRegistry=k(b,class extends b{}),e.SafeWeakRef=k(E,class extends E{}),e.AsyncIteratorPrototype=e.ReflectGetPrototypeOf(async function*(){}).prototype,e.internalBinding=t=>{if("config"===t)return{hasIntl:!1};throw new Error(`unknown module: "${t}"`)},e._stringPrototypeReplaceAll=(t,e,n)=>"[object regexp]"===Object.prototype.toString.call(e).toLowerCase()?t.replace(e,n):t.replace(new A(e,"g"),n),e.SafeArrayPrototypePushApply=(t,e)=>{let n=65536;if(n<e.length){let r=0;do{d(t,m(e,r,r=n)),n+=65536}while(n<e.length);e=m(e,r)}return d(t,e)},e.StringPrototypeReplaceAll=e.StringPrototypeReplaceAll||e._stringPrototypeReplaceAll,P(e,null),x(e),t.exports=e},326(t,e,n){const r=n(714),{Proxy:o,ProxyRevocable:i,SafeWeakMap:s}=r,l=new s;class c{constructor(t,e){const n=new o(t,e);return l.set(n,[t,e]),n}static getProxyDetails(t,e=!0){const n=l.get(t);if(n)return e?n:n[0]}static revocable(t,e){const n=i(t,e);l.set(n.proxy,[t,e]);const r=n.revoke;return n.revoke=()=>{l.set(n.proxy,[null,null]),r()},n}}t.exports={getProxyDetails:c.getProxyDetails.bind(c),Proxy:c}},851(t){t.exports=URL},596(t,e,n){const r=n(714),{BigInt:o,Error:i,NumberParseInt:s,ObjectEntries:l,ObjectGetOwnPropertyDescriptor:c,ObjectGetOwnPropertyDescriptors:a,ObjectGetOwnPropertySymbols:u,ObjectPrototypeToString:f,Symbol:p}=r,y=n(326),g=p("kPending"),h=p("kRejected");t.exports={constants:{kPending:g,kRejected:h,ALL_PROPERTIES:0,ONLY_ENUMERABLE:2},getOwnNonIndexProperties:function(t,e=2){const n=a(t),r=[];for(const[t,o]of l(n))if(!/^(0|[1-9][0-9]*)$/.test(t)||s(t,10)>=2**32-1){if(2===e&&!o.enumerable)continue;r.push(t)}for(const n of u(t)){const o=c(t,n);(2!==e||o.enumerable)&&r.push(n)}return r},getPromiseDetails:()=>[g,void 0],getProxyDetails:y.getProxyDetails,Proxy:y.Proxy,previewEntries:t=>[[],!1],getConstructorName(t){if(!t||"object"!=typeof t)throw new i("Invalid object");if(t.constructor?.name)return t.constructor.name;const e=f(t).match(/^\[object ([^\]]+)\]/);return e?e[1]:"Object"},getExternalValue:()=>o(0)}}},e={};return function n(r){var o=e[r];if(void 0!==o)return o.exports;var i=e[r]={exports:{}};return t[r](i,i.exports,n),i.exports}(702)})());
48769
49290
 
49291
+ /***/ },
49292
+
49293
+ /***/ "./node_modules/time-commando/index.js"
49294
+ /*!*********************************************!*\
49295
+ !*** ./node_modules/time-commando/index.js ***!
49296
+ \*********************************************/
49297
+ (__unused_webpack_module, exports) {
49298
+
49299
+ "use strict";
49300
+
49301
+
49302
+ /**
49303
+ * Creates a new Date object from the given value.
49304
+ *
49305
+ * @param {any} val - The value to create the Date object from.
49306
+ * @returns {Date} A new Date object.
49307
+ */
49308
+
49309
+ exports.D = function(val) {
49310
+ return new Date(val);
49311
+ };
49312
+
49313
+ /**
49314
+ * Creates a new Date object representing the current date and time.
49315
+ *
49316
+ * @returns {Date} A new Date object representing the current date and time.
49317
+ */
49318
+
49319
+ exports.now = function now() {
49320
+ return new Date();
49321
+ };
49322
+
49323
+ /**
49324
+ * Creates a new Date object representing the next midnight from the given date.
49325
+ * If no date is provided, it defaults to the current date and time.
49326
+ *
49327
+ * @param {Date} [date] - The date from which to calculate the next midnight.
49328
+ * @returns {Date} A new Date object representing the next midnight.
49329
+ */
49330
+
49331
+ exports.nextMidnight = function nextMidnight(date) {
49332
+ date = date ?? exports.now();
49333
+ date.setDate(date.getDate() + 1);
49334
+ date.setHours(0, 0, 0, 0);
49335
+ return date;
49336
+ };
49337
+
49338
+ /**
49339
+ * Converts a Date object to a string in the format 'YYYYMMDD' or 'YYYY-MM-DD'
49340
+ *
49341
+ * @param {Date} d - The Date object to be converted
49342
+ * @param {Boolean} dashes - Set to true to return 'YYYY-MM-DD'
49343
+ * @returns {string} A string representing the desired format
49344
+ */
49345
+
49346
+ exports.toYYYYMMDD = function toYYYYMMDD(d, dashes) {
49347
+ if (dashes) {
49348
+ const year = d.getFullYear();
49349
+ const month = d.getMonth() + 1;
49350
+ const day = d.getDate();
49351
+ return year + '-' + ('' + month).padStart(2, '0') + '-' + ('' + day).padStart(2, '0'); // "2021-11-24"
49352
+ }
49353
+ const year = d.getFullYear() * 1e4;
49354
+ const month = (d.getMonth() + 1) * 100;
49355
+ const day = d.getDate();
49356
+ return year + month + day + ''; // `+ ''` to convert to string from number, 20211124 => "20211124"
49357
+ };
49358
+
49359
+ exports.oneSecondMS = 1000;
49360
+ exports.oneMinuteMS = exports.oneSecondMS * 60;
49361
+ exports.oneHourMS = exports.oneMinuteMS * 60;
49362
+ exports.oneDayMS = exports.oneHourMS * 24;
49363
+ exports.oneWeekMS = exports.oneDayMS * 7;
49364
+
49365
+ /**
49366
+ * Return the number of milliseconds in `num` seconds
49367
+ *
49368
+ * @param {number} num - The number of seconds to convert to milliseconds.
49369
+ * @returns {number} The equivalent number of milliseconds.
49370
+ */
49371
+
49372
+ exports.seconds = function seconds(num) {
49373
+ if (typeof num !== 'number') {
49374
+ throw new TypeError('Parameter must be a number, got ' + typeof num);
49375
+ }
49376
+ return num * time.oneSecondMS;
49377
+ };
49378
+
49379
+ /**
49380
+ * Return the number of milliseconds in `num` minutes
49381
+ *
49382
+ * @param {number} num - The number of minutes to convert to milliseconds.
49383
+ * @returns {number} The equivalent number of milliseconds.
49384
+ */
49385
+
49386
+ exports.minutes = function minutes(num) {
49387
+ if (typeof num !== 'number') {
49388
+ throw new TypeError('Parameter must be a number, got ' + typeof num);
49389
+ }
49390
+ return num * time.oneMinuteMS;
49391
+ };
49392
+
49393
+ /**
49394
+ * Return the number of milliseconds in `num` hours
49395
+ *
49396
+ * @param {number} num - The number of hours to convert to milliseconds.
49397
+ * @returns {number} The equivalent number of milliseconds.
49398
+ */
49399
+
49400
+ exports.hours = function hours(num) {
49401
+ if (typeof num !== 'number') {
49402
+ throw new TypeError('Parameter must be a number, got ' + typeof num);
49403
+ }
49404
+ return num * time.oneHourMS;
49405
+ };
49406
+
49407
+ /**
49408
+ * Return the number of milliseconds in `num` days
49409
+ *
49410
+ * @param {number} num - The number of days to convert to milliseconds.
49411
+ * @returns {number} The equivalent number of milliseconds.
49412
+ */
49413
+
49414
+ exports.days = function days(num) {
49415
+ if (typeof num !== 'number') {
49416
+ throw new TypeError('Parameter must be a number, got ' + typeof num);
49417
+ }
49418
+ return num * time.oneDayMS;
49419
+ };
49420
+
49421
+ /**
49422
+ * Return the number of milliseconds in `num` weeks
49423
+ *
49424
+ * @param {number} num - The number of weeks to convert to milliseconds.
49425
+ * @returns {number} The equivalent number of milliseconds.
49426
+ */
49427
+
49428
+ exports.weeks = function weeks(num) {
49429
+ if (typeof num !== 'number') {
49430
+ throw new TypeError('Parameter must be a number, got ' + typeof num);
49431
+ }
49432
+ return num * time.oneWeekMS;
49433
+ };
49434
+
49435
+
48770
49436
  /***/ },
48771
49437
 
48772
49438
  /***/ "./node_modules/vue/dist/vue.runtime.esm-bundler.js"
@@ -48953,7 +49619,7 @@ __webpack_require__.r(__webpack_exports__);
48953
49619
  /* harmony import */ var _vue_runtime_dom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/runtime-dom */ "./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js");
48954
49620
  /* harmony import */ var _vue_runtime_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/runtime-dom */ "./node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js");
48955
49621
  /**
48956
- * vue v3.5.31
49622
+ * vue v3.5.32
48957
49623
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
48958
49624
  * @license MIT
48959
49625
  **/
@@ -50118,7 +50784,7 @@ module.exports = "<div class=\"relative flex items-start\" :class=\"{'justify-en
50118
50784
  (module) {
50119
50785
 
50120
50786
  "use strict";
50121
- module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px); height: calc(100dvh - 55px)\">\n <button\n type=\"button\"\n class=\"fixed top-[65px] left-0 cursor-pointer bg-muted rounded-r-md p-1\"\n :class=\"hideSidebar === true ? 'z-[10001]' : hideSidebar === false ? 'z-10' : 'z-30 lg:hidden'\"\n @click=\"hideSidebar = hideSidebar === false ? true : false\"\n aria-label=\"Toggle chat history\"\n title=\"Toggle chat history\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5 text-content-tertiary\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <button\n class=\"fixed top-[65px] right-4 z-10 p-2 rounded-md shadow bg-surface\"\n :class=\"hasWorkspace ? 'text-content-secondary hover:bg-muted' : 'text-gray-300 cursor-not-allowed bg-page'\"\n @click=\"toggleShareThread\"\n :disabled=\"!hasWorkspace || !chatThreadId || sharingThread\"\n aria-label=\"Share thread with workspace\"\n title=\"Share thread with workspace\"\n >\n <svg v-if=\"hasWorkspace\" xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7a2.48 2.48 0 0 0 0-1.39l7.02-4.11a2.5 2.5 0 1 0-.87-1.37L8.04 9.94a2.5 2.5 0 1 0 0 4.12l7.12 4.16a2.5 2.5 0 1 0 .84-1.34l-7.05-4.12c-.04-.02-.08-.05-.11-.07a2.48 2.48 0 0 0 0-1.39c.03-.02.07-.04.11-.07l7.11-4.16c.52.47 1.2.76 1.94.76a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0-1.94.94L7.97 8.43a2.5 2.5 0 1 0 0 7.14l9.09 5.3c.52-.47 1.2-.76 1.94-.76a2.5 2.5 0 1 0 0-5z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M12 1a5 5 0 00-5 5v3H6a2 2 0 00-2 2v9a2 2 0 002 2h12a2 2 0 002-2v-9a2 2 0 00-2-2h-1V6a5 5 0 00-5-5zm-3 8V6a3 3 0 016 0v3H9zm9 2v9H6v-9h12z\"/></svg>\n </button>\n <!-- Sidebar: Chat Threads -->\n <aside\n class=\"bg-page border-r overflow-hidden h-full transition-all duration-300 ease-in-out z-20 w-64 fixed lg:relative shrink-0 flex flex-col\"\n :class=\"hideSidebar === false ? 'translate-x-0' : hideSidebar === true ? '-translate-x-full lg:translate-x-0 lg:!w-0 lg:!border-r-0' : '-translate-x-full lg:translate-x-0'\"\n style=\"z-index: 1000\">\n <!-- Search + New Thread -->\n <div class=\"p-3 shrink-0\">\n <div class=\"relative flex items-center gap-2\">\n <div class=\"relative flex-1\">\n <svg class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n <input\n v-model=\"threadSearch\"\n type=\"text\"\n placeholder=\"Search threads...\"\n @keydown.esc=\"threadSearch = ''\"\n class=\"w-full rounded-md border border-edge bg-surface py-1.5 pl-8 pr-3 text-sm text-content placeholder:text-gray-400 focus:border-edge-strong focus:outline-none focus:ring-1 focus:ring-gray-300\"\n />\n </div>\n <async-button\n @click=\"createNewThread\"\n class=\"shrink-0 rounded-md border border-edge bg-surface p-1.5 text-content-tertiary hover:bg-muted hover:text-content-secondary\"\n title=\"New thread\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" />\n </svg>\n </async-button>\n </div>\n </div>\n <!-- Thread list (scrollable) -->\n <nav class=\"flex-1 overflow-y-auto px-2 pb-2\">\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">Threads</div>\n <div v-if=\"status === 'loaded' && filteredThreads.length === 0\" class=\"px-2 py-2 text-sm text-content-tertiary\">\n <template v-if=\"threadSearch.trim()\">No threads match \"{{threadSearch}}\"</template>\n <template v-else>No threads yet</template>\n </div>\n <ul role=\"list\">\n <li\n v-for=\"thread in filteredThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"rounded-md py-2 px-2 cursor-pointer mb-0.5\"\n :class=\"thread._id === chatThreadId ? 'bg-gray-200 text-content' : 'hover:bg-muted text-content-secondary'\"\n >\n <div class=\"text-sm font-medium truncate\">{{ thread.title || 'Untitled Thread' }}</div>\n <div class=\"text-xs text-gray-400 mt-0.5\">{{ formatThreadDate(thread.updatedAt || thread.createdAt) }}</div>\n </li>\n </ul>\n </nav>\n <!-- Bottom toolbar -->\n <div class=\"shrink-0 border-t border-edge bg-page px-2 py-1.5 flex items-center gap-1\">\n <button\n type=\"button\"\n @click=\"hideSidebar = true\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Hide sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\" />\n </svg>\n </button>\n </div>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col bg-slate-50\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <div v-if=\"chatMessages?.length === 0\">\n <div class=\"flex items-center w-full h-full justify-center py-3 mb-4\">\n <p class=\"mx-4 font-bold text-content\">\n Ask Mongoose Studio to analyze your data or generate a script\n </p>\n </div>\n </div>\n <ul role=\"list\" class=\"space-y-4\" v-else>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\" :target-dashboard-id=\"currentThread?.dashboardId\"></chat-message>\n </li>\n </ul>\n </div>\n\n\n <!-- Input Area -->\n <div class=\"border-t p-4\">\n <form @submit.prevent=\"sendMessage\" :disabled=\"sendingMessage\" class=\"flex gap-2 items-end justify-end\">\n <textarea\n v-model=\"newMessage\"\n :placeholder=\"sendingMessage ? 'Sending...' : 'Ask about your data, generate a query, or build a chart…'\"\n class=\"flex-1 border rounded px-4 py-2 resize-none overflow-y-auto shadow-sm\"\n :disabled=\"sendingMessage\"\n rows=\"2\"\n ref=\"messageInput\"\n @input=\"adjustTextareaHeight\"\n @keydown.enter.exact.prevent=\"handleEnter\"\n ></textarea>\n <button class=\"bg-blue-600 text-white px-4 h-[42px] rounded disabled:bg-gray-600\" :disabled=\"sendingMessage\">\n <svg v-if=\"sendingMessage\" style=\"height: 1em\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <g>\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" opacity=\"0.3\" />\n <path d=\"M12 2a10 10 0 0 1 10 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\" />\n </path>\n </g>\n </svg>\n <span v-else>Send</span>\n </button>\n </form>\n </div>\n </main>\n</div>\n";
50787
+ module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px); height: calc(100dvh - 55px)\">\n <button\n type=\"button\"\n class=\"fixed top-[65px] left-0 cursor-pointer bg-muted rounded-r-md p-1\"\n :class=\"hideSidebar === true ? 'z-[10001]' : hideSidebar === false ? 'z-10' : 'z-30 lg:hidden'\"\n @click=\"hideSidebar = hideSidebar === false ? true : false\"\n aria-label=\"Toggle chat history\"\n title=\"Toggle chat history\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5 text-content-tertiary\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <!-- Sidebar: Chat Threads -->\n <aside\n class=\"bg-page border-r overflow-hidden h-full transition-all duration-300 ease-in-out z-20 w-64 fixed lg:relative shrink-0 flex flex-col\"\n :class=\"hideSidebar === false ? 'translate-x-0' : hideSidebar === true ? '-translate-x-full lg:translate-x-0 lg:!w-0 lg:!border-r-0' : '-translate-x-full lg:translate-x-0'\"\n style=\"z-index: 1000\">\n <!-- Search + New Thread -->\n <div class=\"p-3 shrink-0\">\n <div class=\"relative flex items-center gap-2\">\n <div class=\"relative flex-1\">\n <svg class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n <input\n v-model=\"threadSearch\"\n type=\"text\"\n placeholder=\"Search threads...\"\n @keydown.esc=\"threadSearch = ''\"\n class=\"w-full rounded-md border border-edge bg-surface py-1.5 pl-8 pr-3 text-sm text-content placeholder:text-gray-400 focus:border-edge-strong focus:outline-none focus:ring-1 focus:ring-gray-300\"\n />\n </div>\n <async-button\n @click=\"createNewThread\"\n class=\"shrink-0 rounded-md border border-edge bg-surface p-1.5 text-content-tertiary hover:bg-muted hover:text-content-secondary\"\n title=\"New thread\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" />\n </svg>\n </async-button>\n </div>\n </div>\n <!-- Thread list (scrollable) -->\n <nav class=\"flex-1 overflow-y-auto px-2 pb-2\">\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">Threads</div>\n <div v-if=\"status === 'loaded' && filteredThreads.length === 0\" class=\"px-2 py-2 text-sm text-content-tertiary\">\n <template v-if=\"threadSearch.trim()\">No threads match \"{{threadSearch}}\"</template>\n <template v-else>No threads yet</template>\n </div>\n <ul role=\"list\">\n <li\n v-for=\"thread in filteredThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"rounded-md py-2 px-2 cursor-pointer mb-0.5\"\n :class=\"thread._id === chatThreadId ? 'bg-gray-200 text-content' : 'hover:bg-muted text-content-secondary'\"\n >\n <div class=\"text-sm font-medium truncate\">{{ thread.title || 'Untitled Thread' }}</div>\n <div class=\"text-xs text-gray-400 mt-0.5\">{{ formatThreadDate(thread.updatedAt || thread.createdAt) }}</div>\n </li>\n </ul>\n </nav>\n <!-- Bottom toolbar -->\n <div class=\"shrink-0 border-t border-edge bg-page px-2 py-1.5 flex items-center gap-1\">\n <button\n type=\"button\"\n @click=\"hideSidebar = true\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Hide sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\" />\n </svg>\n </button>\n <button\n type=\"button\"\n @click=\"hasWorkspace ? toggleShareThread() : (showProUpgradeModal = true)\"\n class=\"rounded p-1.5\"\n :class=\"hasWorkspace && chatThreadId ? 'text-gray-400 hover:text-gray-600 hover:bg-muted' : !hasWorkspace ? 'text-gray-400 hover:text-gray-600 hover:bg-muted' : 'text-gray-300 cursor-not-allowed'\"\n :disabled=\"hasWorkspace && !chatThreadId\"\n aria-label=\"Share thread with workspace\"\n :title=\"'Share thread with workspace' + (!hasWorkspace ? ' (requires a pro workspace)' : !chatThreadId ? ': Open a thread first!' : '')\"\n >\n <svg v-if=\"hasWorkspace\" xmlns=\"http://www.w3.org/2000/svg\" class=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7a2.48 2.48 0 0 0 0-1.39l7.02-4.11a2.5 2.5 0 1 0-.87-1.37L8.04 9.94a2.5 2.5 0 1 0 0 4.12l7.12 4.16a2.5 2.5 0 1 0 .84-1.34l-7.05-4.12c-.04-.02-.08-.05-.11-.07a2.48 2.48 0 0 0 0-1.39c.03-.02.07-.04.11-.07l7.11-4.16c.52.47 1.2.76 1.94.76a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0-1.94.94L7.97 8.43a2.5 2.5 0 1 0 0 7.14l9.09 5.3c.52-.47 1.2-.76 1.94-.76a2.5 2.5 0 1 0 0-5z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M12 1a5 5 0 00-5 5v3H6a2 2 0 00-2 2v9a2 2 0 002 2h12a2 2 0 002-2v-9a2 2 0 00-2-2h-1V6a5 5 0 00-5-5zm-3 8V6a3 3 0 016 0v3H9zm9 2v9H6v-9h12z\"/></svg>\n </button>\n </div>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col bg-slate-50\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <div v-if=\"chatMessages?.length === 0\">\n <div class=\"flex items-center w-full h-full justify-center py-3 mb-4\">\n <p class=\"mx-4 font-bold text-content\">\n Ask Mongoose Studio to analyze your data or generate a script\n </p>\n </div>\n </div>\n <ul role=\"list\" class=\"space-y-4\" v-else>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\" :target-dashboard-id=\"currentThread?.dashboardId\"></chat-message>\n </li>\n </ul>\n </div>\n\n\n <!-- Input Area -->\n <div class=\"border-t p-4\">\n <form @submit.prevent=\"sendMessage\" :disabled=\"sendingMessage\" class=\"flex gap-2 items-end justify-end\">\n <textarea\n v-model=\"newMessage\"\n :placeholder=\"sendingMessage ? 'Sending...' : 'Ask about your data, generate a query, or build a chart…'\"\n class=\"flex-1 border rounded px-4 py-2 resize-none overflow-y-auto shadow-sm\"\n :disabled=\"sendingMessage\"\n rows=\"2\"\n ref=\"messageInput\"\n @input=\"adjustTextareaHeight\"\n @keydown.enter.exact.prevent=\"handleEnter\"\n ></textarea>\n <button class=\"bg-primary hover:bg-primary-hover text-white px-4 h-[42px] rounded disabled:bg-gray-600\" :disabled=\"sendingMessage\">\n <svg v-if=\"sendingMessage\" style=\"height: 1em\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <g>\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" opacity=\"0.3\" />\n <path d=\"M12 2a10 10 0 0 1 10 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\" />\n </path>\n </g>\n </svg>\n <span v-else>Send</span>\n </button>\n </form>\n </div>\n </main>\n\n <pro-upgrade-modal\n :show=\"showProUpgradeModal\"\n feature-description=\"Sharing threads lets you collaborate with your team by sharing chat threads within your workspace.\"\n @close=\"showProUpgradeModal = false\"\n ></pro-upgrade-modal>\n</div>\n";
50122
50788
 
50123
50789
  /***/ },
50124
50790
 
@@ -50239,7 +50905,7 @@ module.exports = "<div class=\"py-2\">\n <div v-if=\"header\" class=\"border-b
50239
50905
  (module) {
50240
50906
 
50241
50907
  "use strict";
50242
- module.exports = "<div class=\"py-2\">\n <div v-if=\"header\" class=\"border-b border-gray-100 px-2 pb-2 text-xl font-bold\">\n {{header}}\n </div>\n <div class=\"text-xl p-2\">\n {{displayValue}}\n </div>\n</div>";
50908
+ module.exports = "<div class=\"py-2\">\n <div v-if=\"header\" class=\"border-b border-gray-100 px-2 pb-2 text-xl font-bold\">\n {{header}}\n </div>\n <div class=\"text-xl p-2\" :class=\"displayClass\">\n {{displayValue}}\n </div>\n</div>\n";
50243
50909
 
50244
50910
  /***/ },
50245
50911
 
@@ -50250,7 +50916,7 @@ module.exports = "<div class=\"py-2\">\n <div v-if=\"header\" class=\"border-b
50250
50916
  (module) {
50251
50917
 
50252
50918
  "use strict";
50253
- module.exports = "<div>\n <div v-if=\"Array.isArray(result)\">\n <div v-for=\"el in result\" :key=\"el._id || el.finishedEvaluatingAt\">\n <component\n class=\"bg-surface shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl\"\n :is=\"getComponentForValue(el)\"\n :value=\"el\">\n </component>\n </div>\n </div>\n <div v-else>\n <component\n class=\"bg-surface shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl\"\n :is=\"getComponentForValue(result)\"\n :value=\"result\"\n :fullscreen=\"fullscreen\"\n @fullscreen=\"$emit('fullscreen')\">\n </component>\n </div>\n <div class=\"text-right text-sm text-content-secondary mt-1\" v-if=\"finishedEvaluatingAt && !fullscreen\">\n Last Evaluated: {{ format.isoToLongDateTime(finishedEvaluatingAt) }}\n </div>\n</div>\n";
50919
+ module.exports = "<div>\n <div v-if=\"Array.isArray(result)\">\n <div v-for=\"(el, index) in result\">\n <component\n class=\"bg-surface shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl\"\n :is=\"getComponentForValue(el)\"\n :value=\"el\">\n </component>\n </div>\n </div>\n <div v-else>\n <component\n class=\"bg-surface shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl\"\n :is=\"getComponentForValue(result)\"\n :value=\"result\"\n :fullscreen=\"fullscreen\"\n @fullscreen=\"$emit('fullscreen')\">\n </component>\n </div>\n <div class=\"text-right text-sm text-content-secondary mt-1\" v-if=\"finishedEvaluatingAt && !fullscreen\">\n Last Evaluated: {{ format.isoToLongDateTime(finishedEvaluatingAt) }}\n </div>\n</div>\n";
50254
50920
 
50255
50921
  /***/ },
50256
50922
 
@@ -50261,7 +50927,7 @@ module.exports = "<div>\n <div v-if=\"Array.isArray(result)\">\n <div v-for=
50261
50927
  (module) {
50262
50928
 
50263
50929
  "use strict";
50264
- module.exports = "<div class=\"overflow-x-auto\">\n <table class=\"min-w-full border-separate border-spacing-0\">\n <thead v-if=\"hasColumns\" class=\"bg-slate-50\">\n <tr>\n <th\n v-for=\"(column, index) in columns\"\n :key=\"'column-' + index\"\n class=\"bg-slate-50 p-3 text-left text-sm font-semibold text-content border-b border-edge\"\n >\n {{ column }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, rowIndex) in rows\" :key=\"'row-' + rowIndex\" class=\"bg-surface hover:bg-slate-50\">\n <td\n v-for=\"(cell, columnIndex) in row\"\n :key=\"'cell-' + rowIndex + '-' + columnIndex\"\n class=\"p-3 text-sm text-content border-b border-edge\"\n >\n {{ displayValue(cell) }}\n </td>\n </tr>\n <tr v-if=\"!hasRows\">\n <td\n :colspan=\"Math.max(columns.length, 1)\"\n class=\"p-3 text-sm text-content-tertiary border-b border-edge\"\n >\n No rows\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n";
50930
+ module.exports = "<div class=\"overflow-x-auto\">\n <table class=\"min-w-full border-separate border-spacing-0\">\n <thead v-if=\"hasColumns\" class=\"bg-slate-50\">\n <tr>\n <th\n v-for=\"(column, index) in columns\"\n :key=\"'column-' + index\"\n class=\"bg-slate-50 p-3 text-left text-sm font-semibold text-content border-b border-edge\"\n >\n <div v-if=\"index === columns.length - 1\" class=\"relative flex items-center gap-2 w-full\" ref=\"dropdown\">\n <span class=\"min-w-0 flex-1\">{{ column }}</span>\n <button\n @click.stop=\"toggleDropdown\"\n class=\"ml-auto rounded p-1 text-content-secondary hover:bg-muted hover:text-content\"\n aria-label=\"Table actions\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 6a2 2 0 110-4 2 2 0 010 4zm0 6a2 2 0 110-4 2 2 0 010 4zm0 6a2 2 0 110-4 2 2 0 010 4z\" />\n </svg>\n </button>\n <div\n v-if=\"showDropdown\"\n class=\"absolute right-0 top-full z-10 mt-2 w-56 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5\">\n <button\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"downloadCsv(); showDropdown = false\">\n Download as CSV\n </button>\n </div>\n </div>\n <template v-else>{{ column }}</template>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, rowIndex) in rows\" :key=\"'row-' + rowIndex\" class=\"bg-surface hover:bg-slate-50\">\n <td\n v-for=\"(cell, columnIndex) in row\"\n :key=\"'cell-' + rowIndex + '-' + columnIndex\"\n class=\"p-3 text-sm text-content border-b border-edge\"\n >\n {{ displayValue(cell) }}\n </td>\n </tr>\n <tr v-if=\"!hasRows\">\n <td\n :colspan=\"Math.max(columns.length, 1)\"\n class=\"p-3 text-sm text-content-tertiary border-b border-edge\"\n >\n No rows\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n";
50265
50931
 
50266
50932
  /***/ },
50267
50933
 
@@ -50320,6 +50986,17 @@ module.exports = "<div class=\"w-full\">\n <div v-if=\"!arrayValue || arrayValu
50320
50986
 
50321
50987
  /***/ },
50322
50988
 
50989
+ /***/ "./frontend/src/detail-date/detail-date.html"
50990
+ /*!***************************************************!*\
50991
+ !*** ./frontend/src/detail-date/detail-date.html ***!
50992
+ \***************************************************/
50993
+ (module) {
50994
+
50995
+ "use strict";
50996
+ module.exports = "<pre class=\"w-full whitespace-pre-wrap break-words font-mono text-sm text-content-secondary m-0\">{{displayValue}}</pre>\n";
50997
+
50998
+ /***/ },
50999
+
50323
51000
  /***/ "./frontend/src/detail-default/detail-default.html"
50324
51001
  /*!*********************************************************!*\
50325
51002
  !*** ./frontend/src/detail-default/detail-default.html ***!
@@ -50331,6 +51008,17 @@ module.exports = "<div class=\"w-full\">\n <pre v-if=\"!isGeoJsonGeometry || !m
50331
51008
 
50332
51009
  /***/ },
50333
51010
 
51011
+ /***/ "./frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.html"
51012
+ /*!****************************************************************************************!*\
51013
+ !*** ./frontend/src/document-details/date-view-mode-picker/date-view-mode-picker.html ***!
51014
+ \****************************************************************************************/
51015
+ (module) {
51016
+
51017
+ "use strict";
51018
+ module.exports = "<div class=\"flex items-center gap-2\" @click.stop>\n <select\n :value=\"format\"\n @input=\"onFormatChange($event.target.value)\"\n class=\"text-xs border border-edge rounded-md bg-surface px-2 py-1\"\n >\n <option value=\"utc_iso\">UTC (ISO)</option>\n <option value=\"local_browser\">Local (Browser)</option>\n <option value=\"unix_ms\">Unix (ms)</option>\n <option value=\"unix_seconds\">Unix (seconds)</option>\n <option value=\"duration_relative\">Duration relative to now</option>\n <option value=\"custom_tz\">Custom TZ...</option>\n </select>\n <input\n v-if=\"format === 'custom_tz'\"\n :value=\"timezone\"\n @input=\"onTimezoneChange($event.target.value.trim())\"\n :list=\"timezoneDatalistId\"\n type=\"text\"\n placeholder=\"America/New_York\"\n class=\"text-xs border border-edge rounded-md bg-surface px-2 py-1 w-40\"\n >\n <datalist v-if=\"format === 'custom_tz'\" :id=\"timezoneDatalistId\">\n <option v-for=\"tz in timezones\" :key=\"tz\" :value=\"tz\"></option>\n </datalist>\n</div>\n";
51019
+
51020
+ /***/ },
51021
+
50334
51022
  /***/ "./frontend/src/document-details/document-details.css"
50335
51023
  /*!************************************************************!*\
50336
51024
  !*** ./frontend/src/document-details/document-details.css ***!
@@ -50371,7 +51059,7 @@ module.exports = ".document-details {\n width: 100%;\n }\n \n .document-de
50371
51059
  (module) {
50372
51060
 
50373
51061
  "use strict";
50374
- module.exports = "<div class=\"border border-edge bg-surface rounded-lg mb-2\" style=\"overflow: visible;\">\n <!-- Collapsible Header -->\n <div\n @click=\"toggleCollapse\"\n class=\"p-1 cursor-pointer flex items-center justify-between border-b border-edge transition-colors duration-200 ease-in-out\"\n :class=\"{ 'bg-amber-100 hover:bg-amber-200': highlight, 'bg-slate-100 hover:bg-muted': !highlight }\"\n style=\"overflow: visible; position: relative;\"\n >\n <div class=\"flex items-center\" >\n <svg\n :class=\"isCollapsed ? 'rotate-0' : 'rotate-90'\"\n class=\"w-4 h-4 text-content-tertiary mr-2 transition-transform duration-200\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\"></path>\n </svg>\n <span class=\"font-medium text-content\">{{path.path}}</span>\n <span class=\"ml-2 text-sm text-content-tertiary\">({{(path.instance || 'unknown').toLowerCase()}})</span>\n <div v-if=\"isGeoJsonGeometry\" class=\"ml-3 inline-flex items-center gap-2\">\n <div class=\"inline-flex items-center rounded-full bg-gray-200 p-0.5 text-xs font-semibold\">\n <button\n type=\"button\"\n class=\"rounded-full px-2.5 py-0.5 transition\"\n :class=\"detailViewMode === 'text' ? 'bg-blue-600 text-white shadow' : 'text-content-secondary hover:text-content'\"\n :style=\"detailViewMode === 'text' ? 'color: white !important; background-color: #2563eb !important;' : ''\"\n @click.stop=\"setDetailViewMode('text')\">\n Text\n </button>\n <button\n type=\"button\"\n class=\"rounded-full px-2.5 py-0.5 transition\"\n :class=\"detailViewMode === 'map' ? 'bg-blue-600 text-white shadow' : 'text-content-secondary hover:text-content'\"\n :style=\"detailViewMode === 'map' ? 'color: white !important; background-color: #2563eb !important;' : ''\"\n @click.stop=\"setDetailViewMode('map')\">\n Map\n </button>\n </div>\n <!-- Info icon with tooltip -->\n <div v-if=\"editting\" class=\"relative inline-block\" style=\"z-index: 10002;\" @mouseenter=\"showTooltip = true\" @mouseleave=\"showTooltip = false\" @click.stop>\n <svg\n ref=\"infoIcon\"\n class=\"w-6 h-6 text-gray-400 hover:text-gray-600 cursor-help\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"></path>\n </svg>\n <div\n v-show=\"showTooltip\"\n ref=\"tooltip\"\n class=\"absolute left-full top-0 ml-2 w-64 p-3 text-white text-xs rounded-lg shadow-xl\"\n style=\"z-index: 99999; pointer-events: none; white-space: normal; position: fixed; background-color: #111827;\"\n :style=\"getTooltipStyle()\"\n >\n <div class=\"font-semibold mb-2\">Map Controls:</div>\n <div v-if=\"isGeoJsonPoint\" class=\"space-y-1\">\n <div>• Drag pin to move location</div>\n </div>\n <div v-else-if=\"isGeoJsonPolygon\" class=\"space-y-1\">\n <div>• Drag vertices to reshape polygon</div>\n <div v-if=\"isMultiPolygon\">• Right-click edge to add new vertex</div>\n <div>• Right-click vertex to delete</div>\n </div>\n <div class=\"absolute top-2 -left-1 w-0 h-0 border-t-4 border-b-4 border-r-4 border-transparent border-r-gray-900\"></div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"flex items-center gap-1 text-sm text-gray-600 hover:text-gray-800 px-2 py-1 rounded-md border border-transparent hover:border-edge-strong bg-surface\"\n @click.stop.prevent=\"copyPropertyValue\"\n title=\"Copy value\"\n aria-label=\"Copy property value\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 7h8m-8 4h8m-8 4h5m-7-9a2 2 0 012-2h7a2 2 0 012 2v10a2 2 0 01-2 2H8l-4-4V7a2 2 0 012-2z\" />\n </svg>\n {{copyButtonLabel}}\n </button>\n <router-link\n v-if=\"path.ref && getValueForPath(path.path)\"\n :to=\"`/model/${path.ref}/document/${getValueForPath(path.path)}`\"\n class=\"bg-primary hover:bg-primary-hover text-primary-text px-2 py-1 text-sm rounded-md\"\n @click.stop\n >View Document\n </router-link>\n </div>\n </div>\n\n <!-- Collapsible Content -->\n <div v-if=\"!isCollapsed\" class=\"p-2\">\n <!-- Date Type Selector (when editing dates) -->\n <div v-if=\"editting && path.instance === 'Date'\" class=\"mb-3 flex gap-1.5\">\n <div\n @click=\"dateType = 'picker'\"\n :class=\"dateType === 'picker' ? 'bg-teal-600' : ''\"\n class=\"self-stretch px-2 py-1 rounded-sm justify-center items-center gap-1.5 flex cursor-pointer\">\n <div\n :class=\"dateType === 'picker' ? 'text-white' : ''\"\n class=\"text-xs font-medium font-['Lato'] capitalize leading-tight\">\n Date Picker\n </div>\n </div>\n <div\n @click=\"dateType = 'iso'\"\n :class=\"dateType === 'iso' ? 'bg-teal-600' : ''\"\n class=\"self-stretch px-2 py-1 rounded-sm justify-center items-center gap-1.5 flex cursor-pointer\">\n <div\n :class=\"dateType === 'iso' ? 'text-white' : ''\"\n class=\"text-xs font-medium font-['Lato'] capitalize leading-tight\">\n ISO String\n </div>\n </div>\n </div>\n\n <!-- Field Content -->\n <div v-if=\"editting && path.path !== '_id'\">\n <!-- Use detail-default with map editing for GeoJSON geometries -->\n <component\n v-if=\"isGeoJsonGeometry\"\n :is=\"getComponentForPath(path)\"\n :value=\"getEditValueForPath(path)\"\n :view-mode=\"detailViewMode\"\n :on-change=\"handleInputChange\"\n >\n </component>\n <!-- Use standard edit components for other types -->\n <component\n v-else\n :is=\"getEditComponentForPath(path)\"\n :value=\"getEditValueForPath(path)\"\n :format=\"dateType\"\n v-bind=\"getEditComponentProps(path)\"\n @input=\"handleInputChange($event)\"\n @error=\"invalid[path.path] = $event;\"\n >\n </component>\n </div>\n <div v-else>\n <!-- Show truncated or full value based on needsTruncation and isValueExpanded -->\n <!-- Special handling for truncated arrays -->\n <div v-if=\"isArray && shouldShowTruncated\" class=\"w-full\">\n <div class=\"mt-2\">\n <div\n v-for=\"(item, index) in truncatedArrayItems\"\n :key=\"index\"\n class=\"mb-1.5 py-2.5 px-3 pl-4 bg-transparent border-l-[3px] border-l-blue-500 rounded-none transition-all duration-200 cursor-pointer relative hover:bg-slate-50 hover:border-l-blue-600\">\n <div class=\"absolute -left-2 top-1/2 -translate-y-1/2 w-5 h-5 bg-blue-500 text-white rounded-full flex items-center justify-center text-[10px] font-semibold font-mono z-10 hover:bg-blue-600\">{{ index }}</div>\n <div v-if=\"arrayUtils.isObjectItem(item)\" class=\"flex flex-col gap-1 mt-1 px-2\">\n <div\n v-for=\"key in arrayUtils.getItemKeys(item)\"\n :key=\"key\"\n class=\"flex items-start gap-2 text-xs font-mono\">\n <span class=\"font-semibold text-gray-600 flex-shrink-0 min-w-[80px]\">{{ key }}:</span>\n <span class=\"text-gray-800 break-words whitespace-pre-wrap flex-1\">{{ arrayUtils.formatItemValue(item, key) }}</span>\n </div>\n </div>\n <div v-else class=\"text-xs py-1.5 px-2 font-mono text-gray-800 break-words whitespace-pre-wrap mt-1\">{{ arrayUtils.formatValue(item) }}</div>\n </div>\n <div class=\"mb-1.5 py-2.5 px-3 pl-4 bg-transparent border-none border-l-[3px] border-l-blue-500 rounded-none transition-all duration-200 cursor-pointer relative opacity-70 hover:opacity-100\">\n <div class=\"text-xs py-1.5 px-2 font-mono text-content-tertiary italic break-words whitespace-pre-wrap mt-1\">\n ... and {{ remainingArrayCount }} more item{{ remainingArrayCount !== 1 ? 's' : '' }}\n </div>\n </div>\n </div>\n <button\n @click=\"toggleValueExpansion\"\n class=\"mt-2 text-blue-600 hover:text-blue-800 text-sm font-medium flex items-center gap-1 transform transition-all duration-200 ease-in-out hover:translate-x-0.5\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"></path>\n </svg>\n Show all {{ arrayValue.length }} items\n </button>\n </div>\n <!-- Non-array truncated view -->\n <div v-else-if=\"shouldShowTruncated && !isArray\" class=\"relative\">\n <div class=\"text-content-secondary whitespace-pre-wrap break-words font-mono text-sm\">{{truncatedString}}</div>\n <button\n @click=\"toggleValueExpansion\"\n class=\"mt-2 text-blue-600 hover:text-blue-800 text-sm font-medium flex items-center gap-1 transform transition-all duration-200 ease-in-out hover:translate-x-0.5\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"></path>\n </svg>\n Show more ({{valueAsString.length}} characters)\n </button>\n </div>\n <!-- Expanded view -->\n <div v-else-if=\"needsTruncation && isValueExpanded\" class=\"relative\">\n <component\n :is=\"getComponentForPath(path)\"\n :value=\"getValueForPath(path.path)\"\n :view-mode=\"detailViewMode\"></component>\n <button\n @click=\"toggleValueExpansion\"\n class=\"mt-2 text-blue-600 hover:text-blue-800 text-sm font-medium flex items-center gap-1 transform transition-all duration-200 ease-in-out hover:translate-x-0.5\"\n >\n <svg class=\"w-4 h-4 rotate-180\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"></path>\n </svg>\n Show less\n </button>\n </div>\n <!-- Full view (no truncation needed) -->\n <div v-else>\n <component\n :is=\"getComponentForPath(path)\"\n :value=\"getValueForPath(path.path)\"\n :view-mode=\"detailViewMode\"></component>\n </div>\n </div>\n </div>\n</div>\n";
51062
+ module.exports = "<div class=\"border border-edge bg-surface rounded-lg mb-2\" style=\"overflow: visible;\">\n <!-- Collapsible Header -->\n <div\n @click=\"toggleCollapse\"\n class=\"p-1 cursor-pointer flex items-center justify-between border-b border-edge transition-colors duration-200 ease-in-out\"\n :class=\"{ 'bg-amber-100 hover:bg-amber-200': highlight, 'bg-slate-100 hover:bg-muted': !highlight }\"\n style=\"overflow: visible; position: relative;\"\n >\n <div class=\"flex items-center\" >\n <svg\n :class=\"isCollapsed ? 'rotate-0' : 'rotate-90'\"\n class=\"w-4 h-4 text-content-tertiary mr-2 transition-transform duration-200\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\"></path>\n </svg>\n <span class=\"font-medium text-content\">{{path.path}}</span>\n <span class=\"ml-2 text-sm text-content-tertiary\">({{(path.instance || 'unknown').toLowerCase()}})</span>\n <div v-if=\"isGeoJsonGeometry\" class=\"ml-3 inline-flex items-center gap-2\">\n <div class=\"inline-flex items-center rounded-full bg-gray-200 p-0.5 text-xs font-semibold\">\n <button\n type=\"button\"\n class=\"rounded-full px-2.5 py-0.5 transition\"\n :class=\"detailViewMode === 'text' ? 'bg-blue-600 text-white shadow' : 'text-content-secondary hover:text-content'\"\n :style=\"detailViewMode === 'text' ? 'color: white !important; background-color: #2563eb !important;' : ''\"\n @click.stop=\"setDetailViewMode('text')\">\n Text\n </button>\n <button\n type=\"button\"\n class=\"rounded-full px-2.5 py-0.5 transition\"\n :class=\"detailViewMode === 'map' ? 'bg-blue-600 text-white shadow' : 'text-content-secondary hover:text-content'\"\n :style=\"detailViewMode === 'map' ? 'color: white !important; background-color: #2563eb !important;' : ''\"\n @click.stop=\"setDetailViewMode('map')\">\n Map\n </button>\n </div>\n <!-- Info icon with tooltip -->\n <div v-if=\"editting\" class=\"relative inline-block\" style=\"z-index: 10002;\" @mouseenter=\"showTooltip = true\" @mouseleave=\"showTooltip = false\" @click.stop>\n <svg\n ref=\"infoIcon\"\n class=\"w-6 h-6 text-gray-400 hover:text-gray-600 cursor-help\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"></path>\n </svg>\n <div\n v-show=\"showTooltip\"\n ref=\"tooltip\"\n class=\"absolute left-full top-0 ml-2 w-64 p-3 text-white text-xs rounded-lg shadow-xl\"\n style=\"z-index: 99999; pointer-events: none; white-space: normal; position: fixed; background-color: #111827;\"\n :style=\"getTooltipStyle()\"\n >\n <div class=\"font-semibold mb-2\">Map Controls:</div>\n <div v-if=\"isGeoJsonPoint\" class=\"space-y-1\">\n <div>• Drag pin to move location</div>\n </div>\n <div v-else-if=\"isGeoJsonPolygon\" class=\"space-y-1\">\n <div>• Drag vertices to reshape polygon</div>\n <div v-if=\"isMultiPolygon\">• Right-click edge to add new vertex</div>\n <div>• Right-click vertex to delete</div>\n </div>\n <div class=\"absolute top-2 -left-1 w-0 h-0 border-t-4 border-b-4 border-r-4 border-transparent border-r-gray-900\"></div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"flex items-center gap-2\">\n <date-view-mode-picker\n v-if=\"isDatePath\"\n :viewMode=\"dateViewMode\"\n :path=\"path\"\n @update:viewMode=\"dateViewMode = $event\"\n ></date-view-mode-picker>\n <button\n type=\"button\"\n class=\"flex items-center gap-1 text-sm text-gray-600 hover:text-gray-800 px-2 py-1 rounded-md border border-transparent hover:border-edge-strong bg-surface\"\n @click.stop.prevent=\"copyPropertyValue\"\n title=\"Copy value\"\n aria-label=\"Copy property value\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 7h8m-8 4h8m-8 4h5m-7-9a2 2 0 012-2h7a2 2 0 012 2v10a2 2 0 01-2 2H8l-4-4V7a2 2 0 012-2z\" />\n </svg>\n {{copyButtonLabel}}\n </button>\n <router-link\n v-if=\"path.ref && getValueForPath(path.path)\"\n :to=\"`/model/${path.ref}/document/${getValueForPath(path.path)}`\"\n class=\"bg-primary hover:bg-primary-hover text-primary-text px-2 py-1 text-sm rounded-md\"\n @click.stop\n >View Document\n </router-link>\n </div>\n </div>\n\n <!-- Collapsible Content -->\n <div v-if=\"!isCollapsed\" class=\"p-2\">\n <!-- Date Type Selector (when editing dates) -->\n <div v-if=\"editting && path.instance === 'Date'\" class=\"mb-3 flex gap-1.5\">\n <div\n @click=\"dateType = 'picker'\"\n :class=\"dateType === 'picker' ? 'bg-teal-600' : ''\"\n class=\"self-stretch px-2 py-1 rounded-sm justify-center items-center gap-1.5 flex cursor-pointer\">\n <div\n :class=\"dateType === 'picker' ? 'text-white' : ''\"\n class=\"text-xs font-medium font-['Lato'] capitalize leading-tight\">\n Date Picker\n </div>\n </div>\n <div\n @click=\"dateType = 'iso'\"\n :class=\"dateType === 'iso' ? 'bg-teal-600' : ''\"\n class=\"self-stretch px-2 py-1 rounded-sm justify-center items-center gap-1.5 flex cursor-pointer\">\n <div\n :class=\"dateType === 'iso' ? 'text-white' : ''\"\n class=\"text-xs font-medium font-['Lato'] capitalize leading-tight\">\n ISO String\n </div>\n </div>\n </div>\n\n <!-- Field Content -->\n <div v-if=\"editting && path.path !== '_id'\">\n <!-- Use detail-default with map editing for GeoJSON geometries -->\n <component\n v-if=\"isGeoJsonGeometry\"\n :is=\"getComponentForPath(path)\"\n :value=\"getEditValueForPath(path)\"\n :viewMode=\"detailViewMode\"\n :on-change=\"handleInputChange\"\n >\n </component>\n <!-- Use standard edit components for other types -->\n <component\n v-else\n :is=\"getEditComponentForPath(path)\"\n :value=\"getEditValueForPath(path)\"\n :format=\"dateType\"\n v-bind=\"getEditComponentProps(path)\"\n @input=\"handleInputChange($event)\"\n @error=\"invalid[path.path] = $event;\"\n >\n </component>\n </div>\n <div v-else>\n <!-- Show truncated or full value based on needsTruncation and isValueExpanded -->\n <!-- Special handling for truncated arrays -->\n <div v-if=\"isArray && shouldShowTruncated\" class=\"w-full\">\n <div class=\"mt-2\">\n <div\n v-for=\"(item, index) in truncatedArrayItems\"\n :key=\"index\"\n class=\"mb-1.5 py-2.5 px-3 pl-4 bg-transparent border-l-[3px] border-l-blue-500 rounded-none transition-all duration-200 cursor-pointer relative hover:bg-slate-50 hover:border-l-blue-600\">\n <div class=\"absolute -left-2 top-1/2 -translate-y-1/2 w-5 h-5 bg-blue-500 text-white rounded-full flex items-center justify-center text-[10px] font-semibold font-mono z-10 hover:bg-blue-600\">{{ index }}</div>\n <div v-if=\"arrayUtils.isObjectItem(item)\" class=\"flex flex-col gap-1 mt-1 px-2\">\n <div\n v-for=\"key in arrayUtils.getItemKeys(item)\"\n :key=\"key\"\n class=\"flex items-start gap-2 text-xs font-mono\">\n <span class=\"font-semibold text-gray-600 flex-shrink-0 min-w-[80px]\">{{ key }}:</span>\n <span class=\"text-gray-800 break-words whitespace-pre-wrap flex-1\">{{ arrayUtils.formatItemValue(item, key) }}</span>\n </div>\n </div>\n <div v-else class=\"text-xs py-1.5 px-2 font-mono text-gray-800 break-words whitespace-pre-wrap mt-1\">{{ arrayUtils.formatValue(item) }}</div>\n </div>\n <div class=\"mb-1.5 py-2.5 px-3 pl-4 bg-transparent border-none border-l-[3px] border-l-blue-500 rounded-none transition-all duration-200 cursor-pointer relative opacity-70 hover:opacity-100\">\n <div class=\"text-xs py-1.5 px-2 font-mono text-content-tertiary italic break-words whitespace-pre-wrap mt-1\">\n ... and {{ remainingArrayCount }} more item{{ remainingArrayCount !== 1 ? 's' : '' }}\n </div>\n </div>\n </div>\n <button\n @click=\"toggleValueExpansion\"\n class=\"mt-2 text-blue-600 hover:text-blue-800 text-sm font-medium flex items-center gap-1 transform transition-all duration-200 ease-in-out hover:translate-x-0.5\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"></path>\n </svg>\n Show all {{ arrayValue.length }} items\n </button>\n </div>\n <!-- Non-array truncated view -->\n <div v-else-if=\"shouldShowTruncated && !isArray\" class=\"relative\">\n <div class=\"text-content-secondary whitespace-pre-wrap break-words font-mono text-sm\">{{truncatedString}}</div>\n <button\n @click=\"toggleValueExpansion\"\n class=\"mt-2 text-blue-600 hover:text-blue-800 text-sm font-medium flex items-center gap-1 transform transition-all duration-200 ease-in-out hover:translate-x-0.5\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"></path>\n </svg>\n Show more ({{valueAsString.length}} characters)\n </button>\n </div>\n <!-- Expanded view -->\n <div v-else-if=\"needsTruncation && isValueExpanded\" class=\"relative\">\n <component\n :is=\"getComponentForPath(path)\"\n :value=\"rawValue\"\n :viewMode=\"isDatePath ? dateViewMode : detailViewMode\"\n @updated=\"renderedValue = $event\"></component>\n <button\n @click=\"toggleValueExpansion\"\n class=\"mt-2 text-blue-600 hover:text-blue-800 text-sm font-medium flex items-center gap-1 transform transition-all duration-200 ease-in-out hover:translate-x-0.5\"\n >\n <svg class=\"w-4 h-4 rotate-180\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"></path>\n </svg>\n Show less\n </button>\n </div>\n <!-- Full view (no truncation needed) -->\n <div v-else>\n <component\n :is=\"getComponentForPath(path)\"\n :value=\"rawValue\"\n :viewMode=\"isDatePath ? dateViewMode : detailViewMode\"\n @updated=\"renderedValue = $event\"></component>\n </div>\n </div>\n </div>\n</div>\n";
50375
51063
 
50376
51064
  /***/ },
50377
51065
 
@@ -50734,7 +51422,7 @@ module.exports = ".models {\n position: relative;\n display: flex;\n flex-dir
50734
51422
  (module) {
50735
51423
 
50736
51424
  "use strict";
50737
- module.exports = "<div class=\"models flex\" style=\"height: calc(100vh - 55px); height: calc(100dvh - 55px)\">\n <aside class=\"bg-page border-r overflow-hidden transition-all duration-300 ease-in-out z-20 w-0 lg:w-64 fixed lg:relative shrink-0 flex flex-col top-[55px] bottom-0 lg:top-auto lg:bottom-auto lg:h-full\" :class=\"hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''\">\n <!-- Search -->\n <div class=\"p-3 shrink-0\">\n <div class=\"relative\">\n <svg class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n <input\n v-model=\"modelSearch\"\n type=\"text\"\n placeholder=\"Find model...\"\n @keydown.esc=\"modelSearch = ''\"\n class=\"w-full rounded-md border border-edge bg-surface py-1.5 pl-8 pr-3 text-sm text-content placeholder:text-gray-400 focus:border-edge-strong focus:outline-none focus:ring-1 focus:ring-gray-300\"\n />\n </div>\n </div>\n <!-- Model list (scrollable) -->\n <nav class=\"flex-1 overflow-y-auto px-2 pb-2\">\n <!-- Recently Viewed -->\n <div v-if=\"filteredRecentModels.length > 0 && !modelSearch.trim()\">\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">Recently Viewed</div>\n <ul role=\"list\">\n <li v-for=\"model in filteredRecentModels\" :key=\"'recent-' + model\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"flex items-center rounded-md py-1.5 px-2 text-sm text-content-secondary\"\n :class=\"model === currentModel ? 'bg-gray-200 font-semibold text-content' : 'hover:bg-muted'\">\n <span class=\"truncate\" v-html=\"highlightMatch(model)\"></span>\n <span\n v-if=\"modelDocumentCounts && modelDocumentCounts[model] !== undefined && model !== currentModel\"\n class=\"ml-auto text-xs text-gray-400 bg-muted rounded px-1.5 py-[1px]\"\n >\n {{formatCompactCount(modelDocumentCounts[model])}}\n </span>\n </router-link>\n </li>\n </ul>\n <div class=\"border-b border-edge my-2\"></div>\n </div>\n <!-- All Models / Search Results -->\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">{{ modelSearch.trim() ? 'Search Results' : 'All Models' }}</div>\n <ul role=\"list\">\n <li v-for=\"model in filteredModels\" :key=\"'all-' + model\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"flex items-center rounded-md py-1.5 px-2 text-sm text-content-secondary\"\n :class=\"model === currentModel ? 'bg-gray-200 font-semibold text-content' : 'hover:bg-muted'\">\n <span class=\"truncate\" v-html=\"highlightMatch(model)\"></span>\n <span\n v-if=\"modelDocumentCounts && modelDocumentCounts[model] !== undefined && model !== currentModel\"\n class=\"ml-auto text-xs text-gray-400 bg-muted rounded px-1.5 py-[1px]\"\n >\n {{formatCompactCount(modelDocumentCounts[model])}}\n </span>\n </router-link>\n </li>\n </ul>\n <div v-if=\"filteredModels.length === 0 && modelSearch.trim()\" class=\"px-2 py-2 text-sm text-content-tertiary\">\n No models match \"{{modelSearch}}\"\n </div>\n <div v-if=\"models.length === 0 && status === 'loaded'\" class=\"p-2 bg-red-100 rounded-md\">\n No models found\n </div>\n </nav>\n <!-- Bottom toolbar -->\n <div class=\"shrink-0 border-t border-edge bg-page px-2 py-1.5 flex items-center gap-1\">\n <button\n type=\"button\"\n @click=\"hideSidebar = true\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Hide sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\" />\n </svg>\n </button>\n <button\n type=\"button\"\n @click=\"openModelSwitcher\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Quick switch (Ctrl+P)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n </button>\n </div>\n </aside>\n <div class=\"documents bg-slate-50 min-w-0\" ref=\"documentsList\">\n <div class=\"documents-menu bg-slate-50\">\n <div class=\"flex flex-row items-center w-full gap-2\">\n <button\n v-if=\"hideSidebar === true || hideSidebar === null\"\n type=\"button\"\n @click=\"hideSidebar = false\"\n class=\"shrink-0 rounded-md p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n :class=\"hideSidebar === null ? 'lg:hidden' : ''\"\n title=\"Show sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <document-search\n ref=\"documentSearch\"\n :value=\"searchText\"\n :schema-paths=\"schemaPaths\"\n @search=\"search\"\n >\n </document-search>\n <div>\n <span v-if=\"numDocuments == null\">Loading ...</span>\n <span v-else-if=\"typeof numDocuments === 'number'\">{{documents.length}}/{{numDocuments === 1 ? numDocuments + ' document' : numDocuments + ' documents'}}</span>\n </div>\n <button\n @click=\"stagingSelect\"\n type=\"button\"\n :class=\"{\n 'bg-page0 ring-inset ring-2 ring-gray-300 hover:bg-gray-200 text-content-secondary': selectMultiple,\n 'bg-primary hover:bg-primary-hover text-primary-text': !selectMultiple\n }\"\n class=\"rounded px-2 py-2 text-sm font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {{ selectMultiple ? 'Cancel' : 'Select' }}\n </button>\n <button\n v-show=\"selectMultiple\"\n @click=\"shouldShowUpdateMultipleModal=true;\"\n type=\"button\"\n class=\"rounded bg-green-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600\"\n >\n Update\n </button>\n <button\n @click=\"shouldShowDeleteMultipleModal=true;\"\n type=\"button\"\n v-show=\"selectMultiple\"\n class=\"rounded bg-red-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500\"\n >\n Delete\n </button>\n <div class=\"relative\" v-show=\"!selectMultiple\" ref=\"actionsMenuContainer\" @keyup.esc.prevent=\"closeActionsMenu\">\n <button\n @click=\"toggleActionsMenu\"\n type=\"button\"\n aria-label=\"More actions\"\n class=\"rounded bg-surface px-2 py-2 text-sm font-semibold text-content-secondary shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-page focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Zm0 6a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Zm0 6a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Z\" />\n </svg>\n </button>\n <div\n v-if=\"showActionsMenu\"\n class=\"absolute right-0 mt-2 w-48 origin-top-right rounded-md bg-surface shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-50\"\n >\n <div class=\"py-1\">\n <button\n @click=\"shouldShowExportModal = true; showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Export\n </button>\n <button\n @click=\"shouldShowCreateModal = true; showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Create\n </button>\n <button\n @click=\"openIndexModal\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Indexes\n </button>\n <button\n @click=\"openCollectionInfo\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Collection Info\n </button>\n <button\n @click=\"findOldestDocument\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Find oldest document\n </button>\n <button\n @click=\"toggleRowNumbers()\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n {{ showRowNumbers ? 'Hide row numbers' : 'Show row numbers' }}\n </button>\n <button\n @click=\"resetFilter()\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Reset Filter\n </button>\n <button\n @click=\"toggleProjectionMenu(); showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm hover:bg-muted\"\n :class=\"isProjectionMenuSelected ? 'text-primary font-semibold' : 'text-content-secondary'\"\n >\n {{ isProjectionMenuSelected ? 'Projection (On)' : 'Projection' }}\n </button>\n <button\n v-if=\"isProjectionMenuSelected\"\n @click=\"clearProjection()\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Reset Projection\n </button>\n <async-button\n v-if=\"isProjectionMenuSelected\"\n type=\"button\"\n @click=\"applyDefaultProjectionColumns()\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Default Projection\n </async-button>\n </div>\n </div>\n </div>\n <span class=\"isolate inline-flex rounded-md shadow-sm\">\n <button\n @click=\"setOutputType('table')\"\n type=\"button\"\n class=\"relative inline-flex items-center rounded-none rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-page focus:z-10\"\n :class=\"outputType === 'table' ? 'bg-gray-200' : 'bg-surface'\">\n <img class=\"h-5 w-5\" src=\"images/table.svg\">\n </button>\n <button\n @click=\"setOutputType('json')\"\n type=\"button\"\n class=\"relative -ml-px inline-flex items-center px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-page focus:z-10\"\n :class=\"outputType === 'json' ? 'bg-gray-200' : 'bg-surface'\">\n <img class=\"h-5 w-5\" src=\"images/json.svg\">\n </button>\n <button\n @click=\"setOutputType('map')\"\n :disabled=\"geoJsonFields.length === 0\"\n type=\"button\"\n :title=\"geoJsonFields.length > 0 ? 'Map view' : 'No GeoJSON fields detected'\"\n class=\"relative -ml-px inline-flex items-center rounded-none rounded-r-md px-2 py-2 ring-1 ring-inset ring-gray-300 focus:z-10\"\n :class=\"[\n geoJsonFields.length === 0 ? 'text-gray-300 cursor-not-allowed bg-muted' : 'text-gray-400 hover:bg-page',\n outputType === 'map' ? 'bg-gray-200' : (geoJsonFields.length > 0 ? 'bg-surface' : '')\n ]\">\n <svg class=\"h-5 w-5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z\" />\n </svg>\n </button>\n </span>\n </div>\n <div v-if=\"isProjectionMenuSelected && (outputType === 'table' || outputType === 'json')\" class=\"flex items-center gap-2 w-full mt-2 flex-shrink-0\">\n <input\n ref=\"projectionInput\"\n v-model=\"projectionText\"\n type=\"text\"\n placeholder=\"Projection: name email, or -password\"\n class=\"flex-1 min-w-0 rounded border border-edge bg-surface px-2 py-1.5 text-sm font-mono placeholder:text-content-tertiary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary\"\n @focus=\"initProjection($event)\"\n @keydown.enter=\"applyProjectionFromInput()\"\n />\n </div>\n </div>\n <!-- In JSON view, this container is the scrollable element used for infinite scroll. -->\n <div class=\"documents-container relative\" ref=\"documentsContainerScroll\" @scroll=\"checkIfScrolledToBottom\">\n <div v-if=\"error\">\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 relative m-4 rounded-md\" role=\"alert\">\n <span class=\"block font-bold\">Error</span>\n <span class=\"block\">{{ error }}</span>\n </div>\n </div>\n <div v-else-if=\"outputType === 'table'\" class=\"flex-1 min-h-0 flex flex-col overflow-hidden\">\n <div\n ref=\"documentsScrollContainer\"\n class=\"overflow-x-auto overflow-y-auto flex-1 min-h-0 border border-edge rounded-lg bg-surface\"\n @scroll=\"checkIfScrolledToBottom\"\n >\n <table class=\"min-w-full border-collapse text-sm\">\n <thead class=\"sticky top-0 z-10 bg-slate-100 dark:bg-shark-800 border-b border-edge\">\n <tr>\n <th v-if=\"showRowNumbers\" class=\"px-3 py-2.5 text-left font-medium text-content border-r border-edge whitespace-nowrap align-middle w-0\">\n #\n </th>\n <th\n v-for=\"path in tableDisplayPaths\"\n :key=\"path.path\"\n class=\"px-3 py-2.5 text-left font-medium text-content border-r border-edge last:border-r-0 whitespace-nowrap align-middle\"\n >\n <div class=\"flex items-center gap-2\">\n <span\n @click=\"addPathFilter(path.path)\"\n class=\"cursor-pointer hover:text-primary truncate min-w-0\"\n :title=\"path.path\"\n >\n {{ path.path }}\n </span>\n <span class=\"text-xs text-content-tertiary shrink-0\">({{ path.instance || 'unknown' }})</span>\n <span class=\"inline-flex shrink-0 gap-0.5 items-center\">\n <button\n type=\"button\"\n @click.stop=\"sortDocs(1, path.path)\"\n class=\"p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted\"\n :class=\"{ 'text-primary font-semibold': sortBy[path.path] === 1 }\"\n :title=\"sortBy[path.path] === 1 ? 'Clear sort' : 'Sort ascending'\"\n >\n ↑\n </button>\n <button\n type=\"button\"\n @click.stop=\"sortDocs(-1, path.path)\"\n class=\"p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted\"\n :class=\"{ 'text-primary font-semibold': sortBy[path.path] === -1 }\"\n :title=\"sortBy[path.path] === -1 ? 'Clear sort' : 'Sort descending'\"\n >\n ↓\n </button>\n <button\n v-if=\"filteredPaths.length > 0\"\n type=\"button\"\n @click.stop=\"removeField(path)\"\n class=\"p-1.5 rounded-md border border-transparent text-content-tertiary hover:text-valencia-600 hover:bg-valencia-50 hover:border-valencia-200 focus:outline-none focus:ring-2 focus:ring-valencia-500/30\"\n title=\"Remove column\"\n aria-label=\"Remove column\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n </button>\n </span>\n </div>\n </th>\n <th v-if=\"filteredPaths.length > 0\" class=\"px-2 py-2.5 border-r border-edge last:border-r-0 align-middle w-0 bg-slate-50 dark:bg-shark-800/80\">\n <div class=\"relative\" ref=\"addFieldContainer\">\n <button\n type=\"button\"\n @click=\"toggleAddFieldDropdown()\"\n class=\"flex items-center justify-center w-8 h-8 rounded border border-dashed border-edge text-content-tertiary hover:border-primary hover:text-primary hover:bg-primary-subtle/30\"\n title=\"Add column\"\n aria-label=\"Add column\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" class=\"w-5 h-5\"> <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" /> </svg>\n </button>\n <div\n v-if=\"showAddFieldDropdown\"\n class=\"absolute right-0 top-full mt-1 z-[100] min-w-[180px] max-w-[280px] rounded-md border border-edge bg-surface shadow-lg py-1 max-h-48 overflow-y-auto\"\n >\n <input\n v-if=\"availablePathsToAdd.length > 5\"\n ref=\"addFieldFilterInput\"\n v-model=\"addFieldFilterText\"\n type=\"text\"\n placeholder=\"Filter fields...\"\n class=\"mx-2 mb-1 w-[calc(100%-1rem)] rounded border border-edge px-2 py-1 text-sm\"\n @click.stop\n />\n <button\n v-for=\"p in filteredPathsToAdd\"\n :key=\"p.path\"\n type=\"button\"\n class=\"w-full px-3 py-1.5 text-left text-sm hover:bg-muted\"\n @click.stop=\"addField(p)\"\n >\n {{ p.path }}\n </button>\n <p v-if=\"filteredPathsToAdd.length === 0\" class=\"px-3 py-2 text-sm text-content-tertiary\">\n {{ addFieldFilterText.trim() ? 'No matching fields' : 'All fields added' }}\n </p>\n </div>\n </div>\n </th>\n </tr>\n </thead>\n <tbody class=\"bg-surface\">\n <tr\n v-for=\"(document, docIndex) in documents\"\n :key=\"document._id\"\n @click=\"handleDocumentClick(document, $event)\"\n class=\"border-b border-edge cursor-pointer transition-colors hover:bg-muted/60\"\n :class=\"{ 'bg-primary-subtle/50 hover:bg-primary-subtle/70': selectedDocuments.some(x => x._id.toString() === document._id.toString()) }\"\n >\n <td v-if=\"showRowNumbers\" class=\"px-3 py-2 border-r border-edge align-top text-content-tertiary whitespace-nowrap\">\n {{ docIndex + 1 }}\n </td>\n <td\n v-for=\"schemaPath in tableDisplayPaths\"\n :key=\"schemaPath.path\"\n class=\"px-3 py-2 border-r border-edge last:border-r-0 align-top max-w-[280px]\"\n >\n <div class=\"table-cell-content flex items-center gap-1.5 min-w-0 group\">\n <span class=\"min-w-0 overflow-hidden text-ellipsis flex-1\">\n <component\n :is=\"getComponentForPath(schemaPath)\"\n :value=\"getValueForPath(document, schemaPath.path)\"\n :allude=\"getReferenceModel(schemaPath)\"\n />\n </span>\n <button\n type=\"button\"\n class=\"table-cell-copy shrink-0 p-1 rounded text-content-tertiary hover:text-content hover:bg-muted focus:outline-none focus:ring-1 focus:ring-edge\"\n aria-label=\"Copy cell value\"\n @click.stop=\"copyCellValue(getValueForPath(document, schemaPath.path))\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M8 5H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1M8 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M8 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m0 0h2a2 2 0 0 1 2 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n </div>\n </td>\n <td v-if=\"filteredPaths.length > 0\" class=\"w-0 px-0 py-0 border-r border-edge last:border-r-0 bg-slate-50/50 dark:bg-shark-800/30\"></td>\n </tr>\n </tbody>\n </table>\n </div>\n <div v-if=\"outputType === 'table' && (loadingMore || (status === 'loading' && documents.length > 0))\" class=\"flex items-center justify-center gap-2 py-3 text-sm text-content-tertiary border-t border-edge bg-surface\">\n <img src=\"images/loader.gif\" alt=\"\" class=\"h-5 w-5\">\n <span>Loading documents…</span>\n </div>\n <p v-if=\"outputType === 'table' && documents.length === 0 && status === 'loaded'\" class=\"mt-2 text-sm text-content-tertiary px-1\">\n No documents to show. Use Projection in the menu to choose columns.\n </p>\n </div>\n <div v-else-if=\"outputType === 'json'\" class=\"flex flex-col space-y-2 p-1 mt-1\">\n <div\n v-for=\"document in documents\"\n :key=\"document._id\"\n @click=\"handleDocumentContainerClick(document, $event)\"\n :class=\"[\n 'group relative transition-colors rounded-md border border-slate-100',\n selectedDocuments.some(x => x._id.toString() === document._id.toString()) ? 'bg-blue-200' : 'hover:shadow-sm hover:border-slate-300 bg-surface'\n ]\"\n >\n <button\n type=\"button\"\n class=\"absolute top-2 right-2 z-10 inline-flex items-center rounded bg-primary px-2 py-1 text-xs font-semibold text-primary-text shadow-sm transition-opacity duration-150 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n @click.stop=\"openDocument(document)\"\n >\n Open this Document\n </button>\n <list-json :value=\"filterDocument(document)\" :references=\"referenceMap\">\n </list-json>\n </div>\n <div v-if=\"outputType === 'json' && (loadingMore || (status === 'loading' && documents.length > 0))\" class=\"flex items-center justify-center gap-2 py-3 text-sm text-content-tertiary\">\n <img src=\"images/loader.gif\" alt=\"\" class=\"h-5 w-5\">\n <span>Loading documents…</span>\n </div>\n </div>\n <div v-else-if=\"outputType === 'map'\" class=\"flex flex-col h-full\">\n <div class=\"p-2 bg-surface border-b flex items-center gap-2\">\n <label class=\"text-sm font-medium text-content-secondary\">GeoJSON Field:</label>\n <select\n :value=\"selectedGeoField\"\n @change=\"setSelectedGeoField($event.target.value)\"\n class=\"rounded-md border border-edge-strong py-1 px-2 text-sm focus:border-primary focus:ring-primary\"\n >\n <option v-for=\"field in geoJsonFields\" :key=\"field.path\" :value=\"field.path\">\n {{ field.label }}\n </option>\n </select>\n <async-button\n @click=\"loadMoreDocuments\"\n :disabled=\"loadedAllDocs\"\n type=\"button\"\n class=\"rounded px-2 py-1 text-xs font-semibold text-primary-text shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n :class=\"loadedAllDocs ? 'bg-gray-400 cursor-not-allowed' : 'bg-primary hover:bg-primary-hover'\"\n >\n Load more\n </async-button>\n </div>\n <div class=\"flex-1 min-h-[400px]\" ref=\"modelsMap\"></div>\n </div>\n <div v-if=\"status === 'loading' && !loadingMore && documents.length === 0\" class=\"loader loader-overlay\" aria-busy=\"true\">\n <img src=\"images/loader.gif\" alt=\"Loading\">\n </div>\n </div>\n </div>\n <modal v-if=\"shouldShowExportModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowExportModal = false\">&times;</div>\n <export-query-results\n :schemaPaths=\"schemaPaths\"\n :search-text=\"searchText\"\n :currentModel=\"currentModel\"\n @done=\"shouldShowExportModal = false\">\n </export-query-results>\n </template>\n </modal>\n <modal v-if=\"shouldShowIndexModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowIndexModal = false\">&times;</div>\n <div class=\"text-xl font-bold mb-2\">Indexes</div>\n <div v-for=\"index in mongoDBIndexes\" class=\"w-full flex items-center\">\n <div class=\"grow shrink text-left flex justify-between items-center\" v-if=\"index.name != '_id_'\">\n <div>\n <div class=\"font-bold flex items-center gap-2\">\n <div>{{ index.name }}</div>\n <div v-if=\"isTTLIndex(index)\" class=\"rounded-full bg-primary-subtle px-2 py-0.5 text-xs font-semibold text-primary\">\n TTL: {{ formatTTL(index.expireAfterSeconds) }}\n </div>\n </div>\n <div class=\"text-sm font-mono\">{{ JSON.stringify(index.key) }}</div>\n </div>\n <div>\n <async-button\n type=\"button\"\n @click=\"dropIndex(index.name)\"\n class=\"rounded-md bg-valencia-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-valencia-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600 disabled:bg-gray-400 disabled:cursor-not-allowed\">\n Drop\n </async-button>\n </div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowCollectionInfoModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCollectionInfoModal = false\">&times;</div>\n <div class=\"text-xl font-bold mb-2\">Collection Info</div>\n <div v-if=\"!collectionInfo\" class=\"text-gray-600\">Loading collection details...</div>\n <div v-else class=\"space-y-3\">\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Documents</div>\n <div class=\"text-content\">{{ formatNumber(collectionInfo.documentCount) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Indexes</div>\n <div class=\"text-content\">{{ formatNumber(collectionInfo.indexCount) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Total Index Size</div>\n <div class=\"text-content\">{{ formatCollectionSize(collectionInfo.totalIndexSize) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Total Storage Size</div>\n <div class=\"text-content\">{{ formatCollectionSize(collectionInfo.size) }}</div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Collation</div>\n <div class=\"text-content\">{{ collectionInfo.hasCollation ? 'Yes' : 'No' }}</div>\n </div>\n <div v-if=\"collectionInfo.hasCollation\" class=\"rounded bg-muted p-3 text-sm text-gray-800 overflow-x-auto\">\n <pre class=\"whitespace-pre-wrap\">{{ JSON.stringify(collectionInfo.collation, null, 2) }}</pre>\n </div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Capped</div>\n <div class=\"text-content\">{{ collectionInfo.capped ? 'Yes' : 'No' }}</div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowCreateModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCreateModal = false;\">&times;</div>\n <create-document :currentModel=\"currentModel\" :paths=\"schemaPaths\" @close=\"closeCreationModal\"></create-document>\n </template>\n </modal>\n <modal v-if=\"shouldShowUpdateMultipleModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowUpdateMultipleModal = false;\">&times;</div>\n <update-document :currentModel=\"currentModel\" :document=\"selectedDocuments\" :multiple=\"true\" @update=\"updateDocuments\" @close=\"shouldShowUpdateMultipleModal=false;\"></update-document>\n </template>\n </modal>\n <modal v-if=\"shouldShowDeleteMultipleModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowDeleteMultipleModal = false;\">&times;</div>\n <h2>Are you sure you want to delete {{selectedDocuments.length}} documents?</h2>\n <div>\n <list-json :value=\"selectedDocuments\"></list-json>\n </div>\n <div class=\"flex gap-4\">\n <async-button @click=\"deleteDocuments\" class=\"rounded bg-red-500 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600\">\n Confirm\n </async-button>\n <button @click=\"shouldShowDeleteMultipleModal = false;\" class=\"rounded bg-gray-400 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-page0 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500\">\n Cancel\n </button>\n </div>\n </template>\n </modal>\n <model-switcher\n :show=\"showModelSwitcher\"\n :models=\"models\"\n :recently-viewed-models=\"recentlyViewedModels\"\n :model-document-counts=\"modelDocumentCounts\"\n @close=\"showModelSwitcher = false\"\n @select=\"selectSwitcherModel\"\n ></model-switcher>\n</div>\n";
51425
+ module.exports = "<div class=\"models flex\" style=\"height: calc(100vh - 55px); height: calc(100dvh - 55px)\">\n <aside class=\"bg-page border-r overflow-hidden transition-all duration-300 ease-in-out z-20 w-0 lg:w-64 fixed lg:relative shrink-0 flex flex-col top-[55px] bottom-0 lg:top-auto lg:bottom-auto lg:h-full\" :class=\"hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''\">\n <!-- Search -->\n <div class=\"p-3 shrink-0\">\n <div class=\"relative\">\n <svg class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n <input\n v-model=\"modelSearch\"\n type=\"text\"\n placeholder=\"Find model...\"\n @keydown.esc=\"modelSearch = ''\"\n class=\"w-full rounded-md border border-edge bg-surface py-1.5 pl-8 pr-3 text-sm text-content placeholder:text-gray-400 focus:border-edge-strong focus:outline-none focus:ring-1 focus:ring-gray-300\"\n />\n </div>\n </div>\n <!-- Model list (scrollable) -->\n <nav class=\"flex-1 overflow-y-auto px-2 pb-2\">\n <!-- Recently Viewed -->\n <div v-if=\"filteredRecentModels.length > 0 && !modelSearch.trim()\">\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">Recently Viewed</div>\n <ul role=\"list\">\n <li v-for=\"model in filteredRecentModels\" :key=\"'recent-' + model\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"flex items-center rounded-md py-1.5 px-2 text-sm text-content-secondary\"\n :class=\"model === currentModel ? 'bg-gray-200 font-semibold text-content' : 'hover:bg-muted'\">\n <span class=\"truncate\" v-html=\"highlightMatch(model)\"></span>\n <span\n v-if=\"modelDocumentCounts && modelDocumentCounts[model] !== undefined && model !== currentModel\"\n class=\"ml-auto text-xs text-gray-400 bg-muted rounded px-1.5 py-[1px]\"\n >\n {{formatCompactCount(modelDocumentCounts[model])}}\n </span>\n </router-link>\n </li>\n </ul>\n <div class=\"border-b border-edge my-2\"></div>\n </div>\n <!-- All Models / Search Results -->\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">{{ modelSearch.trim() ? 'Search Results' : 'All Models' }}</div>\n <ul role=\"list\">\n <li v-for=\"model in filteredModels\" :key=\"'all-' + model\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"flex items-center rounded-md py-1.5 px-2 text-sm text-content-secondary\"\n :class=\"model === currentModel ? 'bg-gray-200 font-semibold text-content' : 'hover:bg-muted'\">\n <span class=\"truncate\" v-html=\"highlightMatch(model)\"></span>\n <span\n v-if=\"modelDocumentCounts && modelDocumentCounts[model] !== undefined && model !== currentModel\"\n class=\"ml-auto text-xs text-gray-400 bg-muted rounded px-1.5 py-[1px]\"\n >\n {{formatCompactCount(modelDocumentCounts[model])}}\n </span>\n </router-link>\n </li>\n </ul>\n <div v-if=\"filteredModels.length === 0 && modelSearch.trim()\" class=\"px-2 py-2 text-sm text-content-tertiary\">\n No models match \"{{modelSearch}}\"\n </div>\n <div v-if=\"models.length === 0 && status === 'loaded'\" class=\"p-2 bg-red-100 rounded-md\">\n No models found\n </div>\n </nav>\n <!-- Bottom toolbar -->\n <div class=\"shrink-0 border-t border-edge bg-page px-2 py-1.5 flex items-center gap-1\">\n <button\n type=\"button\"\n @click=\"hideSidebar = true\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Hide sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\" />\n </svg>\n </button>\n <button\n type=\"button\"\n @click=\"openModelSwitcher\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Quick switch (Ctrl+P)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n </button>\n </div>\n </aside>\n <div class=\"documents bg-slate-50 min-w-0\" ref=\"documentsList\">\n <div class=\"documents-menu bg-slate-50\">\n <div class=\"flex flex-row items-center w-full gap-2\">\n <button\n v-if=\"hideSidebar === true || hideSidebar === null\"\n type=\"button\"\n @click=\"hideSidebar = false\"\n class=\"shrink-0 rounded-md p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n :class=\"hideSidebar === null ? 'lg:hidden' : ''\"\n title=\"Show sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <document-search\n ref=\"documentSearch\"\n :value=\"searchText\"\n :schema-paths=\"schemaPaths\"\n @search=\"search\"\n >\n </document-search>\n <div>\n <span v-if=\"numDocuments == null\">Loading ...</span>\n <span v-else-if=\"typeof numDocuments === 'number'\">{{documents.length}}/{{numDocuments === 1 ? numDocuments + ' document' : numDocuments + ' documents'}}</span>\n </div>\n <button\n @click=\"stagingSelect\"\n type=\"button\"\n :class=\"{\n 'bg-page0 ring-inset ring-2 ring-gray-300 hover:bg-gray-200 text-content-secondary': selectMultiple,\n 'bg-primary hover:bg-primary-hover text-primary-text': !selectMultiple\n }\"\n class=\"rounded px-2 py-2 text-sm font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {{ selectMultiple ? 'Cancel' : 'Select' }}\n </button>\n <button\n v-show=\"selectMultiple\"\n @click=\"shouldShowUpdateMultipleModal=true;\"\n type=\"button\"\n class=\"rounded bg-green-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600\"\n >\n Update\n </button>\n <button\n @click=\"shouldShowDeleteMultipleModal=true;\"\n type=\"button\"\n v-show=\"selectMultiple\"\n class=\"rounded bg-red-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500\"\n >\n Delete\n </button>\n <div class=\"relative\" v-show=\"!selectMultiple\" ref=\"actionsMenuContainer\" @keyup.esc.prevent=\"closeActionsMenu\">\n <button\n @click=\"toggleActionsMenu\"\n type=\"button\"\n aria-label=\"More actions\"\n class=\"rounded bg-surface px-2 py-2 text-sm font-semibold text-content-secondary shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-page focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Zm0 6a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Zm0 6a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Z\" />\n </svg>\n </button>\n <div\n v-if=\"showActionsMenu\"\n class=\"absolute right-0 mt-2 w-48 origin-top-right rounded-md bg-surface shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-50\"\n >\n <div class=\"py-1\">\n <button\n @click=\"shouldShowExportModal = true; showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Export\n </button>\n <button\n @click=\"shouldShowCreateModal = true; showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Create\n </button>\n <button\n @click=\"openIndexModal\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Indexes\n </button>\n <button\n @click=\"openCollectionInfo\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Collection Info\n </button>\n <button\n @click=\"findOldestDocument\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Find oldest document\n </button>\n <button\n @click=\"toggleRowNumbers()\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n {{ showRowNumbers ? 'Hide row numbers' : 'Show row numbers' }}\n </button>\n <button\n @click=\"resetFilter()\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Reset Filter\n </button>\n <button\n @click=\"toggleProjectionMenu(); showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm hover:bg-muted\"\n :class=\"isProjectionMenuSelected ? 'text-primary font-semibold' : 'text-content-secondary'\"\n >\n {{ isProjectionMenuSelected ? 'Projection (On)' : 'Projection' }}\n </button>\n <button\n v-if=\"isProjectionMenuSelected\"\n @click=\"clearProjection()\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Reset Projection\n </button>\n <async-button\n v-if=\"isProjectionMenuSelected\"\n type=\"button\"\n @click=\"applyDefaultProjectionColumns()\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Default Projection\n </async-button>\n </div>\n </div>\n </div>\n <span class=\"isolate inline-flex rounded-md shadow-sm\">\n <button\n @click=\"setOutputType('table')\"\n type=\"button\"\n class=\"relative inline-flex items-center rounded-none rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-page focus:z-10\"\n :class=\"outputType === 'table' ? 'bg-gray-200' : 'bg-surface'\">\n <img class=\"h-5 w-5\" src=\"images/table.svg\">\n </button>\n <button\n @click=\"setOutputType('json')\"\n type=\"button\"\n class=\"relative -ml-px inline-flex items-center px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-page focus:z-10\"\n :class=\"outputType === 'json' ? 'bg-gray-200' : 'bg-surface'\">\n <img class=\"h-5 w-5\" src=\"images/json.svg\">\n </button>\n <button\n @click=\"setOutputType('map')\"\n :disabled=\"geoJsonFields.length === 0\"\n type=\"button\"\n :title=\"geoJsonFields.length > 0 ? 'Map view' : 'No GeoJSON fields detected'\"\n class=\"relative -ml-px inline-flex items-center rounded-none rounded-r-md px-2 py-2 ring-1 ring-inset ring-gray-300 focus:z-10\"\n :class=\"[\n geoJsonFields.length === 0 ? 'text-gray-300 cursor-not-allowed bg-muted' : 'text-gray-400 hover:bg-page',\n outputType === 'map' ? 'bg-gray-200' : (geoJsonFields.length > 0 ? 'bg-surface' : '')\n ]\">\n <svg class=\"h-5 w-5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z\" />\n </svg>\n </button>\n </span>\n </div>\n <div v-if=\"isProjectionMenuSelected && (outputType === 'table' || outputType === 'json')\" class=\"flex items-center gap-2 w-full mt-2 flex-shrink-0\">\n <input\n ref=\"projectionInput\"\n v-model=\"projectionText\"\n type=\"text\"\n placeholder=\"Projection: name email, or -password\"\n class=\"flex-1 min-w-0 rounded border border-edge bg-surface px-2 py-1.5 text-sm font-mono placeholder:text-content-tertiary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary\"\n @focus=\"initProjection($event)\"\n @keydown.enter=\"applyProjectionFromInput()\"\n />\n </div>\n </div>\n <!-- In JSON view, this container is the scrollable element used for infinite scroll. -->\n <div class=\"documents-container relative\" ref=\"documentsContainerScroll\" @scroll=\"checkIfScrolledToBottom\">\n <div v-if=\"error\">\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 relative m-4 rounded-md\" role=\"alert\">\n <span class=\"block font-bold\">Error</span>\n <span class=\"block\">{{ error }}</span>\n <span class=\"block mt-2\">\n Need help?\n <a\n href=\"https://discord.gg/P3YCfKYxpy\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"underline font-medium text-red-800 hover:text-red-900\"\n >Ask in Discord</a>\n or\n <a\n href=\"https://github.com/mongoosejs/studio/issues\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"underline font-medium text-red-800 hover:text-red-900\"\n >\n open a GitHub issue.\n </a>\n </span>\n </div>\n </div>\n <div v-else-if=\"outputType === 'table'\" class=\"flex-1 min-h-0 flex flex-col overflow-hidden\">\n <div\n ref=\"documentsScrollContainer\"\n class=\"overflow-x-auto overflow-y-auto flex-1 min-h-0 border border-edge rounded-lg bg-surface\"\n @scroll=\"checkIfScrolledToBottom\"\n >\n <table class=\"min-w-full border-collapse text-sm\">\n <thead class=\"sticky top-0 z-10 bg-slate-100 dark:bg-shark-800 border-b border-edge\">\n <tr>\n <th v-if=\"showRowNumbers\" class=\"px-3 py-2.5 text-left font-medium text-content border-r border-edge whitespace-nowrap align-middle w-0\">\n #\n </th>\n <th\n v-for=\"path in tableDisplayPaths\"\n :key=\"path.path\"\n class=\"px-3 py-2.5 text-left font-medium text-content border-r border-edge last:border-r-0 whitespace-nowrap align-middle\"\n >\n <div class=\"flex items-center gap-2\">\n <span\n @click=\"addPathFilter(path.path)\"\n class=\"cursor-pointer hover:text-primary truncate min-w-0\"\n :title=\"path.path\"\n >\n {{ path.path }}\n </span>\n <span class=\"text-xs text-content-tertiary shrink-0\">({{ path.instance || 'unknown' }})</span>\n <span class=\"inline-flex shrink-0 gap-0.5 items-center\">\n <button\n type=\"button\"\n @click.stop=\"sortDocs(1, path.path)\"\n class=\"p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted\"\n :class=\"{ 'text-primary font-semibold': sortBy[path.path] === 1 }\"\n :title=\"sortBy[path.path] === 1 ? 'Clear sort' : 'Sort ascending'\"\n >\n ↑\n </button>\n <button\n type=\"button\"\n @click.stop=\"sortDocs(-1, path.path)\"\n class=\"p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted\"\n :class=\"{ 'text-primary font-semibold': sortBy[path.path] === -1 }\"\n :title=\"sortBy[path.path] === -1 ? 'Clear sort' : 'Sort descending'\"\n >\n ↓\n </button>\n <button\n v-if=\"filteredPaths.length > 0\"\n type=\"button\"\n @click.stop=\"removeField(path)\"\n class=\"p-1.5 rounded-md border border-transparent text-content-tertiary hover:text-valencia-600 hover:bg-valencia-50 hover:border-valencia-200 focus:outline-none focus:ring-2 focus:ring-valencia-500/30\"\n title=\"Remove column\"\n aria-label=\"Remove column\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n </button>\n </span>\n </div>\n </th>\n <th v-if=\"filteredPaths.length > 0\" class=\"px-2 py-2.5 border-r border-edge last:border-r-0 align-middle w-0 bg-slate-50 dark:bg-shark-800/80\">\n <div class=\"relative\" ref=\"addFieldContainer\">\n <button\n type=\"button\"\n @click=\"toggleAddFieldDropdown()\"\n class=\"flex items-center justify-center w-8 h-8 rounded border border-dashed border-edge text-content-tertiary hover:border-primary hover:text-primary hover:bg-primary-subtle/30\"\n title=\"Add column\"\n aria-label=\"Add column\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" class=\"w-5 h-5\"> <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" /> </svg>\n </button>\n <div\n v-if=\"showAddFieldDropdown\"\n class=\"absolute right-0 top-full mt-1 z-[100] min-w-[180px] max-w-[280px] rounded-md border border-edge bg-surface shadow-lg py-1 max-h-48 overflow-y-auto\"\n >\n <input\n v-if=\"availablePathsToAdd.length > 5\"\n ref=\"addFieldFilterInput\"\n v-model=\"addFieldFilterText\"\n type=\"text\"\n placeholder=\"Filter fields...\"\n class=\"mx-2 mb-1 w-[calc(100%-1rem)] rounded border border-edge px-2 py-1 text-sm\"\n @click.stop\n />\n <button\n v-for=\"p in filteredPathsToAdd\"\n :key=\"p.path\"\n type=\"button\"\n class=\"w-full px-3 py-1.5 text-left text-sm hover:bg-muted\"\n @click.stop=\"addField(p)\"\n >\n {{ p.path }}\n </button>\n <p v-if=\"filteredPathsToAdd.length === 0\" class=\"px-3 py-2 text-sm text-content-tertiary\">\n {{ addFieldFilterText.trim() ? 'No matching fields' : 'All fields added' }}\n </p>\n </div>\n </div>\n </th>\n </tr>\n </thead>\n <tbody class=\"bg-surface\">\n <tr\n v-for=\"(document, docIndex) in documents\"\n :key=\"document._id\"\n @click=\"handleDocumentClick(document, $event)\"\n class=\"border-b border-edge cursor-pointer transition-colors hover:bg-muted/60\"\n :class=\"{ 'bg-primary-subtle/50 hover:bg-primary-subtle/70': selectedDocuments.some(x => x._id.toString() === document._id.toString()) }\"\n >\n <td v-if=\"showRowNumbers\" class=\"px-3 py-2 border-r border-edge align-top text-content-tertiary whitespace-nowrap\">\n {{ docIndex + 1 }}\n </td>\n <td\n v-for=\"schemaPath in tableDisplayPaths\"\n :key=\"schemaPath.path\"\n class=\"px-3 py-2 border-r border-edge last:border-r-0 align-top max-w-[280px]\"\n >\n <div class=\"table-cell-content flex items-center gap-1.5 min-w-0 group\">\n <span class=\"min-w-0 overflow-hidden text-ellipsis flex-1\">\n <component\n :is=\"getComponentForPath(schemaPath)\"\n :value=\"getValueForPath(document, schemaPath.path)\"\n :allude=\"getReferenceModel(schemaPath)\"\n />\n </span>\n <button\n type=\"button\"\n class=\"table-cell-copy shrink-0 p-1 rounded text-content-tertiary hover:text-content hover:bg-muted focus:outline-none focus:ring-1 focus:ring-edge\"\n aria-label=\"Copy cell value\"\n @click.stop=\"copyCellValue(getValueForPath(document, schemaPath.path))\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M8 5H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1M8 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M8 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m0 0h2a2 2 0 0 1 2 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n </div>\n </td>\n <td v-if=\"filteredPaths.length > 0\" class=\"w-0 px-0 py-0 border-r border-edge last:border-r-0 bg-slate-50/50 dark:bg-shark-800/30\"></td>\n </tr>\n </tbody>\n </table>\n </div>\n <div v-if=\"outputType === 'table' && (loadingMore || (status === 'loading' && documents.length > 0))\" class=\"flex items-center justify-center gap-2 py-3 text-sm text-content-tertiary border-t border-edge bg-surface\">\n <img src=\"images/loader.gif\" alt=\"\" class=\"h-5 w-5\">\n <span>Loading documents…</span>\n </div>\n <p v-if=\"outputType === 'table' && documents.length === 0 && status === 'loaded'\" class=\"mt-2 text-sm text-content-tertiary px-1\">\n No documents to show. Use Projection in the menu to choose columns.\n </p>\n </div>\n <div v-else-if=\"outputType === 'json'\" class=\"flex flex-col space-y-2 p-1 mt-1\">\n <div\n v-for=\"document in documents\"\n :key=\"document._id\"\n @click=\"handleDocumentContainerClick(document, $event)\"\n :class=\"[\n 'group relative transition-colors rounded-md border border-slate-100',\n selectedDocuments.some(x => x._id.toString() === document._id.toString()) ? 'bg-blue-200' : 'hover:shadow-sm hover:border-slate-300 bg-surface'\n ]\"\n >\n <router-link\n class=\"absolute top-2 right-2 z-10 inline-flex items-center rounded bg-primary px-2 py-1 text-xs font-semibold text-primary-text shadow-sm transition-opacity duration-150 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n :to=\"{ path: '/model/' + currentModel + '/document/' + document._id, query: $route.query }\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n @click.stop\n >\n Open\n </router-link>\n <list-json :value=\"filterDocument(document)\" :references=\"referenceMap\">\n </list-json>\n </div>\n <div v-if=\"outputType === 'json' && (loadingMore || (status === 'loading' && documents.length > 0))\" class=\"flex items-center justify-center gap-2 py-3 text-sm text-content-tertiary\">\n <img src=\"images/loader.gif\" alt=\"\" class=\"h-5 w-5\">\n <span>Loading documents…</span>\n </div>\n </div>\n <div v-else-if=\"outputType === 'map'\" class=\"flex flex-col h-full\">\n <div class=\"p-2 bg-surface border-b flex items-center gap-2\">\n <label class=\"text-sm font-medium text-content-secondary\">GeoJSON Field:</label>\n <select\n :value=\"selectedGeoField\"\n @change=\"setSelectedGeoField($event.target.value)\"\n class=\"rounded-md border border-edge-strong py-1 px-2 text-sm focus:border-primary focus:ring-primary\"\n >\n <option v-for=\"field in geoJsonFields\" :key=\"field.path\" :value=\"field.path\">\n {{ field.label }}\n </option>\n </select>\n <async-button\n @click=\"loadMoreDocuments\"\n :disabled=\"loadedAllDocs\"\n type=\"button\"\n class=\"rounded px-2 py-1 text-xs font-semibold text-primary-text shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n :class=\"loadedAllDocs ? 'bg-gray-400 cursor-not-allowed' : 'bg-primary hover:bg-primary-hover'\"\n >\n Load more\n </async-button>\n </div>\n <div class=\"flex-1 min-h-[400px]\" ref=\"modelsMap\"></div>\n </div>\n <div v-if=\"status === 'loading' && !loadingMore && documents.length === 0\" class=\"loader loader-overlay\" aria-busy=\"true\">\n <img src=\"images/loader.gif\" alt=\"Loading\">\n </div>\n </div>\n </div>\n <modal v-if=\"shouldShowExportModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowExportModal = false\">&times;</div>\n <export-query-results\n :schemaPaths=\"schemaPaths\"\n :search-text=\"searchText\"\n :currentModel=\"currentModel\"\n @done=\"shouldShowExportModal = false\">\n </export-query-results>\n </template>\n </modal>\n <modal v-if=\"shouldShowIndexModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowIndexModal = false\">&times;</div>\n <div class=\"text-xl font-bold mb-2\">Indexes</div>\n <div v-for=\"index in mongoDBIndexes\" class=\"w-full flex items-center\">\n <div class=\"grow shrink text-left flex justify-between items-center\" v-if=\"index.name != '_id_'\">\n <div>\n <div class=\"font-bold flex items-center gap-2\">\n <div>{{ index.name }}</div>\n <div v-if=\"isTTLIndex(index)\" class=\"rounded-full bg-primary-subtle px-2 py-0.5 text-xs font-semibold text-primary\">\n TTL: {{ formatTTL(index.expireAfterSeconds) }}\n </div>\n </div>\n <div class=\"text-sm font-mono\">{{ JSON.stringify(index.key) }}</div>\n </div>\n <div>\n <async-button\n type=\"button\"\n @click=\"dropIndex(index.name)\"\n class=\"rounded-md bg-valencia-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-valencia-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600 disabled:bg-gray-400 disabled:cursor-not-allowed\">\n Drop\n </async-button>\n </div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowCollectionInfoModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCollectionInfoModal = false\">&times;</div>\n <div class=\"text-xl font-bold mb-2\">Collection Info</div>\n <div v-if=\"!collectionInfo\" class=\"text-gray-600\">Loading collection details...</div>\n <div v-else class=\"space-y-3\">\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Documents</div>\n <div class=\"text-content\">{{ formatNumber(collectionInfo.documentCount) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Indexes</div>\n <div class=\"text-content\">{{ formatNumber(collectionInfo.indexCount) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Total Index Size</div>\n <div class=\"text-content\">{{ formatCollectionSize(collectionInfo.totalIndexSize) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Total Storage Size</div>\n <div class=\"text-content\">{{ formatCollectionSize(collectionInfo.size) }}</div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Collation</div>\n <div class=\"text-content\">{{ collectionInfo.hasCollation ? 'Yes' : 'No' }}</div>\n </div>\n <div v-if=\"collectionInfo.hasCollation\" class=\"rounded bg-muted p-3 text-sm text-gray-800 overflow-x-auto\">\n <pre class=\"whitespace-pre-wrap\">{{ JSON.stringify(collectionInfo.collation, null, 2) }}</pre>\n </div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Capped</div>\n <div class=\"text-content\">{{ collectionInfo.capped ? 'Yes' : 'No' }}</div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowCreateModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCreateModal = false;\">&times;</div>\n <create-document :currentModel=\"currentModel\" :paths=\"schemaPaths\" @close=\"closeCreationModal\"></create-document>\n </template>\n </modal>\n <modal v-if=\"shouldShowUpdateMultipleModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowUpdateMultipleModal = false;\">&times;</div>\n <update-document :currentModel=\"currentModel\" :document=\"selectedDocuments\" :multiple=\"true\" @update=\"updateDocuments\" @close=\"shouldShowUpdateMultipleModal=false;\"></update-document>\n </template>\n </modal>\n <modal v-if=\"shouldShowDeleteMultipleModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowDeleteMultipleModal = false;\">&times;</div>\n <h2>Are you sure you want to delete {{selectedDocuments.length}} documents?</h2>\n <div>\n <list-json :value=\"selectedDocuments\"></list-json>\n </div>\n <div class=\"flex gap-4\">\n <async-button @click=\"deleteDocuments\" class=\"rounded bg-red-500 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600\">\n Confirm\n </async-button>\n <button @click=\"shouldShowDeleteMultipleModal = false;\" class=\"rounded bg-gray-400 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-page0 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500\">\n Cancel\n </button>\n </div>\n </template>\n </modal>\n <model-switcher\n :show=\"showModelSwitcher\"\n :models=\"models\"\n :recently-viewed-models=\"recentlyViewedModels\"\n :model-document-counts=\"modelDocumentCounts\"\n @close=\"showModelSwitcher = false\"\n @select=\"selectSwitcherModel\"\n ></model-switcher>\n</div>\n";
50738
51426
 
50739
51427
  /***/ },
50740
51428
 
@@ -50756,7 +51444,18 @@ module.exports = ".active {\n text-decoration: underline;\n}\n\n.navbar .nav-le
50756
51444
  (module) {
50757
51445
 
50758
51446
  "use strict";
50759
- module.exports = "<div class=\"navbar w-full bg-page border-b border-edge !h-[55px] hidden md:grid grid-cols-[1fr_auto_1fr] items-stretch px-4\">\n <!-- Left: Logo + Brand -->\n <div class=\"flex items-center gap-2 self-center\">\n <router-link class=\"flex items-center gap-2\" :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-10 text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n <span class=\"text-base font-semibold text-content whitespace-nowrap\">Mongoose Studio</span>\n </router-link>\n </div>\n <!-- Center: Nav Links -->\n <nav class=\"flex items-stretch gap-6\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Documents</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\" aria-disabled=\"true\">\n Documents\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"dashboardView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Dashboards</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"chatView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Chat</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a\n :href=\"hasTaskVisualizer\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"taskView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">\n Tasks\n </a>\n <a\n href=\"https://studio.mongoosejs.io/docs\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-content-tertiary hover:text-content\"\n >\n Docs\n </a>\n </nav>\n <!-- Right: Env Badge + User -->\n <div class=\"flex items-center justify-end gap-3 self-center\">\n <div\n v-if=\"!!state.nodeEnv\"\n title=\"NODE_ENV\"\n class=\"inline-flex items-center rounded px-2 py-1 text-xs text-content-tertiary bg-surface border border-edge gap-2\"\n >\n <span\n :class=\"warnEnv ? 'bg-red-400' : 'bg-yellow-400'\"\n class=\"inline-block rounded-full\"\n style=\"width: 0.5em; height: 0.5em;\"\n ></span>\n <span>{{state.nodeEnv}}</span>\n </div>\n <button\n v-if=\"!user || !hasAPIKey\"\n type=\"button\"\n @click=\"toggleDarkMode\"\n :title=\"darkMode ? 'Switch to light mode' : 'Switch to dark mode'\"\n class=\"inline-flex items-center justify-center rounded-md p-2 text-content-tertiary hover:text-content-secondary hover:bg-muted\"\n aria-label=\"Toggle dark mode\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/>\n </svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/>\n </svg>\n </button>\n <div class=\"flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-primary px-2 py-2 text-sm font-semibold text-primary-text shadow-sm hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full text-sm focus:outline-none focus:ring-2 focus:ring-gray-300\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n\n <div\n v-if=\"showFlyout\"\n class=\"absolute right-0 top-[90%] w-48 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n aria-labelledby=\"user-menu-button\"\n style=\"z-index: 10000\"\n tabindex=\"-1\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode(); showFlyout = false\"\n class=\"w-full cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle text-left flex items-center gap-2\"\n role=\"menuitem\"\n tabindex=\"-1\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n {{ darkMode ? 'Light mode' : 'Dark mode' }}\n </button>\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span v-else class=\"block px-4 py-2 text-sm text-gray-300 cursor-not-allowed\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n </div>\n</div>\n<!-- Mobile navbar -->\n<div class=\"navbar w-full bg-page flex justify-between border-b border-edge !h-[55px] md:hidden\">\n <div class=\"flex items-center gap-2 pl-4\">\n <router-link class=\"flex items-center gap-2\" :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-8 text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n <span class=\"text-base font-semibold text-content\">Mongoose Studio</span>\n </router-link>\n </div>\n <div class=\"flex items-center\">\n <!-- Mobile menu toggle, controls the 'mobileMenuOpen' state. -->\n <button type=\"button\" id=\"open-mobile-menu\" class=\"-ml-2 rounded-md p-2 pr-4 text-gray-400\">\n <span class=\"sr-only\">Open menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\" />\n </svg>\n </button>\n </div>\n\n <!-- Mobile menu mask -->\n <div id=\"mobile-menu-mask\" class=\"fixed inset-0 bg-black bg-opacity-40 z-40 hidden\"></div>\n <!-- Mobile menu drawer -->\n <div id=\"mobile-menu\" style=\"z-index: 10000\" class=\"fixed inset-0 bg-page shadow-lg transform translate-x-full transition-transform duration-200 ease-in-out flex flex-col\">\n <div class=\"flex items-center justify-between px-4 !h-[55px] border-b border-edge\">\n <router-link :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-[32px] text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n </router-link>\n <button type=\"button\" id=\"close-mobile-menu\" class=\"text-gray-400 p-2 rounded-md\">\n <span class=\"sr-only\">Close menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <nav class=\"flex-1 px-4 py-4 space-y-2\">\n <div class=\"flex items-center gap-2 px-3 py-2\" v-if=\"!user || !hasAPIKey\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode\"\n class=\"inline-flex items-center gap-2 rounded-md px-3 py-2 text-base font-medium text-content-secondary hover:bg-muted\"\n aria-label=\"Toggle dark mode\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n <span>{{ darkMode ? 'Light mode' : 'Dark mode' }}</span>\n </button>\n </div>\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"documentView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Documents</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Documents\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"dashboardView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Dashboards</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"chatView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Chat</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <div v-if=\"!user && hasAPIKey\" class=\"mt-4\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"w-full rounded bg-muted text-content px-3 py-2 text-base font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"mt-4\">\n <div class=\"flex items-center gap-3 px-3 py-2 bg-page rounded-md\">\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n <span class=\"text-content font-medium\">{{ user.name }}</span>\n </div>\n <div class=\"mt-2 space-y-1\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode\"\n class=\"w-full inline-flex items-center gap-2 px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle text-left\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n {{ darkMode ? 'Light mode' : 'Dark mode' }}\n </button>\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle\">Team</router-link>\n <span v-else class=\"block px-3 py-2 rounded-md text-base text-gray-300 cursor-not-allowed\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span @click=\"logout\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle cursor-pointer\">Sign out</span>\n </div>\n </div>\n </nav>\n </div>\n</div>\n";
51447
+ module.exports = "<div class=\"navbar w-full bg-page border-b border-edge !h-[55px] hidden md:grid grid-cols-[1fr_auto_1fr] items-stretch px-4\">\n <!-- Left: Logo + Brand -->\n <div class=\"flex items-center gap-2 self-center\">\n <router-link class=\"flex items-center gap-2\" :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-10 text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n <span class=\"text-base font-semibold text-content whitespace-nowrap\">Mongoose Studio</span>\n </router-link>\n </div>\n <!-- Center: Nav Links -->\n <nav class=\"flex items-stretch gap-6\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Documents</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\" aria-disabled=\"true\">\n Documents\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"dashboardView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Dashboards</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"chatView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Chat</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a\n v-if=\"hasTaskVisualizer\"\n href=\"#/tasks\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"taskView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">\n Tasks\n </a>\n <a\n href=\"https://studio.mongoosejs.io/docs\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-content-tertiary hover:text-content\"\n >\n Docs\n </a>\n </nav>\n <!-- Right: Env Badge + User -->\n <div class=\"flex items-center justify-end gap-3 self-center\">\n <div\n v-if=\"!!state.nodeEnv\"\n title=\"NODE_ENV\"\n class=\"inline-flex items-center rounded px-2 py-1 text-xs text-content-tertiary bg-surface border border-edge gap-2\"\n >\n <span\n :class=\"warnEnv ? 'bg-red-400' : 'bg-yellow-400'\"\n class=\"inline-block rounded-full\"\n style=\"width: 0.5em; height: 0.5em;\"\n ></span>\n <span>{{state.nodeEnv}}</span>\n </div>\n <button\n v-if=\"!user || !hasAPIKey\"\n type=\"button\"\n @click=\"toggleDarkMode\"\n :title=\"darkMode ? 'Switch to light mode' : 'Switch to dark mode'\"\n class=\"inline-flex items-center justify-center rounded-md p-2 text-content-tertiary hover:text-content-secondary hover:bg-muted\"\n aria-label=\"Toggle dark mode\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/>\n </svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/>\n </svg>\n </button>\n <div class=\"flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-primary px-2 py-2 text-sm font-semibold text-primary-text shadow-sm hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full text-sm focus:outline-none focus:ring-2 focus:ring-gray-300\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n\n <div\n v-if=\"showFlyout\"\n class=\"absolute right-0 top-[90%] w-48 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n aria-labelledby=\"user-menu-button\"\n style=\"z-index: 10000\"\n tabindex=\"-1\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode(); showFlyout = false\"\n class=\"w-full cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle text-left flex items-center gap-2\"\n role=\"menuitem\"\n tabindex=\"-1\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n {{ darkMode ? 'Light mode' : 'Dark mode' }}\n </button>\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span v-else class=\"block px-4 py-2 text-sm text-gray-300 cursor-not-allowed\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n </div>\n</div>\n<!-- Mobile navbar -->\n<div class=\"navbar w-full bg-page flex justify-between border-b border-edge !h-[55px] md:hidden\">\n <div class=\"flex items-center gap-2 pl-4\">\n <router-link class=\"flex items-center gap-2\" :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-8 text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n <span class=\"text-base font-semibold text-content\">Mongoose Studio</span>\n </router-link>\n </div>\n <div class=\"flex items-center\">\n <!-- Mobile menu toggle, controls the 'mobileMenuOpen' state. -->\n <button type=\"button\" id=\"open-mobile-menu\" class=\"-ml-2 rounded-md p-2 pr-4 text-gray-400\">\n <span class=\"sr-only\">Open menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\" />\n </svg>\n </button>\n </div>\n\n <!-- Mobile menu mask -->\n <div id=\"mobile-menu-mask\" class=\"fixed inset-0 bg-black bg-opacity-40 z-40 hidden\"></div>\n <!-- Mobile menu drawer -->\n <div id=\"mobile-menu\" style=\"z-index: 10000\" class=\"fixed inset-0 bg-page shadow-lg transform translate-x-full transition-transform duration-200 ease-in-out flex flex-col\">\n <div class=\"flex items-center justify-between px-4 !h-[55px] border-b border-edge\">\n <router-link :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-[32px] text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n </router-link>\n <button type=\"button\" id=\"close-mobile-menu\" class=\"text-gray-400 p-2 rounded-md\">\n <span class=\"sr-only\">Close menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <nav class=\"flex-1 px-4 py-4 space-y-2\">\n <div class=\"flex items-center gap-2 px-3 py-2\" v-if=\"!user || !hasAPIKey\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode\"\n class=\"inline-flex items-center gap-2 rounded-md px-3 py-2 text-base font-medium text-content-secondary hover:bg-muted\"\n aria-label=\"Toggle dark mode\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n <span>{{ darkMode ? 'Light mode' : 'Dark mode' }}</span>\n </button>\n </div>\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"documentView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Documents</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Documents\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"dashboardView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Dashboards</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"chatView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Chat</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasTaskVisualizer\"\n href=\"#/tasks\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"taskView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Tasks</a>\n <div v-if=\"!user && hasAPIKey\" class=\"mt-4\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"w-full rounded bg-muted text-content px-3 py-2 text-base font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"mt-4\">\n <div class=\"flex items-center gap-3 px-3 py-2 bg-page rounded-md\">\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n <span class=\"text-content font-medium\">{{ user.name }}</span>\n </div>\n <div class=\"mt-2 space-y-1\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode\"\n class=\"w-full inline-flex items-center gap-2 px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle text-left\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n {{ darkMode ? 'Light mode' : 'Dark mode' }}\n </button>\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle\">Team</router-link>\n <span v-else class=\"block px-3 py-2 rounded-md text-base text-gray-300 cursor-not-allowed\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span @click=\"logout\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle cursor-pointer\">Sign out</span>\n </div>\n </div>\n </nav>\n </div>\n</div>\n";
51448
+
51449
+ /***/ },
51450
+
51451
+ /***/ "./frontend/src/pro-upgrade-modal/pro-upgrade-modal.html"
51452
+ /*!***************************************************************!*\
51453
+ !*** ./frontend/src/pro-upgrade-modal/pro-upgrade-modal.html ***!
51454
+ \***************************************************************/
51455
+ (module) {
51456
+
51457
+ "use strict";
51458
+ module.exports = "<modal v-if=\"show\" containerClass=\"!max-w-md\">\n <template v-slot:body>\n <div @keydown.esc=\"$emit('close')\" tabindex=\"0\" ref=\"overlay\">\n <div class=\"flex items-center justify-between mb-4\">\n <h3 class=\"text-lg font-semibold text-gray-900\">Pro Feature</h3>\n <button\n type=\"button\"\n @click=\"$emit('close')\"\n class=\"text-gray-400 hover:text-gray-600 cursor-pointer\"\n aria-label=\"Close\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <p class=\"text-gray-600 mb-6\">\n {{ featureDescription }} Upgrade to a Pro workspace to unlock this feature.\n </p>\n <div class=\"flex justify-end gap-3\">\n <button\n type=\"button\"\n @click=\"$emit('close')\"\n class=\"px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200 cursor-pointer\"\n >\n Cancel\n </button>\n <a\n href=\"https://studio.mongoosejs.io/pro\"\n target=\"_blank\"\n class=\"px-4 py-2 text-sm font-medium text-white bg-primary rounded-md hover:bg-primary-hover inline-flex items-center\"\n >\n Upgrade to Pro\n </a>\n </div>\n </div>\n </template>\n</modal>\n";
50760
51459
 
50761
51460
  /***/ },
50762
51461
 
@@ -50822,7 +51521,7 @@ module.exports = "";
50822
51521
  (module) {
50823
51522
 
50824
51523
  "use strict";
50825
- module.exports = "<div class=\"p-4 space-y-6\">\n <div>\n <h1 class=\"text-2xl font-bold text-content-secondary mb-4\">Task Overview</h1>\n <div v-if=\"status == 'init'\">\n <img src=\"images/loader.gif\" />\n </div>\n <!-- Task List -->\n <div class=\"bg-surface p-4 rounded-lg shadow\" v-if=\"status == 'loaded'\">\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Filter by Date:</label>\n <select v-model=\"selectedRange\" @change=\"updateDateRange\" class=\"border-edge-strong rounded-md shadow-sm w-full p-2\">\n <option v-for=\"option in dateFilters\" :key=\"option.value\" :value=\"option.value\">\n {{ option.label }}\n </option>\n </select>\n </div>\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Filter by Status:</label>\n <select v-model=\"selectedStatus\" @change=\"getTasks\" class=\"border-edge-strong rounded-md shadow-sm w-full p-2\">\n <option v-for=\"option in statusFilters\" :key=\"option.value\" :value=\"option.value\">\n {{ option.label }}\n </option>\n </select>\n </div>\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Search by Task Name:</label>\n <input \n v-model=\"searchQuery\" \n type=\"text\" \n @input=\"onSearchInput\"\n class=\"border-edge-strong rounded-md shadow-sm w-full p-2\"\n placeholder=\"Enter task name to search...\"\n >\n </div>\n <div class=\"mb-4\">\n <button\n @click=\"resetFilters\"\n class=\"w-full bg-gray-200 text-content-secondary hover:bg-gray-300 font-medium py-2 px-4 rounded-md transition\"\n >\n Reset Filters\n </button>\n </div>\n <div class=\"mb-6\">\n <button\n @click=\"openCreateTaskModal\"\n class=\"w-full bg-primary text-primary-text hover:bg-primary-hover font-medium py-2 px-4 rounded-md transition\"\n >\n Create New Task\n </button>\n </div>\n <!-- Summary Section -->\n <div class=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n <button \n @click=\"setStatusFilter('pending')\"\n :class=\"getStatusColor('pending') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-yellow-200 hover:border-yellow-300'\"\n >\n <div class=\"text-sm\">Scheduled</div>\n <div class=\"text-2xl font-bold\">{{pendingCount}}</div>\n </button>\n <button \n @click=\"setStatusFilter('succeeded')\"\n :class=\"getStatusColor('succeeded') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-green-200 hover:border-green-300'\"\n >\n <div class=\"text-sm\">Completed</div>\n <div class=\"text-2xl font-bold\">{{succeededCount}}</div>\n </button>\n <button \n @click=\"setStatusFilter('failed')\"\n :class=\"getStatusColor('failed') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-red-200 hover:border-red-300'\"\n >\n <div class=\"text-sm\">Failed</div>\n <div class=\"text-2xl font-bold\">{{failedCount}}</div>\n </button>\n <button \n @click=\"setStatusFilter('cancelled')\"\n :class=\"getStatusColor('cancelled') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-edge hover:border-edge-strong'\"\n >\n <div class=\"text-sm\">Cancelled</div>\n <div class=\"text-2xl font-bold\">{{cancelledCount}}</div>\n </button>\n </div>\n \n <!-- Grouped Task List -->\n <div class=\"mt-6\">\n <h2 class=\"text-lg font-semibold text-content-secondary mb-4\">Tasks by Name</h2>\n <ul class=\"divide-y divide-gray-200\">\n <li v-for=\"group in tasksByName\" :key=\"group.name\" class=\"p-4 group hover:border hover:rounded-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200\">\n <div class=\"flex items-center justify-between mb-3 \">\n <div class=\"flex-1 cursor-pointer\" @click=\"openTaskGroupDetails(group)\">\n <div class=\"flex items-center gap-2\">\n <div class=\"font-medium text-lg group-hover:text-primary transition-colors\">{{ group.name }}</div>\n <svg class=\"w-4 h-4 text-gray-400 group-hover:text-primary transition-colors\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\"></path>\n </svg>\n </div>\n <div class=\"text-sm text-content-tertiary group-hover:text-content-secondary transition-colors\">Total: {{ group.totalCount }} tasks</div>\n <div class=\"text-xs text-primary opacity-0 group-hover:opacity-100 transition-opacity mt-1\">\n Click to view details\n </div>\n </div>\n <div class=\"text-sm text-content-tertiary\">\n Last run: {{ group.lastRun ? new Date(group.lastRun).toLocaleString() : 'Never' }}\n </div>\n </div>\n \n <!-- Status Counts -->\n <div class=\"grid grid-cols-2 sm:grid-cols-4 gap-2\">\n <button \n @click.stop=\"openTaskGroupDetailsWithFilter(group, 'pending')\"\n class=\"bg-yellow-50 border border-yellow-200 rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-yellow-300\"\n >\n <div class=\"text-xs text-yellow-600 font-medium\">Pending</div>\n <div class=\"text-lg font-bold text-yellow-700\">{{ group.statusCounts.pending || 0 }}</div>\n </button>\n <button \n @click.stop=\"openTaskGroupDetailsWithFilter(group, 'succeeded')\"\n class=\"bg-green-50 border border-green-200 rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-green-300\"\n >\n <div class=\"text-xs text-green-600 font-medium\">Succeeded</div>\n <div class=\"text-lg font-bold text-green-700\">{{ group.statusCounts.succeeded || 0 }}</div>\n </button>\n <button \n @click.stop=\"openTaskGroupDetailsWithFilter(group, 'failed')\"\n class=\"bg-red-50 border border-red-200 rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-red-300\"\n >\n <div class=\"text-xs text-red-600 font-medium\">Failed</div>\n <div class=\"text-lg font-bold text-red-700\">{{ group.statusCounts.failed || 0 }}</div>\n </button>\n <button \n @click.stop=\"openTaskGroupDetailsWithFilter(group, 'cancelled')\"\n class=\"bg-page border border-edge rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-edge-strong\"\n >\n <div class=\"text-xs text-gray-600 font-medium\">Cancelled</div>\n <div class=\"text-lg font-bold text-content-secondary\">{{ group.statusCounts.cancelled || 0 }}</div>\n </button>\n </div>\n </li>\n </ul>\n </div>\n </div>\n </div>\n\n <!-- Create Task Modal -->\n <modal v-if=\"showCreateTaskModal\" containerClass=\"!h-[90vh] !w-[90vw]\">\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"closeCreateTaskModal\" role=\"button\" aria-label=\"Close modal\">&times;</div>\n <div class=\"space-y-4\">\n <h3 class=\"text-lg font-semibold text-content-secondary mb-4\">Create New Task</h3>\n \n <div>\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Task Name:</label>\n <input \n v-model=\"newTask.name\" \n type=\"text\" \n class=\"w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"Enter task name\"\n >\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Scheduled Time:</label>\n <input \n v-model=\"newTask.scheduledAt\" \n type=\"datetime-local\" \n class=\"w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Parameters (JSON):</label>\n <ace-editor\n v-model=\"newTask.parameters\"\n mode=\"json\"\n :line-numbers=\"true\"\n class=\"min-h-[120px]\"\n />\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Repeat Interval (ms):</label>\n <input \n v-model=\"newTask.repeatInterval\" \n type=\"number\" \n min=\"0\"\n step=\"1000\"\n class=\"w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"0 for no repetition\"\n >\n <p class=\"text-xs text-content-tertiary mt-1\">Enter 0 or leave empty for no repetition. Use 1000 for 1 second, 60000 for 1 minute, etc.</p>\n </div>\n \n <div class=\"flex gap-2 pt-4\">\n <button \n @click=\"createTask\" \n class=\"flex-1 bg-primary text-primary-text px-4 py-2 rounded-md hover:bg-primary-hover\"\n >\n Create Task\n </button>\n <button \n @click=\"closeCreateTaskModal\" \n class=\"flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400\"\n >\n Cancel\n </button>\n </div>\n </div>\n </template>\n </modal>\n</div>\n";
51524
+ module.exports = "<div class=\"p-4 space-y-6\">\n <div>\n <h1 class=\"text-2xl font-bold text-content-secondary mb-4\">Task Overview</h1>\n <div v-if=\"status == 'init'\">\n <img src=\"images/loader.gif\" />\n </div>\n <!-- Task List -->\n <div class=\"bg-surface p-4 rounded-lg shadow\" v-if=\"status == 'loaded'\">\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Filter by Date:</label>\n <select v-model=\"selectedRange\" @change=\"updateDateRange\" class=\"border-edge-strong rounded-md shadow-sm w-full p-2\">\n <option v-for=\"option in dateFilters\" :key=\"option.value\" :value=\"option.value\">\n {{ option.label }}\n </option>\n </select>\n </div>\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Filter by Status:</label>\n <select v-model=\"selectedStatus\" @change=\"getTasks\" class=\"border-edge-strong rounded-md shadow-sm w-full p-2\">\n <option v-for=\"option in statusFilters\" :key=\"option.value\" :value=\"option.value\">\n {{ option.label }}\n </option>\n </select>\n </div>\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Search by Task Name:</label>\n <input \n v-model=\"searchQuery\" \n type=\"text\" \n @input=\"onSearchInput\"\n class=\"border-edge-strong rounded-md shadow-sm w-full p-2\"\n placeholder=\"Enter task name to search...\"\n >\n </div>\n <div class=\"mb-4\">\n <button\n @click=\"resetFilters\"\n class=\"w-full bg-gray-200 text-content-secondary hover:bg-gray-300 font-medium py-2 px-4 rounded-md transition\"\n >\n Reset Filters\n </button>\n </div>\n <div class=\"mb-6\">\n <button\n @click=\"openCreateTaskModal\"\n class=\"w-full bg-primary text-primary-text hover:bg-primary-hover font-medium py-2 px-4 rounded-md transition\"\n >\n Create New Task\n </button>\n </div>\n <!-- Summary Section -->\n <div class=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n <button \n @click=\"setStatusFilter('pending')\"\n :class=\"getStatusColor('pending') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-yellow-200 hover:border-yellow-300'\"\n >\n <div class=\"text-sm\">Scheduled</div>\n <div class=\"text-2xl font-bold\">{{pendingCount}}</div>\n </button>\n <button \n @click=\"setStatusFilter('succeeded')\"\n :class=\"getStatusColor('succeeded') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-green-200 hover:border-green-300'\"\n >\n <div class=\"text-sm\">Completed</div>\n <div class=\"text-2xl font-bold\">{{succeededCount}}</div>\n </button>\n <button \n @click=\"setStatusFilter('failed')\"\n :class=\"getStatusColor('failed') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-red-200 hover:border-red-300'\"\n >\n <div class=\"text-sm\">Failed</div>\n <div class=\"text-2xl font-bold\">{{failedCount}}</div>\n </button>\n <button \n @click=\"setStatusFilter('cancelled')\"\n :class=\"getStatusColor('cancelled') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-edge hover:border-edge-strong'\"\n >\n <div class=\"text-sm\">Cancelled</div>\n <div class=\"text-2xl font-bold\">{{cancelledCount}}</div>\n </button>\n </div>\n\n <!-- Tasks Over Time Chart -->\n <!--\n Canvas is gated by showOverTimeChart (v-if) so Chart.js is destroyed\n and the DOM node is removed before each refresh. In-place Chart.js\n updates during Vue re-renders from filter changes could freeze the UI\n (dropdowns stuck, chart not updating). See tasks.js getTasks().\n -->\n <div class=\"mt-6\">\n <h2 class=\"text-lg font-semibold text-content-secondary mb-3\">Tasks Over Time</h2>\n <div class=\"bg-page border border-edge rounded-lg p-4\" style=\"height: 260px;\">\n <canvas v-if=\"showOverTimeChart && overTimeBuckets.length > 0\" ref=\"overTimeChart\" style=\"width:100%;height:100%;\"></canvas>\n <div v-else class=\"flex items-center justify-center h-full text-content-tertiary text-sm\">\n No task activity in the selected window\n </div>\n </div>\n </div>\n \n <!-- Grouped Task List -->\n <div class=\"mt-6\">\n <h2 class=\"text-lg font-semibold text-content-secondary mb-4\">Tasks by Name</h2>\n <div class=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n <div v-for=\"group in tasksByName\" :key=\"group.name\" class=\"border border-edge rounded-lg p-4 group hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200\">\n <div class=\"flex items-start justify-between mb-3\">\n <div class=\"flex-1 cursor-pointer min-w-0 mr-2\" @click=\"openTaskGroupDetails(group)\">\n <div class=\"flex items-center gap-1\">\n <div class=\"font-medium text-sm group-hover:text-primary transition-colors truncate\">{{ group.name }}</div>\n <svg class=\"w-3 h-3 text-gray-400 group-hover:text-primary transition-colors flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\"></path>\n </svg>\n </div>\n <div class=\"text-xs text-content-tertiary\">Total: {{ group.totalCount }} tasks</div>\n </div>\n <div class=\"text-xs text-content-tertiary flex-shrink-0\">\n {{ group.lastRun ? new Date(group.lastRun).toLocaleString() : 'Never' }}\n </div>\n </div>\n \n <!-- Status Counts -->\n <div class=\"grid grid-cols-2 gap-1.5\">\n <button \n @click.stop=\"openTaskGroupDetailsWithFilter(group, 'pending')\"\n class=\"bg-yellow-50 border border-yellow-200 rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-yellow-300\"\n >\n <div class=\"text-xs text-yellow-600 font-medium\">Pending</div>\n <div class=\"text-base font-bold text-yellow-700\">{{ group.statusCounts.pending || 0 }}</div>\n </button>\n <button \n @click.stop=\"openTaskGroupDetailsWithFilter(group, 'succeeded')\"\n class=\"bg-green-50 border border-green-200 rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-green-300\"\n >\n <div class=\"text-xs text-green-600 font-medium\">Succeeded</div>\n <div class=\"text-base font-bold text-green-700\">{{ group.statusCounts.succeeded || 0 }}</div>\n </button>\n <button \n @click.stop=\"openTaskGroupDetailsWithFilter(group, 'failed')\"\n class=\"bg-red-50 border border-red-200 rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-red-300\"\n >\n <div class=\"text-xs text-red-600 font-medium\">Failed</div>\n <div class=\"text-base font-bold text-red-700\">{{ group.statusCounts.failed || 0 }}</div>\n </button>\n <button \n @click.stop=\"openTaskGroupDetailsWithFilter(group, 'cancelled')\"\n class=\"bg-page border border-edge rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-edge-strong\"\n >\n <div class=\"text-xs text-gray-600 font-medium\">Cancelled</div>\n <div class=\"text-base font-bold text-content-secondary\">{{ group.statusCounts.cancelled || 0 }}</div>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Create Task Modal -->\n <modal v-if=\"showCreateTaskModal\" containerClass=\"!h-[90vh] !w-[90vw]\">\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"closeCreateTaskModal\" role=\"button\" aria-label=\"Close modal\">&times;</div>\n <div class=\"space-y-4\">\n <h3 class=\"text-lg font-semibold text-content-secondary mb-4\">Create New Task</h3>\n \n <div>\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Task Name:</label>\n <input \n v-model=\"newTask.name\" \n type=\"text\" \n class=\"w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"Enter task name\"\n >\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Scheduled Time:</label>\n <input \n v-model=\"newTask.scheduledAt\" \n type=\"datetime-local\" \n class=\"w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Parameters (JSON):</label>\n <ace-editor\n v-model=\"newTask.parameters\"\n mode=\"json\"\n :line-numbers=\"true\"\n class=\"min-h-[120px]\"\n />\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-content-secondary mb-1\">Repeat Interval (ms):</label>\n <input \n v-model=\"newTask.repeatInterval\" \n type=\"number\" \n min=\"0\"\n step=\"1000\"\n class=\"w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"0 for no repetition\"\n >\n <p class=\"text-xs text-content-tertiary mt-1\">Enter 0 or leave empty for no repetition. Use 1000 for 1 second, 60000 for 1 minute, etc.</p>\n </div>\n \n <div class=\"flex gap-2 pt-4\">\n <button \n @click=\"createTask\" \n class=\"flex-1 bg-primary text-primary-text px-4 py-2 rounded-md hover:bg-primary-hover\"\n >\n Create Task\n </button>\n <button \n @click=\"closeCreateTaskModal\" \n class=\"flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400\"\n >\n Cancel\n </button>\n </div>\n </div>\n </template>\n </modal>\n</div>\n";
50826
51525
 
50827
51526
  /***/ },
50828
51527
 
@@ -62136,7 +62835,7 @@ var src_default = VueToastificationPlugin;
62136
62835
  (module) {
62137
62836
 
62138
62837
  "use strict";
62139
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.3.5","description":"A Mongoose-native MongoDB UI with schema-aware autocomplete, AI-assisted queries, and dashboards that understand your models - not just your data.","homepage":"https://mongoosestudio.app/","repository":{"type":"git","url":"https://github.com/mongoosejs/studio"},"license":"Apache-2.0","dependencies":{"@ai-sdk/anthropic":"2.x","@ai-sdk/google":"2.x","@ai-sdk/openai":"2.x","ace-builds":"^1.43.6","ai":"5.x","archetype":"0.13.1","csv-stringify":"6.3.0","ejson":"^2.2.3","extrovert":"^0.2.0","marked":"15.0.12","node-inspect-extracted":"3.x","regexp.escape":"^2.0.1","tailwindcss":"3.4.0","vue":"3.x","vue-toastification":"^2.0.0-rc.5","webpack":"5.x","xss":"^1.0.15"},"peerDependencies":{"mongoose":"7.x || 8.x || ^9.0.0"},"optionalPeerDependencies":{"@mongoosejs/task":"0.5.x || 0.6.x"},"devDependencies":{"@masteringjs/eslint-config":"0.1.1","axios":"1.2.2","dedent":"^1.6.0","eslint":"9.30.0","express":"4.x","mocha":"10.2.0","mongodb-memory-server":"^11.0.1","mongoose":"9.x","sinon":"^21.0.1"},"scripts":{"lint":"eslint .","seed":"node seed/index.js","start":"node ./local.js","tailwind":"tailwindcss -o ./frontend/public/tw.css","tailwind:watch":"tailwindcss -o ./frontend/public/tw.css --watch","test":"mocha test/*.test.js","test:frontend":"mocha test/frontend/*.test.js"}}');
62838
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.3.7","description":"A Mongoose-native MongoDB UI with schema-aware autocomplete, AI-assisted queries, and dashboards that understand your models - not just your data.","homepage":"https://mongoosestudio.app/","repository":{"type":"git","url":"https://github.com/mongoosejs/studio"},"license":"Apache-2.0","dependencies":{"@ai-sdk/anthropic":"2.x","@ai-sdk/google":"2.x","@ai-sdk/openai":"2.x","ace-builds":"^1.43.6","ai":"5.x","archetype":"0.13.1","csv-stringify":"6.3.0","ejson":"^2.2.3","extrovert":"^0.2.0","marked":"15.0.12","node-inspect-extracted":"3.x","regexp.escape":"^2.0.1","tailwindcss":"3.4.0","vue":"3.x","vue-toastification":"^2.0.0-rc.5","webpack":"5.x","time-commando":"1.0.1","xss":"^1.0.15"},"peerDependencies":{"mongoose":"7.x || 8.x || ^9.0.0"},"optionalPeerDependencies":{"@mongoosejs/task":"0.5.x || 0.6.x"},"devDependencies":{"@masteringjs/eslint-config":"0.1.1","axios":"1.2.2","dedent":"^1.6.0","eslint":"9.30.0","express":"4.x","mocha":"10.2.0","mongodb-memory-server":"^11.0.1","mongoose":"9.x","sinon":"^21.0.1"},"scripts":{"lint":"eslint .","seed":"node seed/index.js","start":"node ./local.js","tailwind":"tailwindcss -o ./frontend/public/tw.css","tailwind:watch":"tailwindcss -o ./frontend/public/tw.css --watch","test":"mocha test/*.test.js","test:frontend":"mocha test/frontend/*.test.js"}}');
62140
62839
 
62141
62840
  /***/ }
62142
62841