@mongoosejs/studio 0.0.96 → 0.0.97

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.
@@ -500,6 +500,11 @@ module.exports = app => app.component('chat', {
500
500
  this.chatMessages.push(chatMessages[1]);
501
501
 
502
502
  this.newMessage = '';
503
+ this.$nextTick(() => {
504
+ if (this.$refs.messageInput) {
505
+ this.$refs.messageInput.style.height = 'auto';
506
+ }
507
+ });
503
508
 
504
509
  this.$nextTick(() => {
505
510
  if (this.$refs.messagesContainer) {
@@ -510,6 +515,18 @@ module.exports = app => app.component('chat', {
510
515
  this.sendingMessage = false;
511
516
  }
512
517
  },
518
+ handleEnter(ev) {
519
+ if (!ev.shiftKey) {
520
+ this.sendMessage();
521
+ }
522
+ },
523
+ adjustTextareaHeight(ev) {
524
+ const textarea = ev.target;
525
+ textarea.style.height = 'auto';
526
+ const lineHeight = parseInt(window.getComputedStyle(textarea).lineHeight, 10);
527
+ const maxHeight = lineHeight * 5;
528
+ textarea.style.height = Math.min(textarea.scrollHeight, maxHeight) + 'px';
529
+ },
513
530
  selectThread(threadId) {
514
531
  this.$router.push('/chat/' + threadId);
515
532
  },
@@ -1756,6 +1773,7 @@ if (typeof process === 'undefined') {
1756
1773
 
1757
1774
  const api = __webpack_require__(/*! ./api */ "./frontend/src/api.js");
1758
1775
  const mothership = __webpack_require__(/*! ./mothership */ "./frontend/src/mothership.js");
1776
+ const { routes } = __webpack_require__(/*! ./routes */ "./frontend/src/routes.js");
1759
1777
  const vanillatoasts = __webpack_require__(/*! vanillatoasts */ "./node_modules/vanillatoasts/vanillatoasts.js");
1760
1778
 
1761
1779
  const app = Vue.createApp({
@@ -1814,7 +1832,7 @@ app.component('app-component', {
1814
1832
  window.state = this;
1815
1833
 
1816
1834
  if (mothership.hasAPIKey) {
1817
- const hash = window.location.hash.replace(/^#?\/?\??/, '') || '';
1835
+ const hash = window.location.hash.replace(/^#?\/?/, '') || '';
1818
1836
  const hashQuery = hash.split('?')[1] || '';
1819
1837
  const hashParams = new URLSearchParams(hashQuery);
1820
1838
  if (hashParams.has('code')) {
@@ -1857,6 +1875,7 @@ app.component('app-component', {
1857
1875
  const { nodeEnv } = await api.status();
1858
1876
  this.nodeEnv = nodeEnv;
1859
1877
  }
1878
+
1860
1879
  this.status = 'loaded';
1861
1880
  },
1862
1881
  setup() {
@@ -1873,7 +1892,6 @@ app.component('app-component', {
1873
1892
  }
1874
1893
  });
1875
1894
 
1876
- const { routes } = __webpack_require__(/*! ./routes */ "./frontend/src/routes.js");
1877
1895
  const router = VueRouter.createRouter({
1878
1896
  history: VueRouter.createWebHashHistory(),
1879
1897
  routes: routes.map(route => ({
@@ -1883,6 +1901,14 @@ const router = VueRouter.createRouter({
1883
1901
  }))
1884
1902
  });
1885
1903
 
1904
+ router.beforeEach((to, from, next) => {
1905
+ if (to.name === 'root' && window.state.roles && window.state.roles[0] === 'dashboards') {
1906
+ return next({ name: 'dashboards' });
1907
+ } else {
1908
+ next();
1909
+ }
1910
+ });
1911
+
1886
1912
  app.use(router);
1887
1913
 
1888
1914
  app.mount('#content');
@@ -2693,14 +2719,6 @@ module.exports = app => app.component('navbar', {
2693
2719
  inject: ['state'],
2694
2720
  data: () => ({ showFlyout: false }),
2695
2721
  mounted: function() {
2696
- // Redirect to first allowed route if current route is not allowed
2697
- if (!this.hasAccess(this.roles, this.$route.name)) {
2698
- const firstAllowedRoute = this.allowedRoutes[0];
2699
- if (firstAllowedRoute) {
2700
- this.$router.push({ name: firstAllowedRoute.name });
2701
- }
2702
- }
2703
-
2704
2722
  const mobileMenuMask = document.querySelector('#mobile-menu-mask');
2705
2723
  const mobileMenu = document.querySelector('#mobile-menu');
2706
2724
 
@@ -2739,11 +2757,8 @@ module.exports = app => app.component('navbar', {
2739
2757
  canViewTeam() {
2740
2758
  return this.hasAccess(this.roles, 'team');
2741
2759
  },
2742
- allowedRoutes() {
2743
- return routes.filter(route => this.hasAccess(this.roles, route.name));
2744
- },
2745
2760
  defaultRoute() {
2746
- return this.allowedRoutes[0]?.name || 'dashboards';
2761
+ return this.roles && this.roles[0] === 'dashboards' ? 'dashboards' : 'root';
2747
2762
  }
2748
2763
  },
2749
2764
  methods: {
@@ -2804,10 +2819,12 @@ const roleAccess = {
2804
2819
  dashboards: ['dashboards', 'dashboard']
2805
2820
  };
2806
2821
 
2822
+ const allowedRoutesForLocalDev = ['document', 'root', 'chat'];
2823
+
2807
2824
  // Helper function to check if a role has access to a route
2808
2825
  function hasAccess(roles, routeName) {
2809
2826
  // change to true for local development
2810
- if (!roles) return false;
2827
+ if (!roles) return allowedRoutesForLocalDev.includes(routeName);
2811
2828
  return roles.some(role => roleAccess[role]?.includes(routeName));
2812
2829
  }
2813
2830
 
@@ -3897,7 +3914,7 @@ module.exports = "<button v-bind=\"attrsToBind\" :disabled=\"isDisabled\" @click
3897
3914
  /***/ ((module) => {
3898
3915
 
3899
3916
  "use strict";
3900
- module.exports = "<div class=\"relative border rounded bg-gray-100 text-black text-sm overflow-hidden\">\n <div class=\"flex border-b pt-[1px] text-xs font-medium bg-gray-200\">\n <button\n class=\"px-3 py-1 border-r border-gray-300 hover:bg-green-300\"\n :class=\"{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-3 py-1 hover:bg-green-300\"\n :class=\"{'bg-green-300': activeTab === 'output'}\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex\">\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-500 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center\"\n @click=\"copyOutput\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-blue-500 text-white border-none rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 1v4m0 0h-4m4 0l-5-5\" />\n </svg>\n </button>\n <async-button\n class=\"px-2 py-1 text-xs bg-green-500 text-white border-none rounded cursor-pointer hover:bg-green-600 transition-colors disabled:bg-gray-400\"\n @click=\"executeScript(message, script)\">\n Execute\n </async-button>\n </div>\n </div>\n\n <pre class=\"p-3 whitespace-pre-wrap max-h-[30vh] max-w-[calc(100vw-4rem)] overflow-y-auto\" v-show=\"activeTab === 'code'\"><code v-text=\"script\" ref=\"code\" :class=\"'language-' + language\"></code></pre>\n\n <div class=\"p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t max-w-[calc(100vw-4rem)] relative\" v-show=\"activeTab === 'output'\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else>{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n\n <modal ref=\"outputModal\" v-if=\"showDetailModal\" containerClass=\"!h-[90vh] !w-[90vw]\">\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"showDetailModal = false;\">&times;</div>\n <div class=\"h-full overflow-auto\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else class=\"whitespace-pre-wrap\">{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n </template>\n </modal>\n</div>\n";
3917
+ module.exports = "<div class=\"relative border rounded bg-gray-100 text-black text-sm overflow-hidden\">\n <div class=\"flex border-b pt-[1px] text-xs font-medium bg-gray-200\">\n <button\n class=\"px-3 py-1 border-r border-gray-300 hover:bg-green-300\"\n :class=\"{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-3 py-1 hover:bg-green-300\"\n :class=\"{'bg-green-300': activeTab === 'output'}\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex\">\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-500 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center\"\n @click=\"copyOutput\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-blue-500 text-white border-none rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 1v4m0 0h-4m4 0l-5-5\" />\n </svg>\n </button>\n <async-button\n class=\"px-2 py-1 text-xs bg-green-500 text-white border-none rounded cursor-pointer hover:bg-green-600 transition-colors disabled:bg-gray-400\"\n @click=\"executeScript(message, script)\">\n Execute\n </async-button>\n </div>\n </div>\n\n <pre class=\"p-3 whitespace-pre-wrap max-h-[50vh] max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] overflow-y-auto\" v-show=\"activeTab === 'code'\"><code v-text=\"script\" ref=\"code\" :class=\"'language-' + language\"></code></pre>\n\n <div class=\"p-3 whitespace-pre-wrap max-h-[50vh] overflow-y-auto bg-white border-t max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] relative\" v-show=\"activeTab === 'output'\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else>{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n\n <modal ref=\"outputModal\" v-if=\"showDetailModal\" containerClass=\"!h-[90vh] !w-[90vw]\">\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"showDetailModal = false;\">&times;</div>\n <div class=\"h-full overflow-auto\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else class=\"whitespace-pre-wrap\">{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n </template>\n </modal>\n</div>\n";
3901
3918
 
3902
3919
  /***/ }),
3903
3920
 
@@ -3908,7 +3925,7 @@ module.exports = "<div class=\"relative border rounded bg-gray-100 text-black te
3908
3925
  /***/ ((module) => {
3909
3926
 
3910
3927
  "use strict";
3911
- module.exports = "<div class=\"relative flex items-start space-x-3\" :class=\"{'justify-end': message.role === 'user'}\">\n <div\n class=\"min-w-0 max-w-[calc(100vw-4rem)]\"\n :class=\"{'text-right': message.role === 'user'}\">\n\n <div class=\"text-sm text-gray-900 p-3 rounded-md inline-block\" :class=\"styleForMessage\">\n <div v-for=\"part in contentSplitByScripts\">\n <div v-if=\"part.type === 'text'\" v-html=\"marked(part.content)\">\n </div>\n <div v-else-if=\"part.type === 'code'\">\n <chat-message-script :message=\"message\" :script=\"part.content\" :language=\"part.language\"></chat-message-script>\n </div>\n </div>\n </div>\n </div>\n</div>\n";
3928
+ module.exports = "<div class=\"relative flex items-start\" :class=\"{'justify-end': message.role === 'user'}\">\n <div\n class=\"min-w-0 max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)]\"\n :class=\"{'text-right': message.role === 'user'}\">\n\n <div class=\"text-sm text-gray-900 md:p-3 rounded-md inline-block\" :class=\"styleForMessage\">\n <div v-for=\"part in contentSplitByScripts\">\n <div v-if=\"part.type === 'text'\" v-html=\"marked(part.content)\">\n </div>\n <div v-else-if=\"part.type === 'code'\">\n <chat-message-script :message=\"message\" :script=\"part.content\" :language=\"part.language\"></chat-message-script>\n </div>\n </div>\n </div>\n </div>\n</div>\n";
3912
3929
 
3913
3930
  /***/ }),
3914
3931
 
@@ -3919,7 +3936,7 @@ module.exports = "<div class=\"relative flex items-start space-x-3\" :class=\"{'
3919
3936
  /***/ ((module) => {
3920
3937
 
3921
3938
  "use strict";
3922
- module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px)\">\n <div class=\"fixed top-[65px] cursor-pointer bg-gray-100 rounded-r-md z-10\" @click=\"hideSidebar = false\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"h-5 w-5\" viewBox=\"0 -960 960 960\" width=\"24px\" fill=\"#5f6368\"><path d=\"M360-120v-720h80v720h-80Zm160-160v-400l200 200-200 200Z\"/></svg>\n </div>\n <!-- Sidebar: Chat Threads -->\n <aside class=\"bg-gray-50 border-r overflow-y-auto overflow-x-hidden h-full transition-all duration-300 ease-in-out z-20 w-0 md:w-64 fixed md:relative\" :class=\"hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''\">\n <div class=\"flex items-center border-b border-gray-100 w-64 overflow-x-hidden\">\n <div class=\"p-4 font-bold text-lg\">Chat Threads</div>\n <button\n @click=\"hideSidebar = true\"\n class=\"ml-auto mr-2 p-2 rounded hover:bg-gray-200 focus:outline-none\"\n aria-label=\"Close sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"h-5 w-5\" viewBox=\"0 -960 960 960\" width=\"24px\" fill=\"currentColor\"><path d=\"M660-320v-320L500-480l160 160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm120-80v-560H200v560h120Zm80 0h360v-560H400v560Zm-80 0H200h120Z\"/></svg>\n </button>\n </div>\n <div class=\"p-4 w-64\">\n <async-button\n @click=\"createNewThread\"\n class=\"w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700\"\n >\n Create New Thread\n </async-button>\n </div>\n <div v-if=\"status === 'loaded' && chatThreads.length === 0\" class=\"p-4 text-sm text-gray-700\">\n No threads yet\n </div>\n <ul v-if=\"status === 'loaded'\" class=\"w-64\">\n <li\n v-for=\"thread in chatThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"p-4 hover:bg-gray-200 cursor-pointer w-64\"\n :class=\"{ 'bg-gray-300': thread._id === chatThreadId }\"\n >\n {{ thread.title || 'Untitled Thread' }}\n </li>\n </ul>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <ul role=\"list\" class=\"space-y-4\">\n <div v-if=\"true\">\n <div class=\"flex items-center justify-center py-3 mb-4\">\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n <p class=\"mx-4 text-sm font-medium text-gray-500\">This is the beginning of the message thread</p>\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n </div>\n </div>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\"></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\">\n <input\n v-model=\"newMessage\"\n placeholder=\"Ask something...\"\n class=\"flex-1 border rounded px-4 py-2\"\n />\n <button class=\"bg-blue-600 text-white px-4 py-2 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";
3939
+ module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px)\">\n <div class=\"fixed top-[65px] cursor-pointer bg-gray-100 rounded-r-md z-10\" @click=\"hideSidebar = false\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"h-5 w-5\" viewBox=\"0 -960 960 960\" class=\"w-5\" fill=\"#5f6368\"><path d=\"M360-120v-720h80v720h-80Zm160-160v-400l200 200-200 200Z\"/></svg>\n </div>\n <!-- Sidebar: Chat Threads -->\n <aside class=\"bg-gray-50 border-r overflow-y-auto overflow-x-hidden h-full transition-all duration-300 ease-in-out z-20 w-0 lg:w-64 fixed lg:relative\" :class=\"hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''\">\n <div class=\"flex items-center border-b border-gray-100 w-64 overflow-x-hidden\">\n <div class=\"p-4 font-bold text-lg\">Chat Threads</div>\n <button\n @click=\"hideSidebar = true\"\n class=\"ml-auto mr-2 p-2 rounded hover:bg-gray-200 focus:outline-none\"\n aria-label=\"Close sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"h-5 w-5\" viewBox=\"0 -960 960 960\" class=\"w-5\" fill=\"currentColor\"><path d=\"M660-320v-320L500-480l160 160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm120-80v-560H200v560h120Zm80 0h360v-560H400v560Zm-80 0H200h120Z\"/></svg>\n </button>\n </div>\n <div class=\"p-4 w-64\">\n <async-button\n @click=\"createNewThread\"\n class=\"w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700\"\n >\n Create New Thread\n </async-button>\n </div>\n <div v-if=\"status === 'loaded' && chatThreads.length === 0\" class=\"p-4 text-sm text-gray-700\">\n No threads yet\n </div>\n <ul v-if=\"status === 'loaded'\" class=\"w-64\">\n <li\n v-for=\"thread in chatThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"p-4 hover:bg-gray-200 cursor-pointer w-64\"\n :class=\"{ 'bg-gray-300': thread._id === chatThreadId }\"\n >\n {{ thread.title || 'Untitled Thread' }}\n </li>\n </ul>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <ul role=\"list\" class=\"space-y-4\">\n <div v-if=\"true\">\n <div class=\"flex items-center justify-center py-3 mb-4\">\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n <p class=\"mx-4 text-sm font-medium text-gray-500\">This is the beginning of the message thread</p>\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n </div>\n </div>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\"></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=\"Ask something...\"\n class=\"flex-1 border rounded px-4 py-2 resize-none overflow-y-auto\"\n rows=\"1\"\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";
3923
3940
 
3924
3941
  /***/ }),
3925
3942
 
@@ -4458,7 +4475,7 @@ module.exports = ".active {\n text-decoration: underline;\n}\n\n.navbar .nav-le
4458
4475
  /***/ ((module) => {
4459
4476
 
4460
4477
  "use strict";
4461
- module.exports = "<div class=\"navbar w-full bg-gray-50 flex justify-between border-b border-gray-200 !h-[55px]\">\n <div class=\"flex items-center gap-4 h-full pl-4\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" class=\"h-[32px] mr-1\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <div v-if=\"!!state.nodeEnv\" class=\"inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900\" :class=\"warnEnv ? 'bg-red-300' : 'bg-yellow-300'\">\n {{state.nodeEnv}}\n </div>\n </div>\n <div class=\"h-full pr-4 hidden md:block\">\n <div class=\"sm:ml-6 sm:flex sm:space-x-8 h-full\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Documents</a>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"dashboardView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Dashboards</a>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"chatView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Chat</a>\n\n <div class=\"h-full flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"h-full flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <div>\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\" 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 </div>\n\n <div v-if=\"showFlyout\" class=\"absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"user-menu-button\" tabindex=\"-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n\n </div>\n </div>\n <div class=\"md:hidden 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\" class=\"fixed inset-0 bg-white shadow-lg z-50 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-gray-200\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" class=\"h-[32px]\" alt=\"Mongoose Studio Logo\" />\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 <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-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Documents</a>\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-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Dashboards</a>\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-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Chat</a>\n <div v-if=\"!user && hasAPIKey\" class=\"mt-4\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"w-full rounded bg-ultramarine-600 px-3 py-2 text-base font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\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-gray-50 rounded-md\">\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n <span class=\"text-gray-900 font-medium\">{{ user.name }}</span>\n </div>\n <div class=\"mt-2 space-y-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" class=\"block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100\">Team</router-link>\n <span @click=\"logout\" class=\"block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100 cursor-pointer\">Sign out</span>\n </div>\n </div>\n </nav>\n </div>\n</div>\n";
4478
+ module.exports = "<div class=\"navbar w-full bg-gray-50 flex justify-between border-b border-gray-200 !h-[55px]\">\n <div class=\"flex items-center gap-4 h-full pl-4\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" class=\"h-[32px] mr-1\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <div v-if=\"!!state.nodeEnv\" title=\"NODE_ENV\" class=\"inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900\" :class=\"warnEnv ? 'bg-red-300' : 'bg-yellow-300'\">\n {{state.nodeEnv}}\n </div>\n </div>\n <div class=\"h-full pr-4 hidden md:block\">\n <div class=\"sm:ml-6 sm:flex sm:space-x-8 h-full\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Documents</a>\n <span v-else class=\"inline-flex items-center px-1 pt-1 border-b-2 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 border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"dashboardView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Dashboards</a>\n <span v-else class=\"inline-flex items-center border-b-2 px-1 pt-1 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 border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"chatView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Chat</a>\n <span v-else class=\"inline-flex items-center border-b-2 px-1 pt-1 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\n <div class=\"h-full flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"h-full flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <div>\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\" 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 </div>\n\n <div v-if=\"showFlyout\" class=\"absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"user-menu-button\" tabindex=\"-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" 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-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n\n </div>\n </div>\n <div class=\"md:hidden 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\" class=\"fixed inset-0 bg-white shadow-lg z-50 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-gray-200\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" class=\"h-[32px]\" alt=\"Mongoose Studio Logo\" />\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 <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-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">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-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">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-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">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-ultramarine-600 px-3 py-2 text-base font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\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-gray-50 rounded-md\">\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n <span class=\"text-gray-900 font-medium\">{{ user.name }}</span>\n </div>\n <div class=\"mt-2 space-y-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" class=\"block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100\">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-gray-700 hover:bg-ultramarine-100 cursor-pointer\">Sign out</span>\n </div>\n </div>\n </nav>\n </div>\n</div>\n";
4462
4479
 
4463
4480
  /***/ }),
4464
4481
 
@@ -618,11 +618,6 @@ video {
618
618
  inset: 0px;
619
619
  }
620
620
 
621
- .inset-x-0 {
622
- left: 0px;
623
- right: 0px;
624
- }
625
-
626
621
  .right-0 {
627
622
  right: 0px;
628
623
  }
@@ -635,52 +630,12 @@ video {
635
630
  top: 0.25rem;
636
631
  }
637
632
 
638
- .top-\[90\%\] {
639
- top: 90%;
640
- }
641
-
642
- .bottom-0 {
643
- bottom: 0px;
644
- }
645
-
646
- .top-1\/2 {
647
- top: 50%;
648
- }
649
-
650
- .top-full {
651
- top: 100%;
652
- }
653
-
654
- .top-0 {
655
- top: 0px;
656
- }
657
-
658
- .top-\[100px\] {
659
- top: 100px;
660
- }
661
-
662
- .top-\[80px\] {
663
- top: 80px;
664
- }
665
-
666
- .top-\[60px\] {
667
- top: 60px;
668
- }
669
-
670
633
  .top-\[65px\] {
671
634
  top: 65px;
672
635
  }
673
636
 
674
- .top-\[70px\] {
675
- top: 70px;
676
- }
677
-
678
- .left-0 {
679
- left: 0px;
680
- }
681
-
682
- .top-\[55px\] {
683
- top: 55px;
637
+ .top-\[90\%\] {
638
+ top: 90%;
684
639
  }
685
640
 
686
641
  .isolate {
@@ -691,6 +646,10 @@ video {
691
646
  z-index: 10;
692
647
  }
693
648
 
649
+ .z-20 {
650
+ z-index: 20;
651
+ }
652
+
694
653
  .z-40 {
695
654
  z-index: 40;
696
655
  }
@@ -699,14 +658,6 @@ video {
699
658
  z-index: 50;
700
659
  }
701
660
 
702
- .z-20 {
703
- z-index: 20;
704
- }
705
-
706
- .z-30 {
707
- z-index: 30;
708
- }
709
-
710
661
  .col-start-1 {
711
662
  grid-column-start: 1;
712
663
  }
@@ -719,10 +670,6 @@ video {
719
670
  margin: 0px;
720
671
  }
721
672
 
722
- .-m-2 {
723
- margin: -0.5rem;
724
- }
725
-
726
673
  .-mx-4 {
727
674
  margin-left: -1rem;
728
675
  margin-right: -1rem;
@@ -756,6 +703,10 @@ video {
756
703
  margin-left: -0.125rem;
757
704
  }
758
705
 
706
+ .-ml-2 {
707
+ margin-left: -0.5rem;
708
+ }
709
+
759
710
  .-ml-px {
760
711
  margin-left: -1px;
761
712
  }
@@ -828,14 +779,6 @@ video {
828
779
  margin-top: 2rem;
829
780
  }
830
781
 
831
- .-ml-2 {
832
- margin-left: -0.5rem;
833
- }
834
-
835
- .-ml-4 {
836
- margin-left: -1rem;
837
- }
838
-
839
782
  .block {
840
783
  display: block;
841
784
  }
@@ -887,6 +830,10 @@ video {
887
830
  height: 2rem;
888
831
  }
889
832
 
833
+ .\!h-\[55px\] {
834
+ height: 55px !important;
835
+ }
836
+
890
837
  .\!h-\[90vh\] {
891
838
  height: 90vh !important;
892
839
  }
@@ -911,6 +858,10 @@ video {
911
858
  height: 1.25rem;
912
859
  }
913
860
 
861
+ .h-6 {
862
+ height: 1.5rem;
863
+ }
864
+
914
865
  .h-8 {
915
866
  height: 2rem;
916
867
  }
@@ -943,32 +894,12 @@ video {
943
894
  height: 1px;
944
895
  }
945
896
 
946
- .\!h-\[55px\] {
947
- height: 55px !important;
948
- }
949
-
950
- .h-6 {
951
- height: 1.5rem;
952
- }
953
-
954
- .h-0 {
955
- height: 0px;
956
- }
957
-
958
- .h-0\.5 {
959
- height: 0.125rem;
960
- }
961
-
962
- .h-\[170px\] {
963
- height: 170px;
897
+ .h-10 {
898
+ height: 2.5rem;
964
899
  }
965
900
 
966
- .h-\[190px\] {
967
- height: 190px;
968
- }
969
-
970
- .h-\[55px\] {
971
- height: 55px;
901
+ .h-11 {
902
+ height: 2.75rem;
972
903
  }
973
904
 
974
905
  .max-h-\[30vh\] {
@@ -979,10 +910,22 @@ video {
979
910
  max-height: 50vh;
980
911
  }
981
912
 
913
+ .\!w-0 {
914
+ width: 0px !important;
915
+ }
916
+
917
+ .\!w-64 {
918
+ width: 16rem !important;
919
+ }
920
+
982
921
  .\!w-\[90vw\] {
983
922
  width: 90vw !important;
984
923
  }
985
924
 
925
+ .w-0 {
926
+ width: 0px;
927
+ }
928
+
986
929
  .w-16 {
987
930
  width: 4rem;
988
931
  }
@@ -1003,6 +946,10 @@ video {
1003
946
  width: 1.25rem;
1004
947
  }
1005
948
 
949
+ .w-6 {
950
+ width: 1.5rem;
951
+ }
952
+
1006
953
  .w-64 {
1007
954
  width: 16rem;
1008
955
  }
@@ -1019,34 +966,6 @@ video {
1019
966
  width: 100%;
1020
967
  }
1021
968
 
1022
- .w-6 {
1023
- width: 1.5rem;
1024
- }
1025
-
1026
- .w-\[170px\] {
1027
- width: 170px;
1028
- }
1029
-
1030
- .w-\[200px\] {
1031
- width: 200px;
1032
- }
1033
-
1034
- .w-0 {
1035
- width: 0px;
1036
- }
1037
-
1038
- .w-\[255px\] {
1039
- width: 255px;
1040
- }
1041
-
1042
- .\!w-0 {
1043
- width: 0px !important;
1044
- }
1045
-
1046
- .\!w-64 {
1047
- width: 16rem !important;
1048
- }
1049
-
1050
969
  .min-w-0 {
1051
970
  min-width: 0px;
1052
971
  }
@@ -1059,34 +978,14 @@ video {
1059
978
  max-width: 64rem;
1060
979
  }
1061
980
 
1062
- .max-w-\[calc\(100\%-6\.5rem\)\] {
1063
- max-width: calc(100% - 6.5rem);
1064
- }
1065
-
1066
- .max-w-\[calc\(100vw-25rem\)\] {
1067
- max-width: calc(100vw - 25rem);
981
+ .max-w-\[calc\(100vw-4rem\)\] {
982
+ max-width: calc(100vw - 4rem);
1068
983
  }
1069
984
 
1070
985
  .max-w-xs {
1071
986
  max-width: 20rem;
1072
987
  }
1073
988
 
1074
- .max-w-7xl {
1075
- max-width: 80rem;
1076
- }
1077
-
1078
- .max-w-\[100vw\] {
1079
- max-width: 100vw;
1080
- }
1081
-
1082
- .max-w-\[calc\(100vw-6rem\)\] {
1083
- max-width: calc(100vw - 6rem);
1084
- }
1085
-
1086
- .max-w-\[calc\(100vw-4rem\)\] {
1087
- max-width: calc(100vw - 4rem);
1088
- }
1089
-
1090
989
  .flex-1 {
1091
990
  flex: 1 1 0%;
1092
991
  }
@@ -1128,11 +1027,6 @@ video {
1128
1027
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1129
1028
  }
1130
1029
 
1131
- .-translate-x-full {
1132
- --tw-translate-x: -100%;
1133
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1134
- }
1135
-
1136
1030
  .translate-x-full {
1137
1031
  --tw-translate-x: 100%;
1138
1032
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
@@ -1150,6 +1044,10 @@ video {
1150
1044
  cursor: pointer;
1151
1045
  }
1152
1046
 
1047
+ .resize-none {
1048
+ resize: none;
1049
+ }
1050
+
1153
1051
  .list-disc {
1154
1052
  list-style-type: disc;
1155
1053
  }
@@ -1168,10 +1066,6 @@ video {
1168
1066
  grid-template-columns: repeat(2, minmax(0, 1fr));
1169
1067
  }
1170
1068
 
1171
- .grid-cols-5 {
1172
- grid-template-columns: repeat(5, minmax(0, 1fr));
1173
- }
1174
-
1175
1069
  .flex-row {
1176
1070
  flex-direction: row;
1177
1071
  }
@@ -1184,6 +1078,10 @@ video {
1184
1078
  align-items: flex-start;
1185
1079
  }
1186
1080
 
1081
+ .items-end {
1082
+ align-items: flex-end;
1083
+ }
1084
+
1187
1085
  .items-center {
1188
1086
  align-items: center;
1189
1087
  }
@@ -1224,10 +1122,6 @@ video {
1224
1122
  gap: 2rem;
1225
1123
  }
1226
1124
 
1227
- .gap-16 {
1228
- gap: 4rem;
1229
- }
1230
-
1231
1125
  .gap-x-4 {
1232
1126
  -moz-column-gap: 1rem;
1233
1127
  column-gap: 1rem;
@@ -1264,24 +1158,18 @@ video {
1264
1158
  margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
1265
1159
  }
1266
1160
 
1267
- .space-y-4 > :not([hidden]) ~ :not([hidden]) {
1268
- --tw-space-y-reverse: 0;
1269
- margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
1270
- margin-bottom: calc(1rem * var(--tw-space-y-reverse));
1271
- }
1272
-
1273
- .space-x-0 > :not([hidden]) ~ :not([hidden]) {
1274
- --tw-space-x-reverse: 0;
1275
- margin-right: calc(0px * var(--tw-space-x-reverse));
1276
- margin-left: calc(0px * calc(1 - var(--tw-space-x-reverse)));
1277
- }
1278
-
1279
1161
  .space-y-2 > :not([hidden]) ~ :not([hidden]) {
1280
1162
  --tw-space-y-reverse: 0;
1281
1163
  margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
1282
1164
  margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
1283
1165
  }
1284
1166
 
1167
+ .space-y-4 > :not([hidden]) ~ :not([hidden]) {
1168
+ --tw-space-y-reverse: 0;
1169
+ margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
1170
+ margin-bottom: calc(1rem * var(--tw-space-y-reverse));
1171
+ }
1172
+
1285
1173
  .divide-y > :not([hidden]) ~ :not([hidden]) {
1286
1174
  --tw-divide-y-reverse: 0;
1287
1175
  border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
@@ -1435,6 +1323,11 @@ video {
1435
1323
  border-color: rgb(63 83 255 / var(--tw-border-opacity));
1436
1324
  }
1437
1325
 
1326
+ .bg-black {
1327
+ --tw-bg-opacity: 1;
1328
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
1329
+ }
1330
+
1438
1331
  .bg-blue-200 {
1439
1332
  --tw-bg-opacity: 1;
1440
1333
  background-color: rgb(191 219 254 / var(--tw-bg-opacity));
@@ -1599,42 +1492,10 @@ video {
1599
1492
  background-color: rgb(253 224 71 / var(--tw-bg-opacity));
1600
1493
  }
1601
1494
 
1602
- .bg-indigo-600 {
1603
- --tw-bg-opacity: 1;
1604
- background-color: rgb(79 70 229 / var(--tw-bg-opacity));
1605
- }
1606
-
1607
- .bg-black {
1608
- --tw-bg-opacity: 1;
1609
- background-color: rgb(0 0 0 / var(--tw-bg-opacity));
1610
- }
1611
-
1612
- .bg-opacity-25 {
1613
- --tw-bg-opacity: 0.25;
1614
- }
1615
-
1616
1495
  .bg-opacity-40 {
1617
1496
  --tw-bg-opacity: 0.4;
1618
1497
  }
1619
1498
 
1620
- .bg-cover {
1621
- background-size: cover;
1622
- }
1623
-
1624
- .bg-center {
1625
- background-position: center;
1626
- }
1627
-
1628
- .object-cover {
1629
- -o-object-fit: cover;
1630
- object-fit: cover;
1631
- }
1632
-
1633
- .object-center {
1634
- -o-object-position: center;
1635
- object-position: center;
1636
- }
1637
-
1638
1499
  .p-1 {
1639
1500
  padding: 0.25rem;
1640
1501
  }
@@ -1720,26 +1581,6 @@ video {
1720
1581
  padding-bottom: 1.5rem;
1721
1582
  }
1722
1583
 
1723
- .px-\[10px\] {
1724
- padding-left: 10px;
1725
- padding-right: 10px;
1726
- }
1727
-
1728
- .py-10 {
1729
- padding-top: 2.5rem;
1730
- padding-bottom: 2.5rem;
1731
- }
1732
-
1733
- .py-\[10px\] {
1734
- padding-top: 10px;
1735
- padding-bottom: 10px;
1736
- }
1737
-
1738
- .px-1\.5 {
1739
- padding-left: 0.375rem;
1740
- padding-right: 0.375rem;
1741
- }
1742
-
1743
1584
  .pb-2 {
1744
1585
  padding-bottom: 0.5rem;
1745
1586
  }
@@ -1788,14 +1629,6 @@ video {
1788
1629
  padding-top: 1px;
1789
1630
  }
1790
1631
 
1791
- .pb-12 {
1792
- padding-bottom: 3rem;
1793
- }
1794
-
1795
- .pt-5 {
1796
- padding-top: 1.25rem;
1797
- }
1798
-
1799
1632
  .text-left {
1800
1633
  text-align: left;
1801
1634
  }
@@ -1889,6 +1722,11 @@ video {
1889
1722
  color: rgb(0 242 58 / var(--tw-text-opacity));
1890
1723
  }
1891
1724
 
1725
+ .text-gray-300 {
1726
+ --tw-text-opacity: 1;
1727
+ color: rgb(209 213 219 / var(--tw-text-opacity));
1728
+ }
1729
+
1892
1730
  .text-gray-400 {
1893
1731
  --tw-text-opacity: 1;
1894
1732
  color: rgb(156 163 175 / var(--tw-text-opacity));
@@ -1944,6 +1782,11 @@ video {
1944
1782
  color: rgb(0 168 165 / var(--tw-text-opacity));
1945
1783
  }
1946
1784
 
1785
+ .text-ultramarine-700 {
1786
+ --tw-text-opacity: 1;
1787
+ color: rgb(7 19 250 / var(--tw-text-opacity));
1788
+ }
1789
+
1947
1790
  .text-valencia-500 {
1948
1791
  --tw-text-opacity: 1;
1949
1792
  color: rgb(220 73 73 / var(--tw-text-opacity));
@@ -1954,16 +1797,6 @@ video {
1954
1797
  color: rgb(255 255 255 / var(--tw-text-opacity));
1955
1798
  }
1956
1799
 
1957
- .text-indigo-600 {
1958
- --tw-text-opacity: 1;
1959
- color: rgb(79 70 229 / var(--tw-text-opacity));
1960
- }
1961
-
1962
- .text-ultramarine-700 {
1963
- --tw-text-opacity: 1;
1964
- color: rgb(7 19 250 / var(--tw-text-opacity));
1965
- }
1966
-
1967
1800
  .accent-sky-600 {
1968
1801
  accent-color: #0284c7;
1969
1802
  }
@@ -1972,14 +1805,6 @@ video {
1972
1805
  opacity: 0.5;
1973
1806
  }
1974
1807
 
1975
- .opacity-0 {
1976
- opacity: 0;
1977
- }
1978
-
1979
- .opacity-100 {
1980
- opacity: 1;
1981
- }
1982
-
1983
1808
  .shadow-lg {
1984
1809
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
1985
1810
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
@@ -1992,18 +1817,6 @@ video {
1992
1817
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1993
1818
  }
1994
1819
 
1995
- .shadow {
1996
- --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
1997
- --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
1998
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1999
- }
2000
-
2001
- .shadow-xl {
2002
- --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
2003
- --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
2004
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
2005
- }
2006
-
2007
1820
  .outline-none {
2008
1821
  outline: 2px solid transparent;
2009
1822
  outline-offset: 2px;
@@ -2078,14 +1891,14 @@ video {
2078
1891
  transition-duration: 150ms;
2079
1892
  }
2080
1893
 
2081
- .transition-colors {
2082
- transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
1894
+ .transition-all {
1895
+ transition-property: all;
2083
1896
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2084
1897
  transition-duration: 150ms;
2085
1898
  }
2086
1899
 
2087
- .transition-opacity {
2088
- transition-property: opacity;
1900
+ .transition-colors {
1901
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
2089
1902
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2090
1903
  transition-duration: 150ms;
2091
1904
  }
@@ -2096,16 +1909,6 @@ video {
2096
1909
  transition-duration: 150ms;
2097
1910
  }
2098
1911
 
2099
- .transition-all {
2100
- transition-property: all;
2101
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2102
- transition-duration: 150ms;
2103
- }
2104
-
2105
- .duration-150 {
2106
- transition-duration: 150ms;
2107
- }
2108
-
2109
1912
  .duration-200 {
2110
1913
  transition-duration: 200ms;
2111
1914
  }
@@ -2114,22 +1917,10 @@ video {
2114
1917
  transition-duration: 300ms;
2115
1918
  }
2116
1919
 
2117
- .ease-in {
2118
- transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
2119
- }
2120
-
2121
- .ease-out {
2122
- transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
2123
- }
2124
-
2125
1920
  .ease-in-out {
2126
1921
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2127
1922
  }
2128
1923
 
2129
- .ease-linear {
2130
- transition-timing-function: linear;
2131
- }
2132
-
2133
1924
  .placeholder\:text-gray-400::-moz-placeholder {
2134
1925
  --tw-text-opacity: 1;
2135
1926
  color: rgb(156 163 175 / var(--tw-text-opacity));
@@ -2155,10 +1946,6 @@ video {
2155
1946
  --tw-ring-color: rgb(0 168 165 / var(--tw-ring-opacity));
2156
1947
  }
2157
1948
 
2158
- .hover\:border-b:hover {
2159
- border-bottom-width: 1px;
2160
- }
2161
-
2162
1949
  .hover\:border-gray-300:hover {
2163
1950
  --tw-border-opacity: 1;
2164
1951
  border-color: rgb(209 213 219 / var(--tw-border-opacity));
@@ -2179,6 +1966,11 @@ video {
2179
1966
  background-color: rgb(0 242 58 / var(--tw-bg-opacity));
2180
1967
  }
2181
1968
 
1969
+ .hover\:bg-gray-100:hover {
1970
+ --tw-bg-opacity: 1;
1971
+ background-color: rgb(243 244 246 / var(--tw-bg-opacity));
1972
+ }
1973
+
2182
1974
  .hover\:bg-gray-200:hover {
2183
1975
  --tw-bg-opacity: 1;
2184
1976
  background-color: rgb(229 231 235 / var(--tw-bg-opacity));
@@ -2274,11 +2066,6 @@ video {
2274
2066
  background-color: rgb(220 73 73 / var(--tw-bg-opacity));
2275
2067
  }
2276
2068
 
2277
- .hover\:bg-gray-100:hover {
2278
- --tw-bg-opacity: 1;
2279
- background-color: rgb(243 244 246 / var(--tw-bg-opacity));
2280
- }
2281
-
2282
2069
  .hover\:text-gray-700:hover {
2283
2070
  --tw-text-opacity: 1;
2284
2071
  color: rgb(55 65 81 / var(--tw-text-opacity));
@@ -2289,16 +2076,6 @@ video {
2289
2076
  color: rgb(10 87 87 / var(--tw-text-opacity));
2290
2077
  }
2291
2078
 
2292
- .hover\:text-black:hover {
2293
- --tw-text-opacity: 1;
2294
- color: rgb(0 0 0 / var(--tw-text-opacity));
2295
- }
2296
-
2297
- .hover\:text-gray-800:hover {
2298
- --tw-text-opacity: 1;
2299
- color: rgb(31 41 55 / var(--tw-text-opacity));
2300
- }
2301
-
2302
2079
  .focus\:z-10:focus {
2303
2080
  z-index: 10;
2304
2081
  }
@@ -2497,10 +2274,6 @@ video {
2497
2274
  margin-top: 0px;
2498
2275
  }
2499
2276
 
2500
- .sm\:mt-5 {
2501
- margin-top: 1.25rem;
2502
- }
2503
-
2504
2277
  .sm\:flex {
2505
2278
  display: flex;
2506
2279
  }
@@ -2518,15 +2291,6 @@ video {
2518
2291
  flex: none;
2519
2292
  }
2520
2293
 
2521
- .sm\:translate-y-px {
2522
- --tw-translate-y: 1px;
2523
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
2524
- }
2525
-
2526
- .sm\:transform {
2527
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
2528
- }
2529
-
2530
2294
  .sm\:flex-col {
2531
2295
  flex-direction: column;
2532
2296
  }
@@ -2597,28 +2361,36 @@ video {
2597
2361
  .md\:w-64 {
2598
2362
  width: 16rem;
2599
2363
  }
2364
+
2365
+ .md\:max-w-\[calc\(100vw-16rem\)\] {
2366
+ max-width: calc(100vw - 16rem);
2367
+ }
2368
+
2369
+ .md\:max-w-\[calc\(100vw-20rem\)\] {
2370
+ max-width: calc(100vw - 20rem);
2371
+ }
2372
+
2373
+ .md\:p-3 {
2374
+ padding: 0.75rem;
2375
+ }
2600
2376
  }
2601
2377
 
2602
2378
  @media (min-width: 1024px) {
2379
+ .lg\:relative {
2380
+ position: relative;
2381
+ }
2382
+
2603
2383
  .lg\:-mx-8 {
2604
2384
  margin-left: -2rem;
2605
2385
  margin-right: -2rem;
2606
2386
  }
2607
2387
 
2608
- .lg\:block {
2609
- display: block;
2610
- }
2611
-
2612
- .lg\:hidden {
2613
- display: none;
2614
- }
2615
-
2616
- .lg\:flex-1 {
2617
- flex: 1 1 0%;
2388
+ .lg\:w-64 {
2389
+ width: 16rem;
2618
2390
  }
2619
2391
 
2620
- .lg\:self-stretch {
2621
- align-self: stretch;
2392
+ .lg\:max-w-\[calc\(100vw-20rem\)\] {
2393
+ max-width: calc(100vw - 20rem);
2622
2394
  }
2623
2395
 
2624
2396
  .lg\:px-8 {
@@ -1,9 +1,9 @@
1
- <div class="relative flex items-start space-x-3" :class="{'justify-end': message.role === 'user'}">
1
+ <div class="relative flex items-start" :class="{'justify-end': message.role === 'user'}">
2
2
  <div
3
- class="min-w-0 max-w-[calc(100vw-4rem)]"
3
+ class="min-w-0 max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)]"
4
4
  :class="{'text-right': message.role === 'user'}">
5
5
 
6
- <div class="text-sm text-gray-900 p-3 rounded-md inline-block" :class="styleForMessage">
6
+ <div class="text-sm text-gray-900 md:p-3 rounded-md inline-block" :class="styleForMessage">
7
7
  <div v-for="part in contentSplitByScripts">
8
8
  <div v-if="part.type === 'text'" v-html="marked(part.content)">
9
9
  </div>
@@ -37,9 +37,9 @@
37
37
  </div>
38
38
  </div>
39
39
 
40
- <pre class="p-3 whitespace-pre-wrap max-h-[30vh] max-w-[calc(100vw-4rem)] overflow-y-auto" v-show="activeTab === 'code'"><code v-text="script" ref="code" :class="'language-' + language"></code></pre>
40
+ <pre class="p-3 whitespace-pre-wrap max-h-[50vh] max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] overflow-y-auto" v-show="activeTab === 'code'"><code v-text="script" ref="code" :class="'language-' + language"></code></pre>
41
41
 
42
- <div class="p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t max-w-[calc(100vw-4rem)] relative" v-show="activeTab === 'output'">
42
+ <div class="p-3 whitespace-pre-wrap max-h-[50vh] overflow-y-auto bg-white border-t max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] relative" v-show="activeTab === 'output'">
43
43
  <dashboard-chart v-if="message.executionResult?.output?.$chart" :value="message.executionResult?.output" />
44
44
  <pre v-else>{{ message.executionResult?.output || 'No output' }}</pre>
45
45
  </div>
@@ -1,9 +1,9 @@
1
1
  <div class="flex" style="height: calc(100vh - 55px)">
2
2
  <div class="fixed top-[65px] cursor-pointer bg-gray-100 rounded-r-md z-10" @click="hideSidebar = false">
3
- <svg xmlns="http://www.w3.org/2000/svg" style="h-5 w-5" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="M360-120v-720h80v720h-80Zm160-160v-400l200 200-200 200Z"/></svg>
3
+ <svg xmlns="http://www.w3.org/2000/svg" style="h-5 w-5" viewBox="0 -960 960 960" class="w-5" fill="#5f6368"><path d="M360-120v-720h80v720h-80Zm160-160v-400l200 200-200 200Z"/></svg>
4
4
  </div>
5
5
  <!-- Sidebar: Chat Threads -->
6
- <aside class="bg-gray-50 border-r overflow-y-auto overflow-x-hidden h-full transition-all duration-300 ease-in-out z-20 w-0 md:w-64 fixed md:relative" :class="hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''">
6
+ <aside class="bg-gray-50 border-r overflow-y-auto overflow-x-hidden h-full transition-all duration-300 ease-in-out z-20 w-0 lg:w-64 fixed lg:relative" :class="hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''">
7
7
  <div class="flex items-center border-b border-gray-100 w-64 overflow-x-hidden">
8
8
  <div class="p-4 font-bold text-lg">Chat Threads</div>
9
9
  <button
@@ -11,7 +11,7 @@
11
11
  class="ml-auto mr-2 p-2 rounded hover:bg-gray-200 focus:outline-none"
12
12
  aria-label="Close sidebar"
13
13
  >
14
- <svg xmlns="http://www.w3.org/2000/svg" style="h-5 w-5" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M660-320v-320L500-480l160 160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm120-80v-560H200v560h120Zm80 0h360v-560H400v560Zm-80 0H200h120Z"/></svg>
14
+ <svg xmlns="http://www.w3.org/2000/svg" style="h-5 w-5" viewBox="0 -960 960 960" class="w-5" fill="currentColor"><path d="M660-320v-320L500-480l160 160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm120-80v-560H200v560h120Zm80 0h360v-560H400v560Zm-80 0H200h120Z"/></svg>
15
15
  </button>
16
16
  </div>
17
17
  <div class="p-4 w-64">
@@ -58,13 +58,17 @@
58
58
 
59
59
  <!-- Input Area -->
60
60
  <div class="border-t p-4">
61
- <form @submit.prevent="sendMessage" :disabled="sendingMessage" class="flex gap-2">
62
- <input
61
+ <form @submit.prevent="sendMessage" :disabled="sendingMessage" class="flex gap-2 items-end justify-end">
62
+ <textarea
63
63
  v-model="newMessage"
64
64
  placeholder="Ask something..."
65
- class="flex-1 border rounded px-4 py-2"
66
- />
67
- <button class="bg-blue-600 text-white px-4 py-2 rounded disabled:bg-gray-600" :disabled="sendingMessage">
65
+ class="flex-1 border rounded px-4 py-2 resize-none overflow-y-auto"
66
+ rows="1"
67
+ ref="messageInput"
68
+ @input="adjustTextareaHeight"
69
+ @keydown.enter.exact.prevent="handleEnter"
70
+ ></textarea>
71
+ <button class="bg-blue-600 text-white px-4 h-[42px] rounded disabled:bg-gray-600" :disabled="sendingMessage">
68
72
  <svg v-if="sendingMessage" style="height: 1em" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
69
73
  <g>
70
74
  <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2" opacity="0.3" />
@@ -44,6 +44,11 @@ module.exports = app => app.component('chat', {
44
44
  this.chatMessages.push(chatMessages[1]);
45
45
 
46
46
  this.newMessage = '';
47
+ this.$nextTick(() => {
48
+ if (this.$refs.messageInput) {
49
+ this.$refs.messageInput.style.height = 'auto';
50
+ }
51
+ });
47
52
 
48
53
  this.$nextTick(() => {
49
54
  if (this.$refs.messagesContainer) {
@@ -54,6 +59,18 @@ module.exports = app => app.component('chat', {
54
59
  this.sendingMessage = false;
55
60
  }
56
61
  },
62
+ handleEnter(ev) {
63
+ if (!ev.shiftKey) {
64
+ this.sendMessage();
65
+ }
66
+ },
67
+ adjustTextareaHeight(ev) {
68
+ const textarea = ev.target;
69
+ textarea.style.height = 'auto';
70
+ const lineHeight = parseInt(window.getComputedStyle(textarea).lineHeight, 10);
71
+ const maxHeight = lineHeight * 5;
72
+ textarea.style.height = Math.min(textarea.scrollHeight, maxHeight) + 'px';
73
+ },
57
74
  selectThread(threadId) {
58
75
  this.$router.push('/chat/' + threadId);
59
76
  },
@@ -6,6 +6,7 @@ if (typeof process === 'undefined') {
6
6
 
7
7
  const api = require('./api');
8
8
  const mothership = require('./mothership');
9
+ const { routes } = require('./routes');
9
10
  const vanillatoasts = require('vanillatoasts');
10
11
 
11
12
  const app = Vue.createApp({
@@ -67,7 +68,7 @@ app.component('app-component', {
67
68
  window.state = this;
68
69
 
69
70
  if (mothership.hasAPIKey) {
70
- const hash = window.location.hash.replace(/^#?\/?\??/, '') || '';
71
+ const hash = window.location.hash.replace(/^#?\/?/, '') || '';
71
72
  const hashQuery = hash.split('?')[1] || '';
72
73
  const hashParams = new URLSearchParams(hashQuery);
73
74
  if (hashParams.has('code')) {
@@ -110,6 +111,7 @@ app.component('app-component', {
110
111
  const { nodeEnv } = await api.status();
111
112
  this.nodeEnv = nodeEnv;
112
113
  }
114
+
113
115
  this.status = 'loaded';
114
116
  },
115
117
  setup() {
@@ -126,7 +128,6 @@ app.component('app-component', {
126
128
  }
127
129
  });
128
130
 
129
- const { routes } = require('./routes');
130
131
  const router = VueRouter.createRouter({
131
132
  history: VueRouter.createWebHashHistory(),
132
133
  routes: routes.map(route => ({
@@ -136,6 +137,14 @@ const router = VueRouter.createRouter({
136
137
  }))
137
138
  });
138
139
 
140
+ router.beforeEach((to, from, next) => {
141
+ if (to.name === 'root' && window.state.roles && window.state.roles[0] === 'dashboards') {
142
+ return next({ name: 'dashboards' });
143
+ } else {
144
+ next();
145
+ }
146
+ });
147
+
139
148
  app.use(router);
140
149
 
141
150
  app.mount('#content');
@@ -3,7 +3,7 @@
3
3
  <router-link :to="{ name: defaultRoute }">
4
4
  <img src="images/logo.svg" class="h-[32px] mr-1" alt="Mongoose Studio Logo" />
5
5
  </router-link>
6
- <div v-if="!!state.nodeEnv" class="inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900" :class="warnEnv ? 'bg-red-300' : 'bg-yellow-300'">
6
+ <div v-if="!!state.nodeEnv" title="NODE_ENV" class="inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900" :class="warnEnv ? 'bg-red-300' : 'bg-yellow-300'">
7
7
  {{state.nodeEnv}}
8
8
  </div>
9
9
  </div>
@@ -13,14 +13,32 @@
13
13
  href="#/"
14
14
  class="inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
15
15
  :class="documentView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'">Documents</a>
16
+ <span v-else class="inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium text-gray-300 cursor-not-allowed" aria-disabled="true">
17
+ Documents
18
+ <svg class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
19
+ <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" />
20
+ </svg>
21
+ </span>
16
22
  <a v-if="hasAccess(roles, 'dashboards')"
17
23
  href="#/dashboards"
18
24
  class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium"
19
25
  :class="dashboardView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'">Dashboards</a>
26
+ <span v-else class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium text-gray-300 cursor-not-allowed">
27
+ Dashboards
28
+ <svg class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
29
+ <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" />
30
+ </svg>
31
+ </span>
20
32
  <a v-if="hasAccess(roles, 'chat')"
21
33
  href="#/chat"
22
34
  class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium"
23
35
  :class="chatView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'">Chat</a>
36
+ <span v-else class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium text-gray-300 cursor-not-allowed">
37
+ Chat
38
+ <svg class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
39
+ <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" />
40
+ </svg>
41
+ </span>
24
42
 
25
43
  <div class="h-full flex items-center" v-if="!user && hasAPIKey">
26
44
  <button
@@ -41,6 +59,12 @@
41
59
 
42
60
  <div v-if="showFlyout" class="absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
43
61
  <router-link to="/team" v-if="hasAccess(roles, 'team')" @click="showFlyout = false" class="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200" role="menuitem" tabindex="-1" id="user-menu-item-2">Team</router-link>
62
+ <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">
63
+ Team
64
+ <svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
65
+ <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" />
66
+ </svg>
67
+ </span>
44
68
  <span @click="logout" class="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200" role="menuitem" tabindex="-1" id="user-menu-item-2">Sign out</span>
45
69
  </div>
46
70
  </div>
@@ -77,14 +101,32 @@
77
101
  href="#/"
78
102
  class="block px-3 py-2 rounded-md text-base font-medium"
79
103
  :class="documentView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'">Documents</a>
104
+ <span v-else class="block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed">
105
+ Documents
106
+ <svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
107
+ <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" />
108
+ </svg>
109
+ </span>
80
110
  <a v-if="hasAccess(roles, 'dashboards')"
81
111
  href="#/dashboards"
82
112
  class="block px-3 py-2 rounded-md text-base font-medium"
83
113
  :class="dashboardView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'">Dashboards</a>
114
+ <span v-else class="block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed">
115
+ Dashboards
116
+ <svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
117
+ <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" />
118
+ </svg>
119
+ </span>
84
120
  <a v-if="hasAccess(roles, 'chat')"
85
121
  href="#/chat"
86
122
  class="block px-3 py-2 rounded-md text-base font-medium"
87
123
  :class="chatView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'">Chat</a>
124
+ <span v-else class="block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed">
125
+ Chat
126
+ <svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
127
+ <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" />
128
+ </svg>
129
+ </span>
88
130
  <div v-if="!user && hasAPIKey" class="mt-4">
89
131
  <button
90
132
  type="button"
@@ -100,6 +142,12 @@
100
142
  </div>
101
143
  <div class="mt-2 space-y-1">
102
144
  <router-link to="/team" v-if="hasAccess(roles, 'team')" class="block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100">Team</router-link>
145
+ <span v-else class="block px-3 py-2 rounded-md text-base text-gray-300 cursor-not-allowed">
146
+ Team
147
+ <svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
148
+ <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" />
149
+ </svg>
150
+ </span>
103
151
  <span @click="logout" class="block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100 cursor-pointer">Sign out</span>
104
152
  </div>
105
153
  </div>
@@ -15,14 +15,6 @@ module.exports = app => app.component('navbar', {
15
15
  inject: ['state'],
16
16
  data: () => ({ showFlyout: false }),
17
17
  mounted: function() {
18
- // Redirect to first allowed route if current route is not allowed
19
- if (!this.hasAccess(this.roles, this.$route.name)) {
20
- const firstAllowedRoute = this.allowedRoutes[0];
21
- if (firstAllowedRoute) {
22
- this.$router.push({ name: firstAllowedRoute.name });
23
- }
24
- }
25
-
26
18
  const mobileMenuMask = document.querySelector('#mobile-menu-mask');
27
19
  const mobileMenu = document.querySelector('#mobile-menu');
28
20
 
@@ -61,11 +53,8 @@ module.exports = app => app.component('navbar', {
61
53
  canViewTeam() {
62
54
  return this.hasAccess(this.roles, 'team');
63
55
  },
64
- allowedRoutes() {
65
- return routes.filter(route => this.hasAccess(this.roles, route.name));
66
- },
67
56
  defaultRoute() {
68
- return this.allowedRoutes[0]?.name || 'dashboards';
57
+ return this.roles && this.roles[0] === 'dashboards' ? 'dashboards' : 'root';
69
58
  }
70
59
  },
71
60
  methods: {
@@ -9,10 +9,12 @@ const roleAccess = {
9
9
  dashboards: ['dashboards', 'dashboard']
10
10
  };
11
11
 
12
+ const allowedRoutesForLocalDev = ['document', 'root', 'chat'];
13
+
12
14
  // Helper function to check if a role has access to a route
13
15
  function hasAccess(roles, routeName) {
14
16
  // change to true for local development
15
- if (!roles) return false;
17
+ if (!roles) return allowedRoutesForLocalDev.includes(routeName);
16
18
  return roles.some(role => roleAccess[role]?.includes(routeName));
17
19
  }
18
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongoosejs/studio",
3
- "version": "0.0.96",
3
+ "version": "0.0.97",
4
4
  "description": "A sleek, powerful MongoDB UI with built-in dashboarding and auth, seamlessly integrated with your Express, Vercel, or Netlify app.",
5
5
  "homepage": "https://studio.mongoosejs.io/",
6
6
  "repository": {