@raketa-cloud/admin 1.10.1 → 1.10.3

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.
@@ -1525,6 +1525,7 @@ select {
1525
1525
 
1526
1526
  .page-title {
1527
1527
  margin-top: 1.5rem;
1528
+ margin-bottom: 1.5rem;
1528
1529
  display: flex;
1529
1530
  align-items: center;
1530
1531
  justify-content: space-between;
@@ -1626,6 +1627,10 @@ select {
1626
1627
  position: static;
1627
1628
  }
1628
1629
 
1630
+ .fixed {
1631
+ position: fixed;
1632
+ }
1633
+
1629
1634
  .absolute {
1630
1635
  position: absolute;
1631
1636
  }
@@ -1642,6 +1647,11 @@ select {
1642
1647
  inset: 0px;
1643
1648
  }
1644
1649
 
1650
+ .inset-x-0 {
1651
+ left: 0px;
1652
+ right: 0px;
1653
+ }
1654
+
1645
1655
  .-right-0 {
1646
1656
  right: -0px;
1647
1657
  }
@@ -1662,6 +1672,10 @@ select {
1662
1672
  top: -0.125rem;
1663
1673
  }
1664
1674
 
1675
+ .bottom-0 {
1676
+ bottom: 0px;
1677
+ }
1678
+
1665
1679
  .bottom-20 {
1666
1680
  bottom: 5rem;
1667
1681
  }
@@ -1863,6 +1877,10 @@ select {
1863
1877
  height: 2rem;
1864
1878
  }
1865
1879
 
1880
+ .h-12 {
1881
+ height: 3rem;
1882
+ }
1883
+
1866
1884
  .h-2 {
1867
1885
  height: 0.5rem;
1868
1886
  }
@@ -1908,6 +1926,10 @@ select {
1908
1926
  max-height: 100vh;
1909
1927
  }
1910
1928
 
1929
+ .min-h-0 {
1930
+ min-height: 0px;
1931
+ }
1932
+
1911
1933
  .w-1 {
1912
1934
  width: 0.25rem;
1913
1935
  }
@@ -1986,6 +2008,22 @@ select {
1986
2008
  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));
1987
2009
  }
1988
2010
 
2011
+ @keyframes bounce {
2012
+ 0%, 100% {
2013
+ transform: translateY(-25%);
2014
+ animation-timing-function: cubic-bezier(0.8,0,1,1);
2015
+ }
2016
+
2017
+ 50% {
2018
+ transform: none;
2019
+ animation-timing-function: cubic-bezier(0,0,0.2,1);
2020
+ }
2021
+ }
2022
+
2023
+ .animate-bounce {
2024
+ animation: bounce 1s infinite;
2025
+ }
2026
+
1989
2027
  @keyframes ping {
1990
2028
  75%, 100% {
1991
2029
  transform: scale(2);
@@ -2035,6 +2073,10 @@ select {
2035
2073
  align-items: flex-start;
2036
2074
  }
2037
2075
 
2076
+ .items-end {
2077
+ align-items: flex-end;
2078
+ }
2079
+
2038
2080
  .items-center {
2039
2081
  align-items: center;
2040
2082
  }
@@ -2263,6 +2305,20 @@ select {
2263
2305
  background-color: rgb(250 204 21 / var(--tw-bg-opacity));
2264
2306
  }
2265
2307
 
2308
+ .bg-gradient-to-t {
2309
+ background-image: linear-gradient(to top, var(--tw-gradient-stops));
2310
+ }
2311
+
2312
+ .from-raketa-primary\/15 {
2313
+ --tw-gradient-from: rgba(var(--primary), 0.15) var(--tw-gradient-from-position);
2314
+ --tw-gradient-to: rgba(var(--primary), 0) var(--tw-gradient-to-position);
2315
+ --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
2316
+ }
2317
+
2318
+ .to-transparent {
2319
+ --tw-gradient-to: transparent var(--tw-gradient-to-position);
2320
+ }
2321
+
2266
2322
  .fill-\[\#34a853\] {
2267
2323
  fill: #34a853;
2268
2324
  }
@@ -2334,6 +2390,10 @@ select {
2334
2390
  padding-bottom: 1rem;
2335
2391
  }
2336
2392
 
2393
+ .pb-1 {
2394
+ padding-bottom: 0.25rem;
2395
+ }
2396
+
2337
2397
  .pb-4 {
2338
2398
  padding-bottom: 1rem;
2339
2399
  }
@@ -2530,6 +2590,10 @@ select {
2530
2590
  color: rgb(255 255 255 / var(--tw-text-opacity));
2531
2591
  }
2532
2592
 
2593
+ .opacity-0 {
2594
+ opacity: 0;
2595
+ }
2596
+
2533
2597
  .opacity-10 {
2534
2598
  opacity: 0.1;
2535
2599
  }
@@ -2589,6 +2653,12 @@ select {
2589
2653
  transition-duration: 150ms;
2590
2654
  }
2591
2655
 
2656
+ .transition-opacity {
2657
+ transition-property: opacity;
2658
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2659
+ transition-duration: 150ms;
2660
+ }
2661
+
2592
2662
  .duration-150 {
2593
2663
  transition-duration: 150ms;
2594
2664
  }
@@ -2601,6 +2671,14 @@ select {
2601
2671
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2602
2672
  }
2603
2673
 
2674
+ .scrollbar-hidden {
2675
+ scrollbar-width: none;
2676
+ }
2677
+
2678
+ .scrollbar-hidden::-webkit-scrollbar {
2679
+ display: none;
2680
+ }
2681
+
2604
2682
  :root {
2605
2683
  --background: 255, 255, 255;
2606
2684
  --foreground: 0, 0, 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raketa-cloud/admin",
3
- "version": "1.10.1",
3
+ "version": "1.10.3",
4
4
  "main": "src/index.js",
5
5
  "files": [
6
6
  "src/",
@@ -319,7 +319,7 @@ body {
319
319
  }
320
320
 
321
321
  .page-title {
322
- @apply flex items-center justify-between mt-6;
322
+ @apply flex items-center justify-between my-6;
323
323
  }
324
324
 
325
325
  .actions-toolbar {
@@ -359,6 +359,16 @@ body {
359
359
  }
360
360
  }
361
361
 
362
+ @layer utilities {
363
+ .scrollbar-hidden {
364
+ scrollbar-width: none;
365
+ }
366
+
367
+ .scrollbar-hidden::-webkit-scrollbar {
368
+ display: none;
369
+ }
370
+ }
371
+
362
372
  .space-the-final-frontier {
363
373
  position: fixed;
364
374
  top: 50%;
@@ -64,7 +64,8 @@
64
64
  </svg>
65
65
  </button>
66
66
 
67
- <div class="my-4">
67
+ <div class="relative flex-1 min-h-0">
68
+ <div id="sidebar-menu" class="h-full py-4 overflow-y-auto scrollbar-hidden">
68
69
  <% _context.layout.sidebar.forEach((menu, idx) => { %>
69
70
  <% if (!menu) { %>
70
71
  <% } else if (menu.submenus) { %>
@@ -77,7 +78,7 @@
77
78
  </div>
78
79
  </div>
79
80
 
80
- <div class="absolute z-50 top-0 left-[64px] w-[250px] border-l bg-[#F7F7FC] shadow-lg hidden group-hover/item:block">
81
+ <div data-sidebar-flyout class="fixed z-50 left-[64px] w-[250px] border-l bg-[#F7F7FC] shadow-lg hidden group-hover/item:block">
81
82
  <% menu.submenus.forEach(submenu => { %>
82
83
  <a href="<%= `/${_context.locale}${submenu.link}` %>" title="<%= submenu.label %>" class="block py-3 px-4 body-2 <%= _context.path.includes(submenu.link) ? "text-raketa-foreground" : "text-raketa-foreground/50 hover:text-raketa-foreground transition-all ease-in-out duration-300" %>"><%= submenu.label %></a>
83
84
  <% }) %>
@@ -132,6 +133,13 @@
132
133
 
133
134
  </div>
134
135
 
136
+ <div id="sidebar-scroll-hint" class="pointer-events-none absolute inset-x-0 bottom-0 h-12 flex items-end justify-center pb-1 bg-gradient-to-t from-raketa-primary/15 to-transparent text-raketa-primary transition-opacity duration-300 opacity-0">
137
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 animate-bounce">
138
+ <path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
139
+ </svg>
140
+ </div>
141
+ </div>
142
+
135
143
  <div class="group/item">
136
144
  <a href="/logout" class="relative flex items-center gap-3 px-5 py-4 border-t border-neutral-300 text-raketa-primary hover:bg-raketa-primary hover:text-white group-[.is-active]/item:bg-raketa-primary group-[.is-active]/item:text-white dark:border-neutral-700">
137
145
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-6 opacity-100 group-[.expanded]:opacity-50">
@@ -165,6 +173,50 @@
165
173
  toggleEl.addEventListener('click', handleToggle);
166
174
  </script>
167
175
 
176
+ <script>
177
+ (() => {
178
+ const menuEl = document.getElementById('sidebar-menu');
179
+ const hintEl = document.getElementById('sidebar-scroll-hint');
180
+ let hoveredItem = null;
181
+
182
+ const updateHint = () => {
183
+ const hasMore = menuEl.scrollHeight - menuEl.clientHeight > 1;
184
+ hintEl.classList.toggle('opacity-0', !hasMore || menuEl.scrollTop > 0);
185
+ };
186
+
187
+ // Flyouts are position: fixed so the scrollable menu doesn't clip them
188
+ const positionFlyout = (item) => {
189
+ const flyout = item.querySelector('[data-sidebar-flyout]');
190
+ if (!flyout) return;
191
+
192
+ const { top } = item.getBoundingClientRect();
193
+ const maxTop = window.innerHeight - flyout.offsetHeight;
194
+ flyout.style.top = `${Math.max(0, Math.min(top, maxTop))}px`;
195
+ };
196
+
197
+ menuEl.querySelectorAll('[data-sidebar-flyout]').forEach((flyout) => {
198
+ const item = flyout.parentElement;
199
+
200
+ item.addEventListener('mouseenter', () => {
201
+ hoveredItem = item;
202
+ positionFlyout(item);
203
+ });
204
+ item.addEventListener('mouseleave', () => {
205
+ hoveredItem = null;
206
+ });
207
+ });
208
+
209
+ menuEl.addEventListener('scroll', () => {
210
+ updateHint();
211
+ if (hoveredItem) positionFlyout(hoveredItem);
212
+ }, { passive: true });
213
+
214
+ const resizeObserver = new ResizeObserver(updateHint);
215
+ resizeObserver.observe(menuEl);
216
+ Array.from(menuEl.children).forEach((child) => resizeObserver.observe(child));
217
+ })();
218
+ </script>
219
+
168
220
  <script>
169
221
  const TIMEZONES = JSON.parse("<%= JSON.stringify(_context.timezones) %>".replaceAll("&#34;", '"'))
170
222
  const TIME_LOCALE = JSON.parse("<%= JSON.stringify(_context.timeLocale || 'en-GB') %>".replaceAll("&#34;", '"'))