@vc-shell/framework 1.0.289 → 1.0.291

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 (178) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/core/composables/index.ts +1 -0
  3. package/core/composables/useTheme/index.ts +60 -0
  4. package/core/directives/loading/styles.css +6 -1
  5. package/dist/core/composables/index.d.ts +1 -0
  6. package/dist/core/composables/index.d.ts.map +1 -1
  7. package/dist/core/composables/useTheme/index.d.ts +11 -0
  8. package/dist/core/composables/useTheme/index.d.ts.map +1 -0
  9. package/dist/framework.js +27889 -27362
  10. package/dist/index.css +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/locales/en.json +6 -0
  13. package/dist/shared/components/app-bar-button/app-bar-button.vue.d.ts +56 -0
  14. package/dist/shared/components/app-bar-button/app-bar-button.vue.d.ts.map +1 -0
  15. package/dist/shared/components/app-bar-button/index.d.ts +2 -0
  16. package/dist/shared/components/app-bar-button/index.d.ts.map +1 -0
  17. package/dist/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue.d.ts.map +1 -1
  18. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
  19. package/dist/shared/components/index.d.ts +3 -0
  20. package/dist/shared/components/index.d.ts.map +1 -1
  21. package/dist/shared/components/language-selector/language-selector.vue.d.ts.map +1 -1
  22. package/dist/shared/components/notification-dropdown/notification-dropdown.vue.d.ts.map +1 -1
  23. package/dist/shared/components/notification-template/notification-template.vue.d.ts.map +1 -1
  24. package/dist/shared/components/sidebar/index.d.ts +2 -0
  25. package/dist/shared/components/sidebar/index.d.ts.map +1 -0
  26. package/dist/shared/components/sidebar/sidebar.vue.d.ts +49 -0
  27. package/dist/shared/components/sidebar/sidebar.vue.d.ts.map +1 -0
  28. package/dist/shared/components/theme-selector/index.d.ts +2 -0
  29. package/dist/shared/components/theme-selector/index.d.ts.map +1 -0
  30. package/dist/shared/components/theme-selector/theme-selector.vue.d.ts +3 -0
  31. package/dist/shared/components/theme-selector/theme-selector.vue.d.ts.map +1 -0
  32. package/dist/shared/components/user-dropdown-button/index.d.ts +6 -0
  33. package/dist/shared/components/user-dropdown-button/index.d.ts.map +1 -1
  34. package/dist/shared/components/user-dropdown-button/user-dropdown-button.vue.d.ts +1 -0
  35. package/dist/shared/components/user-dropdown-button/user-dropdown-button.vue.d.ts.map +1 -1
  36. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
  37. package/dist/shared/modules/dynamic/types/index.d.ts +3 -0
  38. package/dist/shared/modules/dynamic/types/index.d.ts.map +1 -1
  39. package/dist/shared/pages/ChangePasswordPage/components/change-password/ChangePassword.vue.d.ts +16 -3
  40. package/dist/shared/pages/ChangePasswordPage/components/change-password/ChangePassword.vue.d.ts.map +1 -1
  41. package/dist/shared/pages/ChangePasswordPage/components/change-password/index.d.ts +7 -7
  42. package/dist/shared/pages/ChangePasswordPage/components/change-password/index.d.ts.map +1 -1
  43. package/dist/shared/pages/InvitePage/components/invite/Invite.vue.d.ts +24 -3
  44. package/dist/shared/pages/InvitePage/components/invite/Invite.vue.d.ts.map +1 -1
  45. package/dist/shared/pages/InvitePage/components/invite/index.d.ts +24 -1
  46. package/dist/shared/pages/InvitePage/components/invite/index.d.ts.map +1 -1
  47. package/dist/shared/pages/ResetPasswordPage/components/reset-password/ResetPassword.vue.d.ts +24 -3
  48. package/dist/shared/pages/ResetPasswordPage/components/reset-password/ResetPassword.vue.d.ts.map +1 -1
  49. package/dist/shared/pages/ResetPasswordPage/components/reset-password/index.d.ts +24 -1
  50. package/dist/shared/pages/ResetPasswordPage/components/reset-password/index.d.ts.map +1 -1
  51. package/dist/tailwind.config.d.ts +42 -15
  52. package/dist/tailwind.config.d.ts.map +1 -1
  53. package/dist/tsconfig.tsbuildinfo +1 -1
  54. package/dist/ui/components/atoms/vc-badge/vc-badge.vue.d.ts.map +1 -1
  55. package/dist/ui/components/atoms/vc-link/vc-link.vue.d.ts.map +1 -1
  56. package/dist/ui/components/atoms/vc-progress/vc-progress.vue.d.ts.map +1 -1
  57. package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts.map +1 -1
  58. package/dist/ui/components/atoms/vc-tooltip/vc-tooltip.vue.d.ts.map +1 -1
  59. package/dist/ui/components/atoms/vc-video/vc-video.vue.d.ts.map +1 -1
  60. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts.map +1 -1
  61. package/dist/ui/components/molecules/vc-checkbox/vc-checkbox.vue.d.ts.map +1 -1
  62. package/dist/ui/components/molecules/vc-field/_internal/vc-field-type/vc-field-type.vue.d.ts.map +1 -1
  63. package/dist/ui/components/molecules/vc-field/vc-field.vue.d.ts.map +1 -1
  64. package/dist/ui/components/molecules/vc-file-upload/vc-file-upload.vue.d.ts.map +1 -1
  65. package/dist/ui/components/molecules/vc-input/vc-input.vue.d.ts.map +1 -1
  66. package/dist/ui/components/molecules/vc-slider/vc-slider.vue.d.ts.map +1 -1
  67. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts.map +1 -1
  68. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue.d.ts.map +1 -1
  69. package/dist/ui/components/organisms/vc-app/vc-app.stories.d.ts +26 -0
  70. package/dist/ui/components/organisms/vc-app/vc-app.stories.d.ts.map +1 -1
  71. package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts +26 -0
  72. package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
  73. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts.map +1 -1
  74. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue.d.ts.map +1 -1
  75. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/vc-blade-toolbar.vue.d.ts.map +1 -1
  76. package/dist/ui/components/organisms/vc-gallery/_internal/vc-gallery-preview/vc-gallery-preview.vue.d.ts.map +1 -1
  77. package/dist/ui/components/organisms/vc-table/_internal/vc-table-add-new/vc-table-add-new.vue.d.ts.map +1 -1
  78. package/dist/ui/components/organisms/vc-table/_internal/vc-table-base-header/vc-table-base-header.vue.d.ts +1 -0
  79. package/dist/ui/components/organisms/vc-table/_internal/vc-table-base-header/vc-table-base-header.vue.d.ts.map +1 -1
  80. package/dist/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue.d.ts.map +1 -1
  81. package/dist/ui/components/organisms/vc-table/_internal/vc-table-empty/vc-table-empty.vue.d.ts.map +1 -1
  82. package/dist/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue.d.ts +1 -0
  83. package/dist/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue.d.ts.map +1 -1
  84. package/dist/ui/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue.d.ts.map +1 -1
  85. package/dist/ui/components/organisms/vc-table/vc-table.stories.d.ts +15 -0
  86. package/dist/ui/components/organisms/vc-table/vc-table.stories.d.ts.map +1 -1
  87. package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts +3 -0
  88. package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
  89. package/package.json +4 -4
  90. package/shared/components/app-bar-button/app-bar-button.vue +169 -0
  91. package/shared/components/app-bar-button/index.ts +1 -0
  92. package/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue +138 -38
  93. package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +10 -1
  94. package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +55 -30
  95. package/shared/components/change-password/change-password.vue +7 -1
  96. package/shared/components/common/popup/vc-popup-error.vue +1 -1
  97. package/shared/components/common/popup/vc-popup-warning.vue +1 -1
  98. package/shared/components/index.ts +3 -0
  99. package/shared/components/language-selector/language-selector.vue +55 -39
  100. package/shared/components/notification-dropdown/_internal/notification/notification.vue +7 -1
  101. package/shared/components/notification-dropdown/notification-dropdown.vue +96 -83
  102. package/shared/components/notification-template/notification-template.vue +66 -22
  103. package/shared/components/notifications/styles/index.scss +1 -0
  104. package/shared/components/sidebar/index.ts +1 -0
  105. package/shared/components/sidebar/sidebar.vue +96 -0
  106. package/shared/components/theme-selector/index.ts +1 -0
  107. package/shared/components/theme-selector/theme-selector.vue +95 -0
  108. package/shared/components/user-dropdown-button/user-dropdown-button.vue +155 -86
  109. package/shared/modules/assets/components/assets-details/assets-details.vue +9 -2
  110. package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +16 -6
  111. package/shared/modules/dynamic/composables/useFilterBuilder/index.ts +1 -1
  112. package/shared/modules/dynamic/helpers/nodeBuilder.ts +1 -1
  113. package/shared/modules/dynamic/pages/dynamic-blade-form.vue +6 -2
  114. package/shared/modules/dynamic/pages/dynamic-blade-list.vue +16 -2
  115. package/shared/modules/dynamic/types/index.ts +3 -0
  116. package/shared/pages/ChangePasswordPage/components/change-password/ChangePassword.vue +14 -9
  117. package/shared/pages/InvitePage/components/invite/Invite.vue +59 -15
  118. package/shared/pages/LoginPage/components/login/Login.vue +78 -22
  119. package/shared/pages/ResetPasswordPage/components/reset-password/ResetPassword.vue +67 -15
  120. package/tailwind.config.ts +281 -15
  121. package/ui/components/atoms/vc-badge/vc-badge.vue +38 -23
  122. package/ui/components/atoms/vc-button/vc-button.vue +37 -34
  123. package/ui/components/atoms/vc-card/vc-card.vue +17 -11
  124. package/ui/components/atoms/vc-col/vc-col.vue +4 -6
  125. package/ui/components/atoms/vc-container/vc-container.vue +26 -8
  126. package/ui/components/atoms/vc-hint/vc-hint.vue +8 -2
  127. package/ui/components/atoms/vc-icon/vc-icon.vue +3 -3
  128. package/ui/components/atoms/vc-image/vc-image.vue +33 -9
  129. package/ui/components/atoms/vc-label/vc-label.vue +38 -9
  130. package/ui/components/atoms/vc-link/vc-link.vue +15 -8
  131. package/ui/components/atoms/vc-loading/vc-loading.vue +37 -8
  132. package/ui/components/atoms/vc-progress/vc-progress.vue +29 -21
  133. package/ui/components/atoms/vc-row/vc-row.vue +4 -2
  134. package/ui/components/atoms/vc-status/vc-status.vue +29 -20
  135. package/ui/components/atoms/vc-status-icon/vc-status-icon.vue +20 -3
  136. package/ui/components/atoms/vc-switch/vc-switch.vue +41 -17
  137. package/ui/components/atoms/vc-tooltip/vc-tooltip.vue +35 -9
  138. package/ui/components/atoms/vc-video/vc-video.vue +28 -6
  139. package/ui/components/atoms/vc-widget/vc-widget.vue +59 -28
  140. package/ui/components/molecules/vc-breadcrumbs/_internal/vc-breadcrumbs-item/vc-breadcrumbs-item.vue +29 -27
  141. package/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +34 -11
  142. package/ui/components/molecules/vc-checkbox/vc-checkbox.vue +43 -21
  143. package/ui/components/molecules/vc-editor/vc-editor.vue +70 -32
  144. package/ui/components/molecules/vc-field/_internal/vc-field-type/vc-field-type.vue +32 -16
  145. package/ui/components/molecules/vc-field/vc-field.vue +36 -13
  146. package/ui/components/molecules/vc-file-upload/vc-file-upload.vue +75 -25
  147. package/ui/components/molecules/vc-input/vc-input.vue +279 -218
  148. package/ui/components/molecules/vc-input-currency/vc-input-currency.vue +24 -2
  149. package/ui/components/molecules/vc-multivalue/vc-multivalue.vue +102 -64
  150. package/ui/components/molecules/vc-notification/vc-notification.vue +40 -15
  151. package/ui/components/molecules/vc-pagination/vc-pagination.vue +19 -15
  152. package/ui/components/molecules/vc-radio-button/vc-radio-button.vue +18 -23
  153. package/ui/components/molecules/vc-rating/vc-rating.vue +9 -5
  154. package/ui/components/molecules/vc-select/vc-select.vue +211 -65
  155. package/ui/components/molecules/vc-slider/vc-slider.vue +32 -13
  156. package/ui/components/molecules/vc-textarea/vc-textarea.vue +17 -12
  157. package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +68 -14
  158. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +112 -122
  159. package/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue +213 -96
  160. package/ui/components/organisms/vc-app/vc-app.vue +41 -15
  161. package/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +78 -30
  162. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue +81 -59
  163. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/vc-blade-toolbar.vue +27 -13
  164. package/ui/components/organisms/vc-blade/vc-blade.vue +177 -46
  165. package/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue +40 -11
  166. package/ui/components/organisms/vc-gallery/_internal/vc-gallery-preview/vc-gallery-preview.vue +52 -18
  167. package/ui/components/organisms/vc-gallery/vc-gallery.vue +38 -6
  168. package/ui/components/organisms/vc-login-form/vc-login-form.vue +40 -14
  169. package/ui/components/organisms/vc-popup/vc-popup.vue +186 -44
  170. package/ui/components/organisms/vc-table/_internal/vc-table-add-new/vc-table-add-new.vue +25 -6
  171. package/ui/components/organisms/vc-table/_internal/vc-table-base-header/vc-table-base-header.vue +48 -12
  172. package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +130 -60
  173. package/ui/components/organisms/vc-table/_internal/vc-table-column-switcher/vc-table-column-switcher.vue +55 -7
  174. package/ui/components/organisms/vc-table/_internal/vc-table-counter/vc-table-counter.vue +17 -5
  175. package/ui/components/organisms/vc-table/_internal/vc-table-empty/vc-table-empty.vue +38 -6
  176. package/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue +111 -62
  177. package/ui/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue +139 -46
  178. package/ui/components/organisms/vc-table/vc-table.vue +370 -128
@@ -104,7 +104,10 @@ const utils = (router: Router) => {
104
104
 
105
105
  function getURLQuery() {
106
106
  if (route.query && Object.keys(route.query).length) {
107
- return { params: new URLSearchParams(route.query as Record<string, string>).toString(), obj: route.query };
107
+ return {
108
+ params: new URLSearchParams(route.query as Record<string, string>).toString(),
109
+ obj: route.query,
110
+ };
108
111
  }
109
112
 
110
113
  const [, query] = window.location.href.split("#")[1].split("?");
@@ -125,12 +128,12 @@ const useBladeNavigationSingleton = createSharedComposable(() => {
125
128
  const route = useRoute();
126
129
  const { setupPageTracking } = useAppInsights();
127
130
 
128
- const instance: BladeComponentInternalInstance = getCurrentInstance() as BladeComponentInternalInstance;
131
+ const instance = getCurrentInstance() as BladeComponentInternalInstance;
129
132
  const navigationInstance =
130
133
  (instance !== null && inject<BladeNavigationPlugin>("bladeNavigationPlugin")) || bladeNavigationInstance;
131
134
  const router = navigationInstance?.router;
132
135
 
133
- const { parseUrl, parseWorkspaceUrl, getURLQuery } = utils(router);
136
+ const { parseUrl, parseWorkspaceUrl, getURLQuery, routes } = utils(router);
134
137
 
135
138
  watch(
136
139
  () => route.path,
@@ -161,7 +164,9 @@ const useBladeNavigationSingleton = createSharedComposable(() => {
161
164
  }
162
165
 
163
166
  function updateActiveWorkspace(wsRouteComponent: BladeVNode) {
164
- wsRouteComponent.props.navigation.idx = 0;
167
+ if (wsRouteComponent.props?.navigation) {
168
+ wsRouteComponent.props.navigation.idx = 0;
169
+ }
165
170
  navigationInstance.blades.value[0] = wsRouteComponent;
166
171
  activeWorkspace.value = wsRouteComponent;
167
172
  closeBlade(1);
@@ -202,8 +207,10 @@ const useBladeNavigationSingleton = createSharedComposable(() => {
202
207
  const wsBladeUrl = workspace?.type.url;
203
208
  const lastBladeUrl = lastBlade?.type.url;
204
209
  const param = lastBlade?.props?.param;
205
- if (lastBlade && wsBladeUrl) {
206
- return "/" + parseUrl(wsBladeUrl)?.workspace + lastBladeUrl + (param ? "/" + param : "");
210
+ const parsedWorkspaceUrl = parseUrl(wsBladeUrl || "")?.workspace;
211
+
212
+ if (lastBlade && wsBladeUrl && parsedWorkspaceUrl) {
213
+ return "/" + parsedWorkspaceUrl + lastBladeUrl + (param ? "/" + param : "");
207
214
  } else {
208
215
  return wsBladeUrl;
209
216
  }
@@ -234,8 +241,8 @@ const useBladeNavigationSingleton = createSharedComposable(() => {
234
241
  try {
235
242
  const children = navigationInstance.blades.value.slice(index).reverse();
236
243
  let isPrevented = false;
237
- for (let index = 0; index < children.length; index++) {
238
- const element = children[index];
244
+ for (let i = 0; i < children.length; i++) {
245
+ const element = children[i];
239
246
 
240
247
  if (element.props?.navigation?.onBeforeClose) {
241
248
  const result = await element.props.navigation.onBeforeClose();
@@ -250,7 +257,7 @@ const useBladeNavigationSingleton = createSharedComposable(() => {
250
257
  }
251
258
 
252
259
  if (!isPrevented) {
253
- if (navigationInstance.blades.value[index - 1]?.props?.navigation?.isVisible === false) {
260
+ if (index > 0 && navigationInstance.blades.value[index - 1]?.props?.navigation?.isVisible === false) {
254
261
  navigationInstance.blades.value[index - 1].props.navigation.isVisible = true;
255
262
  }
256
263
  navigationInstance.blades.value.splice(index);
@@ -276,11 +283,14 @@ export function useBladeNavigation(): IUseBladeNavigation {
276
283
 
277
284
  const { hasAccess } = usePermissions();
278
285
 
279
- const instance: BladeComponentInternalInstance = getCurrentInstance() as BladeComponentInternalInstance;
286
+ const instance = getCurrentInstance() as BladeComponentInternalInstance;
280
287
 
281
288
  const { router, route, navigationInstance, closeBlade, setupPageTracking } = useBladeNavigationSingleton();
282
289
  const { parseUrl, getURLQuery, routes: routerRoutes } = utils(router);
283
- const mainRoute = routerRoutes.find((r) => r.meta?.root)!;
290
+ const mainRoute = routerRoutes.find((r) => r.meta?.root);
291
+ if (!mainRoute) {
292
+ throw new Error("Main route not found");
293
+ }
284
294
 
285
295
  async function openWorkspace<Blade extends Component>(
286
296
  { blade, param, options }: IBladeEvent<Blade>,
@@ -312,11 +322,12 @@ export function useBladeNavigation(): IUseBladeNavigation {
312
322
 
313
323
  if (!isPrevented && createdComponent.type?.url) {
314
324
  if (hasAccess(blade.permissions)) {
315
- // If the blade is the same as the one we want to open, do nothing. It prevents the loose of the instance state
316
- if (navigationInstance.blades.value.length > 0) {
317
- if (navigationInstance.blades.value[0].type.url === createdComponent.type.url) {
318
- return;
319
- }
325
+ if (
326
+ hasAccess(blade.permissions) &&
327
+ navigationInstance.blades.value.length > 0 &&
328
+ navigationInstance.blades.value[0].type.url === createdComponent.type.url
329
+ ) {
330
+ return;
320
331
  }
321
332
  navigationInstance.blades.value = [createdComponent];
322
333
  // Find the route with the matching URL and update the components.default property with the new component
@@ -324,15 +335,21 @@ export function useBladeNavigation(): IUseBladeNavigation {
324
335
  if (wsroute && wsroute.components) {
325
336
  wsroute.components.default = createdComponent;
326
337
  }
327
- return await router.push({ name: wsroute?.name, params: { ...params, ...route.params }, query, replace });
328
- } else
338
+ return await router.push({
339
+ name: wsroute?.name,
340
+ params: { ...params, ...route.params },
341
+ query,
342
+ replace,
343
+ });
344
+ } else {
329
345
  notification.error(i18n.global.t("PERMISSION_MESSAGES.ACCESS_RESTRICTED"), {
330
346
  timeout: 3000,
331
347
  });
348
+ }
332
349
  }
333
350
  } catch (e) {
334
351
  console.error(e);
335
- throw new Error(`Opening workspace '${blade.type.name}' is prevented`);
352
+ throw new Error(`Opening workspace '${blade?.type?.name || "Unknown"}' is prevented`);
336
353
  }
337
354
  }
338
355
 
@@ -367,7 +384,14 @@ export function useBladeNavigation(): IUseBladeNavigation {
367
384
 
368
385
  const currentBladeIdx = instanceComponent.props?.navigation?.idx ?? 0;
369
386
 
370
- const bladeNode = createBladeNode<Blade>({ blade, currentBladeIdx, options, param, onClose, onOpen });
387
+ const bladeNode = createBladeNode<Blade>({
388
+ blade,
389
+ currentBladeIdx,
390
+ options,
391
+ param,
392
+ onClose,
393
+ onOpen,
394
+ });
371
395
 
372
396
  if (!isPrevented) {
373
397
  if (hasAccess(blade.permissions)) {
@@ -386,8 +410,7 @@ export function useBladeNavigation(): IUseBladeNavigation {
386
410
  }
387
411
 
388
412
  function findInstanceComponentIndex(instanceComponent: BladeVNode) {
389
- return navigationInstance.blades.value /* @ts-expect-error - findLastIndex is not parsed correctly by ts */
390
- .findLastIndex((x) => _.isEqual(x.type, instanceComponent.type));
413
+ return _.findLastIndex(navigationInstance.blades.value, (x) => _.isEqual(x.type, instanceComponent.type));
391
414
  }
392
415
 
393
416
  function createBladeNode<Blade extends Component>(args: {
@@ -419,7 +442,7 @@ export function useBladeNavigation(): IUseBladeNavigation {
419
442
  console.debug(`vc-app#onParentCall({ method: ${args.method} }) called.`);
420
443
 
421
444
  if (args.method && parentExposedMethods && typeof parentExposedMethods[args.method] === "function") {
422
- const method = parentExposedMethods[args.method] as (args: unknown) => Promise<unknown>;
445
+ const method = parentExposedMethods[args.method];
423
446
  const result = await method(args.args);
424
447
 
425
448
  if (typeof args.callback === "function") {
@@ -436,7 +459,7 @@ export function useBladeNavigation(): IUseBladeNavigation {
436
459
  if (!instance) {
437
460
  warn("resolveComponentByName can only be used in setup().");
438
461
 
439
- return null as any; // Return type inferred as any due to the early return
462
+ return null as unknown as BladeInstanceConstructor;
440
463
  }
441
464
 
442
465
  if (!name) {
@@ -475,7 +498,7 @@ export function useBladeNavigation(): IUseBladeNavigation {
475
498
  const params = Object.fromEntries(Object.entries(to.params).filter(([key]) => key !== "pathMatch"));
476
499
 
477
500
  // Get the raw path of the main route.
478
- const parentRawPath = routerRoutes.find((route) => route.name === mainRoute.name)?.path;
501
+ const parentRawPath = routerRoutes.find((route) => route.name === mainRoute?.name)?.path;
479
502
 
480
503
  // Determine the parent path based on the parameters.
481
504
  const parentPath =
@@ -568,11 +591,12 @@ export function useBladeNavigation(): IUseBladeNavigation {
568
591
  }
569
592
 
570
593
  function setNavigationQuery(query: Record<string, string | number>) {
571
- if (instance.vnode.props.navigation.idx === 0) {
594
+ const typeName = instance.vnode.type.name?.toLowerCase();
595
+ if (typeName && instance.vnode.props.navigation.idx === 0) {
572
596
  // add blade name to query keys
573
597
  const namedQuery = _.mapKeys(
574
598
  _.mapValues(query, (value) => value?.toString()),
575
- (value, key) => instance.vnode.type.name?.toLowerCase() + "_" + key,
599
+ (value, key) => typeName + "_" + key,
576
600
  );
577
601
  const cleanQuery = _.omitBy(namedQuery, _.isNil);
578
602
 
@@ -585,12 +609,13 @@ export function useBladeNavigation(): IUseBladeNavigation {
585
609
  }
586
610
 
587
611
  function getNavigationQuery() {
588
- if (instance.vnode.props.navigation.idx === 0) {
612
+ const typeName = instance.vnode.type.name?.toLowerCase();
613
+ if (typeName && instance.vnode.props.navigation.idx === 0) {
589
614
  const queryKeys = Array.from(Object.keys(route.query));
590
- const bladeQueryKeys = queryKeys.filter((key) => key.startsWith(instance.vnode.type.name?.toLowerCase() ?? ""));
615
+ const bladeQueryKeys = queryKeys.filter((key) => key.startsWith(typeName));
591
616
 
592
617
  const namedQuery = _.mapKeys(_.pick(route.query, bladeQueryKeys), (value, key) =>
593
- key.replace(instance.vnode.type.name?.toLowerCase() + "_", ""),
618
+ key.replace(typeName + "_", ""),
594
619
  ) as Record<string, string | number>;
595
620
 
596
621
  const obj: typeof namedQuery = {};
@@ -118,7 +118,7 @@
118
118
  <VcHint
119
119
  v-for="(err, i) in form.errors"
120
120
  :key="i"
121
- class="tw-mt-3 !tw-text-[#f14e4e]"
121
+ class="tw-mt-3 !tw-text-[color:var(--change-password-error-color)]"
122
122
  >
123
123
  <!-- TODO: stylizing-->
124
124
  {{
@@ -219,3 +219,9 @@ function validate() {
219
219
  });
220
220
  }
221
221
  </script>
222
+
223
+ <style lang="scss">
224
+ :root {
225
+ --change-password-error-color: var(--base-error-color, var(--danger-500));
226
+ }
227
+ </style>
@@ -39,6 +39,6 @@ defineEmits<Emits>();
39
39
 
40
40
  <style lang="scss">
41
41
  :root {
42
- --confirm-button-color: #6b7987;
42
+ --confirm-button-color: var(--secondary-700);
43
43
  }
44
44
  </style>
@@ -42,6 +42,6 @@ defineEmits<Emits>();
42
42
 
43
43
  <style lang="scss">
44
44
  :root {
45
- --confirm-button-color: #6b7987;
45
+ --confirm-button-color: var(--secondary-700);
46
46
  }
47
47
  </style>
@@ -8,3 +8,6 @@ export * from "./language-selector";
8
8
  export * from "./user-dropdown-button";
9
9
  export * from "./notification-dropdown";
10
10
  export * from "./notification-template";
11
+ export * from "./app-bar-button";
12
+ export * from "./sidebar";
13
+ export * from "./theme-selector";
@@ -1,54 +1,44 @@
1
1
  <template>
2
- <div
3
- v-on-click-outside="
4
- () => {
5
- isDropActive = false;
6
- }
7
- "
8
- class="tw-relative"
2
+ <AppBarButtonTemplate
9
3
  :title="$t('COMPONENTS.LANGUAGE_SELECTOR.TITLE')"
10
- @click.stop="isDropActive = !isDropActive"
4
+ icon="fas fa-globe"
5
+ position="bottom-end"
11
6
  >
12
- <div
13
- :class="[
14
- {
15
- 'tw-shadow-[0_-6px_6px_white,1px_1px_22px_rgba(126,142,157,0.2)] [clip-path:inset(0px_-20px_0px_-20px)] tw-bg-white tw-z-[10000]':
16
- isDropActive,
17
- },
18
- 'tw-relative tw-h-full tw-flex tw-items-center tw-justify-center tw-w-[var(--app-bar-button-width)] tw-border-l tw-border-solid tw-border-l-[color:var(--app-bar-button-border-color)] tw-cursor-pointer tw-text-[color:var(--app-bar-button-color)] tw-bg-[color:var(--app-bar-button-background-color)] tw-transition-[color] tw-duration-200 hover:tw-text-[color:var(--app-bar-button-color-hover)] hover:tw-bg-[color:var(--app-bar-button-background-color-hover)]',
19
- ]"
20
- >
21
- <VcIcon
22
- icon="fas fa-globe"
23
- size="xl"
24
- ></VcIcon>
25
- </div>
26
- <div
27
- v-if="isDropActive"
28
- class="tw-absolute tw-right-0 tw-top-[var(--app-bar-height)] tw-bg-white tw-shadow-[0_-6px_6px_white,1px_1px_22px_rgba(126,142,157,0.2)] tw-w-min tw-z-[10000]"
29
- >
30
- <div
31
- v-for="(lang, i) in languageItems"
32
- :key="i"
33
- class="tw-p-3 tw-text-lg tw-text-black tw-border-l tw-border-solid tw-border-l-[#eef0f2] tw-border-b tw-border-b-[#eef0f2] tw-white tw-cursor-pointer hover:tw-bg-[#eff7fc]"
34
- @click="lang.hasOwnProperty('clickHandler') && lang.clickHandler(lang.lang)"
7
+ <template #dropdown-content="{ opened, toggle }">
8
+ <Sidebar
9
+ :is-expanded="$isMobile.value ? opened : false"
10
+ position="right"
11
+ render="mobile"
12
+ @close="toggle"
35
13
  >
36
- {{ lang.title }}
37
- </div>
38
- </div>
39
- </div>
14
+ <template #content>
15
+ <div
16
+ v-if="opened"
17
+ class="vc-language-selector__dropdown"
18
+ >
19
+ <div
20
+ v-for="(lang, i) in languageItems"
21
+ :key="i"
22
+ class="vc-language-selector__item"
23
+ @click="lang.hasOwnProperty('clickHandler') && lang.clickHandler(lang.lang)"
24
+ >
25
+ {{ lang.title }}
26
+ </div>
27
+ </div>
28
+ </template>
29
+ </Sidebar>
30
+ </template>
31
+ </AppBarButtonTemplate>
40
32
  </template>
41
33
 
42
34
  <script lang="ts" setup>
43
- import { VcIcon } from "./../../../ui/components";
44
- import { ref } from "vue";
45
- import { vOnClickOutside } from "@vueuse/components";
46
35
  import { useI18n } from "vue-i18n";
47
36
  import { useLanguages } from "../../../core/composables";
37
+ import { AppBarButtonTemplate } from "./../app-bar-button";
38
+ import { Sidebar } from "./../sidebar";
48
39
 
49
40
  const { availableLocales, getLocaleMessage } = useI18n({ useScope: "global" });
50
41
  const { setLocale } = useLanguages();
51
- const isDropActive = ref(false);
52
42
 
53
43
  const languageItems = availableLocales
54
44
  .map((locale: string) => ({
@@ -60,3 +50,29 @@ const languageItems = availableLocales
60
50
  }))
61
51
  .filter((item) => item.title);
62
52
  </script>
53
+
54
+ <style lang="scss">
55
+ :root {
56
+ --language-selector-bg-color: var(--additional-50);
57
+ --language-selector-text-color: var(--base-text-color, var(--neutrals-950));
58
+ --language-selector-border-color: var(--app-bar-divider-color);
59
+ --language-selector-hover-bg-color: var(--primary-50);
60
+ }
61
+
62
+ .vc-language-selector {
63
+ &__dropdown {
64
+ @apply tw-bg-[color:var(--language-selector-bg-color)] tw-w-full;
65
+ }
66
+
67
+ &__item {
68
+ @apply tw-p-3 tw-text-sm tw-text-[color:var(--language-selector-text-color)]
69
+ tw-border-l tw-border-solid tw-border-l-[var(--language-selector-border-color)]
70
+ tw-border-b tw-border-b-[var(--language-selector-border-color)] tw-w-full tw-cursor-pointer;
71
+ transition: background-color 0.2s;
72
+
73
+ &:hover {
74
+ background-color: var(--language-selector-hover-bg-color);
75
+ }
76
+ }
77
+ }
78
+ </style>
@@ -43,7 +43,7 @@ const props = defineProps<Props>();
43
43
  const emit = defineEmits<Emits>();
44
44
 
45
45
  const notificationStyle = computed(() => ({
46
- color: "#A9BCCD",
46
+ color: "var(--notification-icon-color)",
47
47
  icon: "fas fa-info",
48
48
  }));
49
49
 
@@ -58,3 +58,9 @@ function notificationTemplateRenderer() {
58
58
  );
59
59
  }
60
60
  </script>
61
+
62
+ <style lang="scss">
63
+ :root {
64
+ --notification-icon-color: var(--secondary-600);
65
+ }
66
+ </style>
@@ -1,114 +1,90 @@
1
1
  <template>
2
- <div
3
- v-on-click-outside="
4
- () => {
5
- isDropdownVisible = false;
6
- }
7
- "
8
- class="tw-relative tw-flex tw-items-center tw-h-full"
2
+ <AppBarButtonTemplate
9
3
  :title="$t('COMPONENTS.NOTIFICATION_DROPDOWN.TITLE')"
10
- @click.stop="toggleNotificationsDrop"
4
+ position="bottom-end"
5
+ @toggle="onOpen"
11
6
  >
12
- <div
13
- :class="[
14
- 'tw-relative tw-h-full tw-flex tw-items-center tw-justify-center tw-w-[var(--app-bar-button-width)] tw-border-l tw-border-solid tw-border-l-[color:var(--app-bar-button-border-color)] tw-cursor-pointer tw-text-[color:var(--app-bar-button-color)] tw-bg-[color:var(--app-bar-button-background-color)] tw-transition-[color] tw-duration-200 hover:tw-text-[color:var(--app-bar-button-color-hover)] hover:tw-bg-[color:var(--app-bar-button-background-color-hover)]',
15
- {
16
- 'tw-shadow-[0_-6px_6px_white,1px_1px_22px_rgba(126,142,157,0.2)] [clip-path:inset(0px_-20px_0px_-20px)] tw-bg-white tw-z-[10001]':
17
- isDropdownVisible && !$isMobile.value,
18
- },
19
- ]"
20
- >
21
- <VcIcon
22
- icon="fas fa-bell"
23
- size="xl"
24
- ></VcIcon>
25
- <div
26
- :class="{
27
- 'tw-block tw-absolute tw-right-[12px] tw-top-[18px] tw-w-[7px] tw-h-[7px] tw-bg-[#ff4a4a] tw-rounded-full tw-z-[1]':
28
- isAccent,
29
- }"
30
- ></div>
31
- </div>
32
- <div
33
- v-if="$isMobile.value && isDropdownVisible"
34
- class="tw-fixed tw-left-0 tw-top-0 tw-right-0 tw-bottom-0 tw-z-[10000] tw-bg-[#808c99] tw-opacity-60"
35
- @click.stop="toggleNotificationsDrop"
36
- ></div>
37
- <div
38
- v-if="isDropdownVisible"
39
- class="tw-absolute tw-top-[var(--app-bar-height)] tw-z-[10000] tw-drop-shadow-[0px_4px_15px_rgba(43,67,84,0.15)] tw-bg-white tw-rounded-b-[6px] tw-w-[439px] tw-max-h-[350px] tw-min-h-[50px] tw-right-0 tw-overflow-hidden tw-flex tw-flex-col"
40
- :class="{
41
- 'tw-hidden !tw-fixed !tw-right-0 !tw-top-0 !tw-max-h-full !tw-max-w-[300px] !tw-w-full !tw-bottom-0 !tw-z-[10000] !tw-border-0':
42
- $isMobile.value,
43
- '!tw-flex': $isMobile.value && isDropdownVisible,
44
- }"
45
- >
46
- <div
47
- v-if="$isMobile.value"
48
- class="tw-text-[#319ed4] tw-flex tw-justify-end tw-items-center tw-p-4 tw-cursor-pointer"
49
- >
7
+ <template #button>
8
+ <div class="vc-notification-dropdown__button">
50
9
  <VcIcon
51
- icon="fas fa-times"
10
+ icon="fas fa-bell"
52
11
  size="xl"
53
- @click.stop="isDropdownVisible = false"
54
12
  ></VcIcon>
13
+ <div
14
+ :class="{
15
+ 'vc-notification-dropdown__accent': isAccent,
16
+ }"
17
+ ></div>
55
18
  </div>
56
- <VcContainer
57
- :no-padding="true"
58
- @click.stop
19
+ </template>
20
+
21
+ <template #dropdown-content="{ opened, toggle }">
22
+ <Sidebar
23
+ :is-expanded="$isMobile.value ? opened : false"
24
+ position="right"
25
+ render="mobile"
26
+ @close="toggle"
59
27
  >
60
- <VcCol v-if="notifications && notifications.length">
28
+ <template #content>
61
29
  <div
62
- v-for="item in notifications"
63
- :key="`notification_${item.id}`"
64
- class="tw-py-[18px] tw-px-[15px] tw-border-b tw-border-solid tw-border-b-[#e3e7ec] tw-cursor-pointer last-of-type:tw-border-b-0"
30
+ v-if="opened"
31
+ :class="[
32
+ 'vc-notification-dropdown__dropdown',
33
+ { 'vc-notification-dropdown__dropdown--mobile': $isMobile.value },
34
+ ]"
65
35
  >
66
- <NotificationItem
67
- :notification="item"
68
- :templates="notificationTemplates || []"
69
- @on-click="() => (isDropdownVisible = false)"
70
- />
36
+ <VcContainer
37
+ :no-padding="true"
38
+ @click.stop
39
+ >
40
+ <VcCol v-if="notifications && notifications.length">
41
+ <div
42
+ v-for="item in notifications"
43
+ :key="`notification_${item.id}`"
44
+ class="vc-notification-dropdown__item"
45
+ >
46
+ <NotificationItem
47
+ :notification="item"
48
+ :templates="notificationTemplates || []"
49
+ @on-click="toggle"
50
+ />
51
+ </div>
52
+ </VcCol>
53
+ <div
54
+ v-else
55
+ class="vc-notification-dropdown__empty"
56
+ >
57
+ {{ t("COMPONENTS.NOTIFICATION_DROPDOWN.EMPTY") }}
58
+ </div>
59
+ </VcContainer>
71
60
  </div>
72
- </VcCol>
73
- <div
74
- v-else
75
- class="tw-flex tw-justify-center tw-items-center tw-p-4"
76
- >
77
- {{ t("COMPONENTS.NOTIFICATION_DROPDOWN.EMPTY") }}
78
- </div>
79
- </VcContainer>
80
- </div>
81
- </div>
61
+ </template>
62
+ </Sidebar>
63
+ </template>
64
+ </AppBarButtonTemplate>
82
65
  </template>
83
66
 
84
67
  <script lang="ts" setup>
85
- import { ref, inject, computed } from "vue";
68
+ import { inject, computed } from "vue";
86
69
  import NotificationItem from "./_internal/notification/notification.vue";
87
70
  import { VcCol, VcContainer, VcIcon } from "../../../ui/components";
88
- import { vOnClickOutside } from "@vueuse/components";
89
71
  import { useI18n } from "vue-i18n";
90
72
  import { NotificationTemplateConstructor } from "../../../core/types";
91
73
  import { useNotifications } from "../../../core/composables";
74
+ import { AppBarButtonTemplate } from "./../app-bar-button";
75
+ import { Sidebar } from "./../sidebar";
92
76
 
93
77
  const notificationTemplates = inject<NotificationTemplateConstructor[]>("notificationTemplates");
94
78
 
95
79
  const { t } = useI18n({ useScope: "global" });
96
80
  const { notifications, markAllAsRead } = useNotifications();
97
81
 
98
- const isDropdownVisible = ref(false);
99
-
100
82
  const isAccent = computed(() => {
101
83
  return notifications.value.some((item) => item.isNew);
102
84
  });
103
85
 
104
- function toggleNotificationsDrop() {
105
- isDropdownVisible.value = !isDropdownVisible.value;
106
-
107
- onOpen();
108
- }
109
-
110
- function onOpen() {
111
- if (notifications.value.some((x) => x.isNew)) {
86
+ function onOpen(state: boolean) {
87
+ if (state && notifications.value.some((x) => x.isNew)) {
112
88
  markAllAsRead();
113
89
  }
114
90
  }
@@ -116,6 +92,43 @@ function onOpen() {
116
92
 
117
93
  <style lang="scss">
118
94
  :root {
119
- --notification-color-error: #f14e4e;
95
+ --notification-dropdown-border-color: var(--additional-50);
96
+ --notification-dropdown-bg-color: var(--additional-50);
97
+ --notification-dropdown-accent-color: var(--danger-500);
98
+ --notification-dropdown-button-width: var(--app-bar-button-width);
99
+ }
100
+
101
+ .vc-notification-dropdown {
102
+ &__accent {
103
+ @apply tw-block tw-absolute tw-right-[12px] tw-top-[18px] tw-w-[7px] tw-h-[7px] tw-bg-[--notification-dropdown-accent-color] tw-rounded-full tw-z-[1];
104
+ }
105
+
106
+ &__dropdown {
107
+ @apply tw-bg-[--notification-dropdown-bg-color] tw-rounded-b-[6px] tw-w-[439px]
108
+ tw-max-h-[350px] tw-min-h-[50px] tw-overflow-hidden tw-flex tw-flex-col;
109
+
110
+ &--mobile {
111
+ @apply tw-max-h-full tw-w-full;
112
+ display: flex !important;
113
+ }
114
+ }
115
+
116
+ &__button {
117
+ @apply tw-w-[var(--notification-dropdown-button-width)] tw-h-full tw-flex tw-items-center tw-justify-center tw-relative;
118
+ }
119
+
120
+ &__item {
121
+ @apply tw-py-[18px] tw-px-[15px] tw-border-b tw-border-solid
122
+ tw-border-b-[var(--notification-dropdown-border-color)] tw-cursor-pointer;
123
+ transition: background-color 0.2s;
124
+
125
+ &:last-of-type {
126
+ @apply tw-border-b-0;
127
+ }
128
+ }
129
+
130
+ &__empty {
131
+ @apply tw-flex tw-justify-center tw-items-center tw-p-4 tw-text-sm;
132
+ }
120
133
  }
121
134
  </style>