@vc-shell/framework 1.0.197 → 1.0.199

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 (116) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/core/composables/useBreadcrumbs/index.ts +15 -9
  3. package/core/plugins/modularity/index.ts +1 -1
  4. package/dist/core/composables/useBreadcrumbs/index.d.ts +1 -6
  5. package/dist/core/composables/useBreadcrumbs/index.d.ts.map +1 -1
  6. package/dist/framework.js +27636 -27362
  7. package/dist/index.css +1 -1
  8. package/dist/locales/en.json +2 -1
  9. package/dist/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +1 -1
  10. package/dist/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.d.ts.map +1 -1
  11. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts +1 -2
  12. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
  13. package/dist/shared/components/blade-navigation/types/index.d.ts +1 -1
  14. package/dist/shared/components/blade-navigation/types/index.d.ts.map +1 -1
  15. package/dist/shared/modules/dynamic/components/SchemaRender.d.ts +3 -3
  16. package/dist/shared/modules/dynamic/components/fields/Button.d.ts +1 -1
  17. package/dist/shared/modules/dynamic/components/fields/Card.d.ts +1 -1
  18. package/dist/shared/modules/dynamic/components/fields/Checkbox.d.ts +1 -1
  19. package/dist/shared/modules/dynamic/components/fields/ContentField.d.ts +1 -1
  20. package/dist/shared/modules/dynamic/components/fields/CustomComponent.d.ts +1 -1
  21. package/dist/shared/modules/dynamic/components/fields/DynamicProperty.d.ts +1 -1
  22. package/dist/shared/modules/dynamic/components/fields/DynamicProperty.d.ts.map +1 -1
  23. package/dist/shared/modules/dynamic/components/fields/EditorField.d.ts +1 -1
  24. package/dist/shared/modules/dynamic/components/fields/Fieldset.d.ts +1 -1
  25. package/dist/shared/modules/dynamic/components/fields/GalleryField.d.ts +1 -1
  26. package/dist/shared/modules/dynamic/components/fields/ImageField.d.ts +1 -1
  27. package/dist/shared/modules/dynamic/components/fields/InputCurrency.d.ts +1 -1
  28. package/dist/shared/modules/dynamic/components/fields/InputField.d.ts +1 -1
  29. package/dist/shared/modules/dynamic/components/fields/MultivalueField.d.ts +1 -1
  30. package/dist/shared/modules/dynamic/components/fields/RatingField.d.ts +1 -1
  31. package/dist/shared/modules/dynamic/components/fields/SelectField.d.ts +1 -1
  32. package/dist/shared/modules/dynamic/components/fields/StatusField.d.ts +1 -1
  33. package/dist/shared/modules/dynamic/components/fields/SwitchField.d.ts +1 -1
  34. package/dist/shared/modules/dynamic/components/fields/Table.d.ts +1 -1
  35. package/dist/shared/modules/dynamic/components/fields/TextareaField.d.ts +1 -1
  36. package/dist/shared/modules/dynamic/components/fields/VideoField.d.ts +1 -1
  37. package/dist/shared/modules/dynamic/components/fields/props.d.ts +1 -1
  38. package/dist/shared/modules/dynamic/components/fields/storybook/Button.stories.d.ts +3 -3
  39. package/dist/shared/modules/dynamic/components/fields/storybook/Card.stories.d.ts +3 -3
  40. package/dist/shared/modules/dynamic/components/fields/storybook/Checkbox.stories.d.ts +3 -3
  41. package/dist/shared/modules/dynamic/components/fields/storybook/ContentField.stories.d.ts +3 -3
  42. package/dist/shared/modules/dynamic/components/fields/storybook/EditorField.stories.d.ts +3 -3
  43. package/dist/shared/modules/dynamic/components/fields/storybook/Fieldset.stories.d.ts +3 -3
  44. package/dist/shared/modules/dynamic/components/fields/storybook/GalleryField.stories.d.ts +3 -3
  45. package/dist/shared/modules/dynamic/components/fields/storybook/ImageField.stories.d.ts +3 -3
  46. package/dist/shared/modules/dynamic/components/fields/storybook/InputCurrency.stories.d.ts +3 -3
  47. package/dist/shared/modules/dynamic/components/fields/storybook/InputField.stories.d.ts +3 -3
  48. package/dist/shared/modules/dynamic/components/fields/storybook/MultivalueField.stories.d.ts +3 -3
  49. package/dist/shared/modules/dynamic/components/fields/storybook/RatingField.stories.d.ts +3 -3
  50. package/dist/shared/modules/dynamic/components/fields/storybook/SelectField.stories.d.ts +3 -3
  51. package/dist/shared/modules/dynamic/components/fields/storybook/StatusField.stories.d.ts +3 -3
  52. package/dist/shared/modules/dynamic/components/fields/storybook/TextareaField.stories.d.ts +3 -3
  53. package/dist/shared/modules/dynamic/components/fields/storybook/VideoField.stories.d.ts +3 -3
  54. package/dist/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.d.ts +3 -3
  55. package/dist/shared/modules/dynamic/composables/index.d.ts +1 -0
  56. package/dist/shared/modules/dynamic/composables/index.d.ts.map +1 -1
  57. package/dist/shared/modules/dynamic/composables/useDynamicViewsUtils/index.d.ts +10 -0
  58. package/dist/shared/modules/dynamic/composables/useDynamicViewsUtils/index.d.ts.map +1 -0
  59. package/dist/shared/modules/dynamic/factories/types/index.d.ts +14 -2
  60. package/dist/shared/modules/dynamic/factories/types/index.d.ts.map +1 -1
  61. package/dist/shared/modules/dynamic/index.d.ts +2 -3
  62. package/dist/shared/modules/dynamic/index.d.ts.map +1 -1
  63. package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts +2 -1
  64. package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts.map +1 -1
  65. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts +2 -0
  66. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
  67. package/dist/tsconfig.tsbuildinfo +1 -1
  68. package/dist/ui/components/atoms/vc-card/vc-card.stories.d.ts +26 -7
  69. package/dist/ui/components/atoms/vc-card/vc-card.stories.d.ts.map +1 -1
  70. package/dist/ui/components/molecules/vc-breadcrumbs/_internal/vc-breadcrumbs-item/vc-breadcrumbs-item.vue.d.ts +1 -0
  71. package/dist/ui/components/molecules/vc-breadcrumbs/_internal/vc-breadcrumbs-item/vc-breadcrumbs-item.vue.d.ts.map +1 -1
  72. package/dist/ui/components/molecules/vc-breadcrumbs/index.d.ts +1 -13
  73. package/dist/ui/components/molecules/vc-breadcrumbs/index.d.ts.map +1 -1
  74. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.stories.d.ts +33 -0
  75. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.stories.d.ts.map +1 -1
  76. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts +14 -0
  77. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts.map +1 -1
  78. package/dist/ui/components/molecules/vc-input/vc-input.stories.d.ts +26 -7
  79. package/dist/ui/components/molecules/vc-input/vc-input.stories.d.ts.map +1 -1
  80. package/dist/ui/components/molecules/vc-input/vc-input.vue.d.ts +9 -2
  81. package/dist/ui/components/molecules/vc-input/vc-input.vue.d.ts.map +1 -1
  82. package/dist/ui/components/molecules/vc-multivalue/vc-multivalue.stories.d.ts +84 -63
  83. package/dist/ui/components/molecules/vc-multivalue/vc-multivalue.stories.d.ts.map +1 -1
  84. package/dist/ui/components/molecules/vc-multivalue/vc-multivalue.vue.d.ts +14 -10
  85. package/dist/ui/components/molecules/vc-multivalue/vc-multivalue.vue.d.ts.map +1 -1
  86. package/dist/ui/components/molecules/vc-select/vc-select.vue.d.ts.map +1 -1
  87. package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue.d.ts.map +1 -1
  88. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts +1 -1
  89. package/dist/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue.d.ts +3 -9
  90. package/dist/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue.d.ts.map +1 -1
  91. package/dist/ui/types/index.d.ts +3 -2
  92. package/dist/ui/types/index.d.ts.map +1 -1
  93. package/package.json +4 -4
  94. package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +84 -38
  95. package/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.ts +11 -4
  96. package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +37 -54
  97. package/shared/components/blade-navigation/types/index.ts +1 -1
  98. package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +2 -2
  99. package/shared/modules/dynamic/components/fields/DynamicProperty.ts +7 -3
  100. package/shared/modules/dynamic/components/fields/GalleryField.ts +1 -1
  101. package/shared/modules/dynamic/composables/index.ts +1 -0
  102. package/shared/modules/dynamic/composables/useDynamicViewsUtils/index.ts +46 -0
  103. package/shared/modules/dynamic/factories/types/index.ts +17 -2
  104. package/shared/modules/dynamic/index.ts +2 -3
  105. package/shared/modules/dynamic/pages/dynamic-blade-form.vue +1 -0
  106. package/shared/modules/dynamic/pages/dynamic-blade-list.vue +7 -1
  107. package/ui/components/molecules/vc-breadcrumbs/_internal/vc-breadcrumbs-item/vc-breadcrumbs-item.vue +3 -0
  108. package/ui/components/molecules/vc-breadcrumbs/index.ts +1 -3
  109. package/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +124 -5
  110. package/ui/components/molecules/vc-input/vc-input.vue +58 -18
  111. package/ui/components/molecules/vc-multivalue/vc-multivalue.vue +124 -83
  112. package/ui/components/molecules/vc-select/vc-select.vue +42 -17
  113. package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +10 -14
  114. package/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue +49 -16
  115. package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +1 -1
  116. package/ui/types/index.ts +3 -2
@@ -94,7 +94,7 @@ export interface BladeVNode extends VNode {
94
94
  onOpen?: () => void;
95
95
  onClose?: () => void;
96
96
  onBeforeClose?: () => Promise<boolean | undefined>;
97
- instance: Ref<CoreBladeExposed | undefined | null>;
97
+ instance: CoreBladeExposed | undefined | null;
98
98
  idx: number;
99
99
  };
100
100
  onVnodeUnmounted?: VNodeMountHook | VNodeMountHook[];
@@ -40,13 +40,13 @@
40
40
  icon="fas fa-cloud-upload-alt"
41
41
  class="tw-text-[100px] tw-text-[#41afe6]"
42
42
  ></VcIcon>
43
- <div class="tw-m-4 tw-text-xl tw-font-medium">
43
+ <div class="tw-m-4 tw-text-xl tw-font-medium tw-text-center">
44
44
  {{ t("ASSETS_MANAGER.EMPTY.UPLOAD_ASSETS") }}
45
45
  </div>
46
46
  <VcButton @click="toggleUploader">{{ t("ASSETS_MANAGER.EMPTY.UPLOAD") }}</VcButton>
47
47
  </template>
48
48
  <template v-else>
49
- <div class="tw-m-4 tw-text-xl tw-font-medium">
49
+ <div class="tw-m-4 tw-text-xl tw-font-medium tw-text-center">
50
50
  {{ t("ASSETS_MANAGER.EMPTY.NO_ASSETS") }}
51
51
  </div>
52
52
  </template>
@@ -85,17 +85,21 @@ export default {
85
85
  ),
86
86
  ),
87
87
  optionsGetter: props.bladeContext.scope?.dynamicProperties?.loadDictionaries as (
88
- property: Record<string, any>,
88
+ propertyId: string,
89
89
  keyword?: string | undefined,
90
90
  locale?: string | undefined,
91
91
  ) => Promise<Record<string, any>[]>,
92
92
  "onUpdate:model-value": (args: {
93
- property: Record<string, any>;
94
93
  value: string | Record<string, any>[];
95
94
  dictionary?: Record<string, any>[];
96
95
  locale?: string;
97
96
  }) => {
98
- props.bladeContext.scope?.dynamicProperties?.setPropertyValue(args);
97
+ props.bladeContext.scope?.dynamicProperties?.setPropertyValue({
98
+ property: prop,
99
+ value: args.value,
100
+ dictionary: args.dictionary,
101
+ locale: args.locale,
102
+ });
99
103
  if (props.fieldContext) {
100
104
  setModel({ context: props.fieldContext, property: props.element.property, value: internalModel.value });
101
105
  }
@@ -83,7 +83,7 @@ export default {
83
83
  t(
84
84
  `${props.bladeContext?.settings?.localizationPrefix
85
85
  .trim()
86
- .toUpperCase()}.PAGES.DETAILS.ALERTS.DELETE_CONFIRMATION`,
86
+ .toUpperCase()}.PAGES.ALERTS.IMAGE_DELETE_CONFIRMATION`,
87
87
  ),
88
88
  ),
89
89
  )
@@ -1,3 +1,4 @@
1
1
  export { default as useFilterBuilder } from "./useFilterBuilder";
2
2
  export { useTableTemplates } from "./useTableTemplates";
3
3
  export { useToolbarReducer } from "./useToolbarReducer";
4
+ export { default as useDynamicViewsUtils } from "./useDynamicViewsUtils";
@@ -0,0 +1,46 @@
1
+ import { ref, WatchStopHandle, watch, onMounted, onUnmounted, getCurrentInstance, Ref } from "vue";
2
+ import { ListBaseBladeScope, DetailsBaseBladeScope, DetailsBladeExposed, ListBladeExposed } from "../..";
3
+
4
+ export interface IUseDynamicViewsUtils {
5
+ getBladeExposedData: <BladeScope extends ListBaseBladeScope | DetailsBaseBladeScope>(
6
+ scope: BladeScope,
7
+ ) => BladeScope extends ListBaseBladeScope ? Ref<ListBladeExposed<BladeScope>> : Ref<DetailsBladeExposed<BladeScope>>;
8
+ }
9
+
10
+ export default () => {
11
+ const instance = getCurrentInstance();
12
+
13
+ function getBladeExposedData<BladeScope extends ListBaseBladeScope | DetailsBaseBladeScope>() {
14
+ const reactiveBlade = ref<BladeScope | null>(null);
15
+
16
+ const blade = ref(instance?.vnode);
17
+
18
+ let unwatch: WatchStopHandle | null = null;
19
+
20
+ const updateReactiveBlade = () => {
21
+ if (blade.value && blade.value.props?.navigation?.instance) {
22
+ reactiveBlade.value = blade.value.props.navigation.instance;
23
+ }
24
+ };
25
+
26
+ unwatch = watch(blade, updateReactiveBlade, { immediate: true, deep: true });
27
+
28
+ onMounted(() => {
29
+ updateReactiveBlade();
30
+ });
31
+
32
+ onUnmounted(() => {
33
+ if (unwatch) {
34
+ unwatch();
35
+ }
36
+ });
37
+
38
+ return reactiveBlade as unknown as BladeScope extends ListBaseBladeScope
39
+ ? Ref<ListBladeExposed<BladeScope>>
40
+ : Ref<DetailsBladeExposed<BladeScope>>;
41
+ }
42
+
43
+ return {
44
+ getBladeExposedData,
45
+ };
46
+ };
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { ComputedRef, MaybeRef, Ref, UnwrapNestedRefs } from "vue";
3
3
  import { AsyncAction } from "../../../../../core/composables";
4
- import { SettingsSchema } from "../../types";
4
+ import { SettingsDetails, SettingsGrid, SettingsSchema } from "../../types";
5
5
  import { AssetsHandler, IBladeToolbar, ICommonAsset } from "../../../../../core/types";
6
6
  import { useBladeNavigation } from "../../../../components";
7
7
  import { FormContext } from "vee-validate";
@@ -96,7 +96,7 @@ export interface DetailsBaseBladeScope extends BaseBladeScope {
96
96
  dynamicProperties?: {
97
97
  loading: ComputedRef<boolean>;
98
98
  loadDictionaries: (
99
- property: Record<string, any>,
99
+ propertyId: string,
100
100
  keyword?: string,
101
101
  locale?: string,
102
102
  ) => Promise<Record<string, any>[] | undefined>;
@@ -122,3 +122,18 @@ export interface ListBladeContext extends UseList<Record<string, any>[], Record<
122
122
  settings: ComputedRef<SettingsSchema>;
123
123
  selectedIds: ComputedRef<string[]>;
124
124
  }
125
+
126
+ export interface BaseBladeExposed {
127
+ updateActiveWidgetCount: () => void;
128
+ readonly title: MaybeRef<string>;
129
+ }
130
+
131
+ export type ListBladeExposed<Scope extends ListBaseBladeScope> = BaseBladeExposed & {
132
+ readonly selectedIds: string[];
133
+ reload: () => void;
134
+ readonly settings: SettingsGrid;
135
+ } & UnwrapNestedRefs<Scope>;
136
+
137
+ export type DetailsBladeExposed<Scope extends DetailsBaseBladeScope> = BaseBladeExposed & {
138
+ readonly settings: SettingsDetails;
139
+ } & UnwrapNestedRefs<Scope>;
@@ -171,8 +171,7 @@ export const createDynamicAppModule = (args: {
171
171
  };
172
172
  };
173
173
 
174
- export * from "./pages";
175
- export * from "./composables";
176
- export * from "./components";
177
174
  export * from "./factories";
178
175
  export * from "./types";
176
+ export * from "./pages";
177
+ export { useDynamicViewsUtils } from "./composables";
@@ -357,6 +357,7 @@ defineExpose({
357
357
  title: bladeTitle ?? "",
358
358
  updateActiveWidgetCount,
359
359
  ...toRefs(scope?.value ?? {}),
360
+ settings: toValue(settings),
360
361
  });
361
362
  </script>
362
363
 
@@ -262,6 +262,9 @@ const { load, remove, items, loading, pagination, query, scope } = props.composa
262
262
  emit,
263
263
  props,
264
264
  mounted: useMounted(),
265
+ /**
266
+ * @deprecated use `useDynamicViewsUtils` instead. This will be removed in the next major version.
267
+ */
265
268
  bladeContext: {
266
269
  settings,
267
270
  selectedIds: computed(() => selectedIds.value),
@@ -382,7 +385,8 @@ const toolbarComputed =
382
385
  [];
383
386
 
384
387
  onBeforeMount(async () => {
385
- if (props.composables) await load({ sort: sort.value, ...query.value, ...getNavigationQuery() });
388
+ if (props.composables)
389
+ await load({ sort: sort.value, ...query.value, ...(props.isWidgetView ? {} : getNavigationQuery()) });
386
390
  });
387
391
 
388
392
  watch(
@@ -658,5 +662,7 @@ defineExpose({
658
662
  title,
659
663
  updateActiveWidgetCount,
660
664
  ...toRefs(scope?.value ?? {}),
665
+ selectedIds,
666
+ settings: toValue(settings),
661
667
  });
662
668
  </script>
@@ -3,6 +3,7 @@
3
3
  class="vc-breadcrumbs-item"
4
4
  :class="{
5
5
  'vc-breadcrumbs-item_current': current,
6
+ 'tw-px-1 tw-h-[var(--breadcrumbs-item-height-light)]': variant === 'light',
6
7
  }"
7
8
  @click="onClick"
8
9
  >
@@ -24,6 +25,7 @@ import { VcIcon } from "./../../../../";
24
25
 
25
26
  export interface Props extends Breadcrumbs {
26
27
  current: boolean;
28
+ variant?: "default" | "light";
27
29
  }
28
30
 
29
31
  export interface Emits {
@@ -48,6 +50,7 @@ function onClick(): void {
48
50
  <style lang="scss">
49
51
  :root {
50
52
  --breadcrumbs-item-height: 28px;
53
+ --breadcrumbs-item-height-light: 20px;
51
54
  --breadcrumbs-item-border-color: #a1c0d4;
52
55
  --breadcrumbs-item-border-color-hover: #8fb0c6;
53
56
  --breadcrumbs-item-border-color-current: #838d9a;
@@ -1,3 +1 @@
1
- import _Breadcrumbs from "./vc-breadcrumbs.vue";
2
-
3
- export const VcBreadcrumbs = _Breadcrumbs as typeof _Breadcrumbs;
1
+ export { default as VcBreadcrumbs } from "./vc-breadcrumbs.vue";
@@ -1,26 +1,145 @@
1
1
  <template>
2
2
  <div
3
3
  v-if="items && items.length"
4
+ ref="el"
4
5
  class="tw-flex tw-items-center tw-flex-wrap tw-gap-[10px]"
5
6
  >
6
7
  <VcBreadcrumbsItem
7
- v-for="(item, i) in items"
8
- :key="item?.id ?? `item-${i}`"
9
- v-bind="item"
10
- :current="i === items.length - 1"
8
+ v-if="items.length"
9
+ :id="items[0]?.id"
10
+ :title="items[0]?.title"
11
+ :current="items.length === 1"
12
+ :variant="variant"
13
+ @click="items[0]?.clickHandler && items[0]?.clickHandler(items[0]?.id)"
14
+ >
15
+ </VcBreadcrumbsItem>
16
+ <VcIcon
17
+ v-if="withArrow && canExpand"
18
+ :icon="arrowIcon"
19
+ :size="arrowSize"
20
+ class="tw-text-[color:var(--chevron-color)]"
11
21
  />
22
+ <VcBreadcrumbsItem
23
+ v-if="canExpand"
24
+ id="Expand"
25
+ :current="false"
26
+ title="..."
27
+ :variant="variant"
28
+ @click="expand"
29
+ >
30
+ </VcBreadcrumbsItem>
31
+ <template
32
+ v-for="(item, i) in visibleBreadcrumbs"
33
+ :key="item?.id ?? `breadcrumb-item-${i}`"
34
+ >
35
+ <div v-if="item && item.title && item.isVisible">
36
+ <VcIcon
37
+ v-if="withArrow && i < items.length - 1"
38
+ :icon="arrowIcon"
39
+ :size="arrowSize"
40
+ class="tw-text-[color:var(--chevron-color)] tw-mr-[10px]"
41
+ />
42
+ <VcBreadcrumbsItem
43
+ v-bind="item"
44
+ :current="i === items.length - 1"
45
+ :variant="variant"
46
+ />
47
+ </div>
48
+ </template>
12
49
  </div>
13
50
  </template>
14
51
 
15
52
  <script lang="ts" setup>
16
53
  import { Breadcrumbs } from "../../../types";
17
54
  import VcBreadcrumbsItem from "./_internal/vc-breadcrumbs-item/vc-breadcrumbs-item.vue";
55
+ import { VcIcon } from "./../../atoms/vc-icon";
56
+ import { useElementBounding } from "@vueuse/core";
57
+ import { MaybeRef, Ref, computed, ref, toRefs, toValue, watch } from "vue";
58
+ import * as _ from "lodash-es";
18
59
 
19
60
  export interface Props {
20
61
  items?: Breadcrumbs[];
62
+ variant?: "default" | "light";
63
+ withArrow?: boolean;
64
+ arrowIcon?: string;
65
+ arrowSize?: InstanceType<typeof VcIcon>["$props"]["size"];
66
+ }
67
+
68
+ interface InternalBreadcrumbs extends Breadcrumbs {
69
+ isVisible?: boolean;
21
70
  }
22
71
 
23
- withDefaults(defineProps<Props>(), {
72
+ const props = withDefaults(defineProps<Props>(), {
24
73
  items: () => [],
74
+ variant: "default",
75
+ arrowIcon: "fas fa-chevron-right",
76
+ arrowSize: "xs",
25
77
  });
78
+
79
+ const el = ref(null);
80
+ const visibleBreadcrumbs = ref([]) as Ref<InternalBreadcrumbs[]>;
81
+
82
+ const { width } = useElementBounding(el);
83
+
84
+ const { items } = toRefs(props);
85
+
86
+ const canExpand = computed(
87
+ () =>
88
+ visibleBreadcrumbs.value &&
89
+ _.some(
90
+ visibleBreadcrumbs.value,
91
+ (breadcrumb) => !(typeof breadcrumb?.isVisible === "undefined" ? true : breadcrumb.isVisible),
92
+ ),
93
+ );
94
+
95
+ watch(items, computeVisibleBreadcrumbs, { deep: true });
96
+
97
+ function computeVisibleBreadcrumbs(breadcrumbs: InternalBreadcrumbs[]) {
98
+ if (!(breadcrumbs && breadcrumbs.length)) return [];
99
+
100
+ const expanderWidth = 40;
101
+ const availableWidth = width.value;
102
+ let widthOfItems = calculateTotalWidth(breadcrumbs[0].title);
103
+
104
+ const items = _.tail(_.cloneDeep(breadcrumbs)).reverse();
105
+
106
+ for (let i = 0; i < items.length; i++) {
107
+ const x = items[i];
108
+ const elWidth = calculateTotalWidth(x.title);
109
+ if (widthOfItems + elWidth <= availableWidth) {
110
+ x.isVisible = true;
111
+ widthOfItems += elWidth;
112
+ } else {
113
+ if (i > 0) items[i - 1].isVisible = false;
114
+ widthOfItems += expanderWidth;
115
+ if (widthOfItems > availableWidth) break;
116
+ }
117
+ }
118
+
119
+ visibleBreadcrumbs.value = items.reverse();
120
+ }
121
+
122
+ function calculateTotalWidth(title: MaybeRef<string | undefined>) {
123
+ const unrefTitle = toValue(title);
124
+ if (!unrefTitle) return 0;
125
+
126
+ const paddings = 40;
127
+ const averageCharacterWidth = 4.87;
128
+
129
+ const wordWidth = Math.floor(unrefTitle.length * averageCharacterWidth) + paddings;
130
+
131
+ return wordWidth;
132
+ }
133
+
134
+ function expand() {
135
+ visibleBreadcrumbs.value.forEach((breadcrumb) => {
136
+ breadcrumb.isVisible = true;
137
+ });
138
+ }
26
139
  </script>
140
+
141
+ <style lang="scss">
142
+ :root {
143
+ --chevron-color: #a1c0d4;
144
+ }
145
+ </style>
@@ -54,22 +54,22 @@
54
54
  name="control"
55
55
  :editable="disabled"
56
56
  :focused="autofocus"
57
- :model-value="temp"
57
+ :model-value="handleValue"
58
58
  :emit-value="emitValue"
59
59
  :placeholder="placeholder"
60
60
  >
61
61
  <input
62
62
  ref="inputRef"
63
- v-model="temp"
63
+ v-model="handleValue"
64
64
  :placeholder="placeholder"
65
- :type="internalType"
65
+ :type="internalTypeComputed"
66
66
  :disabled="disabled"
67
67
  :name="name"
68
68
  :maxlength="maxlength"
69
69
  :autofocus="autofocus"
70
70
  :max="maxDate"
71
71
  class="vc-input__input"
72
- @input="onInput"
72
+ @keydown="onKeyDown"
73
73
  />
74
74
  </slot>
75
75
  <div
@@ -191,7 +191,11 @@ export interface Props {
191
191
  * Input type
192
192
  * Default value: text
193
193
  */
194
- type?: "text" | "password" | "email" | "tel" | "number" | "url" | "time" | "date" | "datetime-local";
194
+ type?: "text" | "password" | "email" | "tel" | "number" | "integer" | "url" | "time" | "date" | "datetime-local";
195
+ /**
196
+ * The step attribute is a number that specifies the granularity that the value must adhere to.
197
+ */
198
+ step?: string;
195
199
  /**
196
200
  * Input description (hint) text below input component
197
201
  */
@@ -271,6 +275,7 @@ const props = withDefaults(defineProps<Props>(), {
271
275
  type: "text",
272
276
  name: "Field",
273
277
  maxlength: "1024",
278
+ step: "1",
274
279
  });
275
280
 
276
281
  const emit = defineEmits<Emits>();
@@ -336,18 +341,45 @@ const inputRef = ref();
336
341
 
337
342
  const internalType = ref(unref(props.type));
338
343
 
344
+ const internalTypeComputed = computed({
345
+ get() {
346
+ if (internalType.value === "integer") {
347
+ return "number";
348
+ }
349
+ return internalType.value;
350
+ },
351
+ set(value) {
352
+ internalType.value = value;
353
+ },
354
+ });
355
+
339
356
  const maxDate = computed(() => (props.type === "date" && "9999-12-31") || undefined);
340
357
 
341
358
  const rawModel = computed(() => unref(props.modelValue));
359
+ const handleValue = computed({
360
+ get() {
361
+ return props.type === "integer" || props.type === "number" ? (isNaN(temp.value) ? "" : temp.value) : temp.value;
362
+ },
363
+ set(value) {
364
+ temp.value = value;
365
+ onInput(value);
366
+ },
367
+ });
342
368
  const mutatedModel = ref();
343
369
 
344
370
  watch(
345
371
  rawModel,
346
372
  (newVal) => {
347
- if (internalType.value === "datetime-local" && newVal instanceof Date && !isNaN(newVal.valueOf())) {
348
- mutatedModel.value = moment(newVal).format("YYYY-MM-DDTHH:mm");
349
- } else if (internalType.value === "date" && newVal instanceof Date && !isNaN(newVal.valueOf())) {
350
- mutatedModel.value = moment(newVal).format("YYYY-MM-DD");
373
+ if (props.type === "datetime-local" || props.type === "date") {
374
+ if (newVal instanceof Date && !isNaN(newVal.valueOf())) {
375
+ mutatedModel.value = moment(newVal).format(props.type === "datetime-local" ? "YYYY-MM-DDTHH:mm" : "YYYY-MM-DD");
376
+ } else if (typeof newVal === "string") {
377
+ mutatedModel.value = new Date(newVal).toISOString().slice(0, props.type === "datetime-local" ? 16 : 10);
378
+ }
379
+ } else if (props.type === "number" && newVal !== null) {
380
+ mutatedModel.value = parseFloat(newVal as string);
381
+ } else if (props.type === "integer" && newVal !== null) {
382
+ mutatedModel.value = Math.trunc(newVal as number);
351
383
  } else {
352
384
  mutatedModel.value = newVal;
353
385
  }
@@ -359,24 +391,32 @@ watch(
359
391
  { immediate: true },
360
392
  );
361
393
 
362
- // Handle input event and emit changes
363
- function onInput(e: Event) {
364
- if (!e || !e.target) {
365
- return;
394
+ function onKeyDown(e: KeyboardEvent) {
395
+ const allowedKeys = ["Backspace", "Delete", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
396
+ const keypressed = e.key;
397
+ if (props.type === "integer") {
398
+ if (!/^\d$/.test(keypressed) && !allowedKeys.includes(keypressed)) {
399
+ e.preventDefault();
400
+ return;
401
+ }
366
402
  }
403
+ }
367
404
 
368
- const newValue = (e.target as HTMLInputElement).value;
369
- emitValue(newValue);
405
+ // Handle input event and emit changes
406
+ function onInput(value: string | number | Date | null) {
407
+ emitValue(value);
370
408
  }
371
409
 
372
410
  function emitValue(val: string | number | Date | null) {
373
411
  emitValueFn = () => {
374
412
  if (mutatedModel.value !== val) {
375
413
  let value;
376
- if (internalType.value === "datetime-local" || internalType.value === "date") {
414
+ if (internalTypeComputed.value === "datetime-local" || internalTypeComputed.value === "date") {
377
415
  value = val ? moment(val).toDate() : undefined;
378
- } else if (internalType.value === "number" && val !== null) {
379
- value = +val;
416
+ } else if (props.type === "number" && val !== null) {
417
+ value = parseFloat(val as string);
418
+ } else if (props.type === "integer" && val !== null) {
419
+ value = Math.trunc(parseInt(val as string));
380
420
  } else {
381
421
  value = val;
382
422
  }