@vc-shell/framework 1.0.213 → 1.0.214

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.
@@ -32,6 +32,9 @@ declare const _default: {
32
32
  type: import("vue").PropType<import("../../../..").IBladeToolbar[]>;
33
33
  default: () => never[];
34
34
  };
35
+ hasUnsavedChanges: {
36
+ type: import("vue").PropType<boolean>;
37
+ };
35
38
  }>> & {
36
39
  onClose?: (() => any) | undefined;
37
40
  onExpand?: (() => any) | undefined;
@@ -69,6 +72,9 @@ declare const _default: {
69
72
  type: import("vue").PropType<import("../../../..").IBladeToolbar[]>;
70
73
  default: () => never[];
71
74
  };
75
+ hasUnsavedChanges: {
76
+ type: import("vue").PropType<boolean>;
77
+ };
72
78
  }>> & {
73
79
  onClose?: (() => any) | undefined;
74
80
  onExpand?: (() => any) | undefined;
@@ -114,6 +120,9 @@ declare const _default: {
114
120
  type: import("vue").PropType<import("../../../..").IBladeToolbar[]>;
115
121
  default: () => never[];
116
122
  };
123
+ hasUnsavedChanges: {
124
+ type: import("vue").PropType<boolean>;
125
+ };
117
126
  }>> & {
118
127
  onClose?: (() => any) | undefined;
119
128
  onExpand?: (() => any) | undefined;
@@ -156,6 +165,9 @@ declare const _default: {
156
165
  type: import("vue").PropType<import("../../../..").IBladeToolbar[]>;
157
166
  default: () => never[];
158
167
  };
168
+ hasUnsavedChanges: {
169
+ type: import("vue").PropType<boolean>;
170
+ };
159
171
  }>> & {
160
172
  onClose?: (() => any) | undefined;
161
173
  onExpand?: (() => any) | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"vc-blade.stories.d.ts","sourceRoot":"","sources":["../../../../../ui/components/organisms/vc-blade/vc-blade.stories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG7B,wBAuBiC;AAEjC,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,OAAO,OAAO,CAM1C,CAAC;AAEH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,OAAO,OAAO,CAOjD,CAAC;AAEH,eAAO,MAAM,gBAAgB,EAAE,OAAO,CAAC,OAAO,OAAO,CAMnD,CAAC;AAEH,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,OAAO,OAAO,CAShD,CAAC;AAEH,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,OAAO,OAAO,CASlD,CAAC;AAEH,eAAO,MAAM,mBAAmB,EAAE,OAAO,CAAC,OAAO,OAAO,CAMtD,CAAC"}
1
+ {"version":3,"file":"vc-blade.stories.d.ts","sourceRoot":"","sources":["../../../../../ui/components/organisms/vc-blade/vc-blade.stories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG7B,wBAuBiC;AAEjC,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,OAAO,OAAO,CAM1C,CAAC;AAEH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,OAAO,OAAO,CAOjD,CAAC;AAEH,eAAO,MAAM,gBAAgB,EAAE,OAAO,CAAC,OAAO,OAAO,CAMnD,CAAC;AAEH,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,OAAO,OAAO,CAShD,CAAC;AAEH,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,OAAO,OAAO,CASlD,CAAC;AAEH,eAAO,MAAM,mBAAmB,EAAE,OAAO,CAAC,OAAO,OAAO,CAMtD,CAAC"}
@@ -8,6 +8,7 @@ export interface Props {
8
8
  expandable?: boolean;
9
9
  closable?: boolean;
10
10
  toolbarItems?: IBladeToolbar[];
11
+ hasUnsavedChanges?: boolean;
11
12
  }
12
13
  export interface Emits {
13
14
  (event: "close"): void;
@@ -1 +1 @@
1
- {"version":3,"file":"vc-blade.vue.d.ts","sourceRoot":"","sources":["../../../../../ui/components/organisms/vc-blade/vc-blade.vue.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAQvD,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,aAAa,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4PD,wBAAwG;AACxG,KAAK,sBAAsB,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;AACjE,KAAK,6BAA6B,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE;CAAE,CAAC;AAC9M,KAAK,kBAAkB,CAAC,CAAC,EAAE,CAAC,IAAI;KAE1B,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;QACxE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;KACb,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACT,CAAC;AACN,KAAK,cAAc,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC;AACxD,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAAE,QAAO;QAClD,MAAM,EAAE,CAAC,CAAC;KACT,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"vc-blade.vue.d.ts","sourceRoot":"","sources":["../../../../../ui/components/organisms/vc-blade/vc-blade.vue.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAQvD,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,aAAa,EAAE,CAAC;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4RD,wBAAwG;AACxG,KAAK,sBAAsB,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;AACjE,KAAK,6BAA6B,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE;CAAE,CAAC;AAC9M,KAAK,kBAAkB,CAAC,CAAC,EAAE,CAAC,IAAI;KAE1B,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;QACxE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;KACb,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACT,CAAC;AACN,KAAK,cAAc,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC;AACxD,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAAE,QAAO;QAClD,MAAM,EAAE,CAAC,CAAC;KACT,CAAA;CAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vc-shell/framework",
3
- "version": "1.0.213",
3
+ "version": "1.0.214",
4
4
  "type": "module",
5
5
  "main": "./dist/framework.js",
6
6
  "types": "./dist/index.d.ts",
@@ -59,9 +59,9 @@
59
59
  "devDependencies": {
60
60
  "@types/dompurify": "^3.0.5",
61
61
  "@types/quill": "^2.0.14",
62
- "@vc-shell/api-client-generator": "^1.0.213",
63
- "@vc-shell/config-generator": "^1.0.213",
64
- "@vc-shell/ts-config": "^1.0.213",
62
+ "@vc-shell/api-client-generator": "^1.0.214",
63
+ "@vc-shell/config-generator": "^1.0.214",
64
+ "@vc-shell/ts-config": "^1.0.214",
65
65
  "@vitejs/plugin-vue": "^5.0.3",
66
66
  "sass": "^1.69.6",
67
67
  "shx": "^0.3.4",
@@ -38,7 +38,7 @@ export const useDetailsFactory = <Item>(factoryParams: UseDetailsFactoryParams<I
38
38
  } else throw new Error("Form is not valid");
39
39
  });
40
40
 
41
- const { loading: removeLoading, action: remove } = useAsync<ItemId>(async (args) => {
41
+ const { loading: removeLoading, action: remove } = useAsync<ItemId | Item>(async (args) => {
42
42
  await factoryParams.remove?.(args as ItemId);
43
43
  });
44
44
 
@@ -84,6 +84,7 @@ export interface ListBaseBladeScope<Item = Record<string, any>, Query = Record<s
84
84
  ) => void;
85
85
  onPaginationClick?: (query: Query) => void;
86
86
  breadcrumbs?: ComputedRef<Breadcrumbs[]>;
87
+ modified?: ComputedRef<boolean> | Ref<boolean> | boolean;
87
88
  }
88
89
 
89
90
  export type TOpenBladeArgs = Omit<Parameters<ReturnType<typeof useBladeNavigation>["openBlade"]>["0"], "blade">;
@@ -7,6 +7,7 @@
7
7
  :width="settings?.width || '50%'"
8
8
  :toolbar-items="toolbarComputed"
9
9
  :title="title"
10
+ :has-unsaved-changes="isFormModified"
10
11
  @close="$emit('close:blade')"
11
12
  @expand="$emit('expand:blade')"
12
13
  @collapse="$emit('collapse:blade')"
@@ -104,7 +105,7 @@ import { notification } from "../../../components";
104
105
  interface Props {
105
106
  expanded?: boolean;
106
107
  closable?: boolean;
107
- param?: string;
108
+ param?: string | any;
108
109
  model?: DynamicDetailsSchema;
109
110
  options?: {
110
111
  [x: string]: unknown;
@@ -10,6 +10,7 @@
10
10
  :class="{
11
11
  'tw-flex tw-flex-auto': isWidgetView,
12
12
  }"
13
+ :has-unsaved-changes="unref(scope)?.modified"
13
14
  @close="$emit('close:blade')"
14
15
  @expand="$emit('expand:blade')"
15
16
  @collapse="$emit('collapse:blade')"
@@ -39,20 +40,20 @@
39
40
  class="tw-grow tw-basis-0"
40
41
  :loading="loading"
41
42
  :expanded="expanded"
42
- :columns="(tableColsWithLocales as ITableColumns[]) ?? []"
43
+ :columns="tableColsWithLocales ?? []"
43
44
  :state-key="stateKey ?? ''"
44
- :items="itemsProxy as Record<string, any>[]"
45
+ :items="itemsProxy ?? []"
45
46
  :multiselect="isWidgetView ? false : tableData?.multiselect"
46
47
  :header="isWidgetView ? false : tableData?.header"
47
48
  :item-action-builder="actionBuilder"
48
49
  :enable-item-actions="!!tableData?.actions && !isWidgetView"
49
- :footer="!isWidgetView"
50
+ :footer="isWidgetView ? false : tableData?.footer"
50
51
  :sort="sort"
51
52
  :pages="pagination?.pages"
52
53
  :current-page="pagination?.currentPage"
53
54
  :search-value="searchValue"
54
55
  :selected-item-id="selectedItemId"
55
- :total-label="$t(`${settings?.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.TABLE.TOTALS`)"
56
+ :total-label="$t(`${localizationPrefix}.PAGES.LIST.TABLE.TOTALS`)"
56
57
  :total-count="pagination?.totalCount"
57
58
  :active-filter-count="activeFilterCount"
58
59
  :reorderable-rows="isWidgetView ? false : tableData?.reorderableRows"
@@ -87,12 +88,12 @@
87
88
  <template v-else>
88
89
  <div class="tw-w-full tw-h-full tw-box-border tw-flex tw-flex-col tw-items-center tw-justify-center">
89
90
  <div class="tw-m-4 tw-text-xl tw-font-medium">
90
- {{ $t(`${settings?.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.NOT_FOUND.EMPTY`) }}
91
+ {{ $t(`${localizationPrefix}.PAGES.LIST.NOT_FOUND.EMPTY`) }}
91
92
  </div>
92
93
  <VcButton
93
94
  v-if="isFilterVisible"
94
95
  @click="resetSearch"
95
- >{{ $t(`${settings?.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.NOT_FOUND.RESET`) }}</VcButton
96
+ >{{ $t(`${localizationPrefix}.PAGES.LIST.NOT_FOUND.RESET`) }}</VcButton
96
97
  >
97
98
  </div>
98
99
  </template>
@@ -113,7 +114,7 @@
113
114
  <template v-else>
114
115
  <div class="tw-w-full tw-h-full tw-box-border tw-flex tw-flex-col tw-items-center tw-justify-center">
115
116
  <div class="tw-m-4 tw-text-xl tw-font-medium">
116
- {{ $t(`${settings?.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.EMPTY.NO_ITEMS`) }}
117
+ {{ $t(`${localizationPrefix}.PAGES.LIST.EMPTY.NO_ITEMS`) }}
117
118
  </div>
118
119
  </div>
119
120
  </template>
@@ -180,7 +181,7 @@ import { safeIn } from "../helpers/safeIn";
180
181
  export interface Props {
181
182
  expanded?: boolean;
182
183
  closable?: boolean;
183
- param?: string;
184
+ param?: string | any;
184
185
  options?: unknown;
185
186
  model?: DynamicGridSchema;
186
187
  composables?: Record<string, (...args: any[]) => Record<string, any>>;
@@ -210,6 +211,7 @@ const { debounce } = useFunctions();
210
211
  const emit = defineEmits<Emits>();
211
212
 
212
213
  const settings = computed(() => props.model?.settings);
214
+ const localizationPrefix = computed(() => settings.value?.localizationPrefix.trim().toUpperCase());
213
215
  const title = computed(() => t(settings.value?.titleTemplate as string));
214
216
  const allSelected = ref(false);
215
217
  const searchValue = ref();
@@ -217,7 +219,6 @@ const selectedItemId = shallowRef();
217
219
  const sort = shallowRef("createdDate:DESC");
218
220
  const selectedIds = shallowRef<string[]>([]);
219
221
  const itemsProxy = ref<Record<string, any>[]>();
220
- const modified = shallowRef(false);
221
222
 
222
223
  const { moduleNotifications, markAsRead } = useNotifications(settings.value?.pushNotificationType);
223
224
  const { setNavigationQuery, getNavigationQuery } = useBladeNavigation();
@@ -242,7 +243,10 @@ const tableData =
242
243
  props.composables &&
243
244
  computed(() => props.model?.content.find((type: ListContentSchema) => type.component === "vc-table"));
244
245
 
245
- const tableColsWithLocales = tableData?.value?.columns?.map((col) => ({ ...col, title: computed(() => t(col.title)) }));
246
+ const tableColsWithLocales = tableData?.value?.columns?.map((col) => ({
247
+ ...col,
248
+ title: computed(() => t(col.title)),
249
+ })) as ITableColumns[];
246
250
 
247
251
  const stateKey =
248
252
  props.composables &&
@@ -348,12 +352,6 @@ const toolbarComputed =
348
352
  useToolbarReducer({
349
353
  defaultToolbarSchema: settings.value?.toolbar ?? [],
350
354
  defaultToolbarBindings: {
351
- save: {
352
- clickHandler() {
353
- emit("close:blade");
354
- },
355
- disabled: computed(() => !modified.value),
356
- },
357
355
  openAddBlade: {
358
356
  async clickHandler() {
359
357
  if (
@@ -398,14 +396,6 @@ watch(
398
396
  { immediate: true },
399
397
  );
400
398
 
401
- watch(
402
- () => itemsProxy.value,
403
- (newVal) => {
404
- modified.value = !_.isEqual(newVal, items.value);
405
- },
406
- { deep: true },
407
- );
408
-
409
399
  watch(sort, async (value) => {
410
400
  await load({ ...query.value, sort: value });
411
401
  });
@@ -8,7 +8,7 @@
8
8
  >
9
9
  <span>{{ label }}</span>
10
10
  </VcLabel>
11
- <div class="tw-relative tw-inline-block tw-w-[54px] tw-h-[18px]">
11
+ <div class="tw-relative tw-inline-block tw-w-[32px] tw-h-[18px]">
12
12
  <label>
13
13
  <input
14
14
  type="checkbox"
@@ -63,11 +63,9 @@ function onInput(e: Event) {
63
63
  <style lang="scss">
64
64
  :root {
65
65
  --switch-main-color: #43b0e6;
66
- --switch-secondary-color: #565656;
66
+ --switch-secondary-color: #d2d4d7;
67
67
  --switch-transition: all 0.2s ease-in-out;
68
68
  --switch-icon-transition: opacity 0.3s ease-in-out;
69
- --switch-active-icon: url("data:image/svg+xml;utf8,<svg width='10' height='8' viewBox='0 0 10 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M3.73609 7.34288L0.161085 3.85628C-0.0536949 3.64681 -0.0536949 3.30718 0.161085 3.09769L0.938884 2.3391C1.15366 2.12961 1.50193 2.12961 1.71671 2.3391L4.125 4.68782L8.28329 0.657101C8.49807 0.447633 8.84634 0.447633 9.06112 0.657101L9.83892 1.41569C10.0537 1.62516 10.0537 1.96479 9.83892 2.17428L4.51391 7.3429C4.29911 7.55237 3.95087 7.55237 3.73609 7.34288Z' fill='white'/></svg>");
70
- --switch-disabled-icon: url("data:image/svg+xml;utf8,<svg width='8' height='8' viewBox='0 0 8 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M5.51636 4L7.79068 1.72568C8.06977 1.44659 8.06977 0.994091 7.79068 0.714773L7.28523 0.209318C7.00614 -0.0697727 6.55364 -0.0697727 6.27432 0.209318L4 2.48364L1.72568 0.209318C1.44659 -0.0697727 0.994091 -0.0697727 0.714773 0.209318L0.209318 0.714773C-0.0697727 0.993864 -0.0697727 1.44636 0.209318 1.72568L2.48364 4L0.209318 6.27432C-0.0697727 6.55341 -0.0697727 7.00591 0.209318 7.28523L0.714773 7.79068C0.993864 8.06977 1.44659 8.06977 1.72568 7.79068L4 5.51636L6.27432 7.79068C6.55341 8.06977 7.00614 8.06977 7.28523 7.79068L7.79068 7.28523C8.06977 7.00614 8.06977 6.55364 7.79068 6.27432L5.51636 4Z' fill='white'/></svg>");
71
69
  }
72
70
 
73
71
  .vc-switch {
@@ -75,11 +73,11 @@ function onInput(e: Event) {
75
73
  @apply tw-w-0 tw-h-0 tw-opacity-0;
76
74
 
77
75
  &:checked + .vc-switch__slider:before {
78
- @apply tw-translate-x-[29px];
76
+ @apply tw-translate-x-[14px];
79
77
  }
80
78
 
81
79
  &:checked + .vc-switch__slider {
82
- @apply tw-bg-[color:var(--switch-main-color)] after:tw-bg-[image:var(--switch-active-icon)] after:tw-bg-[position:10px] after:tw-bg-[length:10px_7px];
80
+ @apply tw-bg-[color:var(--switch-main-color)] after:tw-bg-[position:10px] after:tw-bg-[length:10px_7px];
83
81
  }
84
82
 
85
83
  &:disabled + .vc-switch__slider {
@@ -88,14 +86,10 @@ function onInput(e: Event) {
88
86
  }
89
87
 
90
88
  &__slider {
91
- @apply tw-absolute tw-top-0 tw-right-0 tw-bottom-0 tw-left-0 tw-bg-[color:var(--switch-secondary-color)] tw-rounded-[3px] tw-cursor-pointer tw-transition tw-duration-200;
92
-
93
- &:after {
94
- @apply tw-inline-block tw-w-full tw-h-full tw-bg-[image:var(--switch-disabled-icon)] tw-bg-[position:calc(100%-11px)] tw-bg-no-repeat tw-bg-[length:8px_8px] tw-content-[""];
95
- }
89
+ @apply tw-absolute tw-top-0 tw-right-0 tw-bottom-0 tw-left-0 tw-bg-[color:var(--switch-secondary-color)] tw-rounded-[9999px] tw-cursor-pointer tw-transition tw-duration-200 tw-shadow-[inset_0px_2px_4px_rgba(0,0,0,0.1)];
96
90
 
97
91
  &:before {
98
- @apply tw-absolute tw-bottom-px tw-left-px tw-flex tw-justify-center tw-items-center tw-w-[23px] tw-h-[16px] tw-bg-white tw-rounded-sm tw-text-[color:#d2d2d2] tw-text-[10px] tw-transition tw-duration-200 tw-content-["|||"];
92
+ @apply tw-absolute tw-bottom-px tw-left-px tw-flex tw-justify-center tw-items-center tw-w-[16px] tw-h-[16px] tw-bg-white tw-rounded-[9999px] tw-text-[color:#d2d2d2] tw-text-[10px] tw-transition tw-shadow-[0_2px_4px_rgba(0,0,0,0.1)] tw-duration-200 tw-content-[""];
99
93
  }
100
94
  }
101
95
  }
@@ -34,6 +34,7 @@
34
34
  </template>
35
35
  </VcBladeHeader>
36
36
 
37
+ <!-- Show error message -->
37
38
  <template v-if="error">
38
39
  <div class="tw-text-white tw-p-2 tw-flex tw-flex-row tw-items-center tw-bg-[color:var(--blade-color-error)]">
39
40
  <VcIcon
@@ -50,6 +51,19 @@
50
51
  </div>
51
52
  </template>
52
53
 
54
+ <!-- Unsaved changes -->
55
+ <template v-if="hasUnsavedChanges">
56
+ <div
57
+ class="tw-text-white tw-px-2 tw-py-1 tw-flex tw-flex-row tw-items-center tw-bg-[color:var(--blade-color-unsaved-changes)]"
58
+ >
59
+ <VcIcon
60
+ size="s"
61
+ icon="fas fa-info-circle"
62
+ />
63
+ <div class="tw-line-clamp-1 tw-w-full tw-ml-2">{{ t("COMPONENTS.ORGANISMS.VC_BLADE.UNSAVED_CHANGES") }}</div>
64
+ </div>
65
+ </template>
66
+
53
67
  <!-- Set up blade toolbar -->
54
68
  <VcBladeToolbar
55
69
  class="tw-shrink-0"
@@ -78,6 +92,7 @@ export interface Props {
78
92
  expandable?: boolean;
79
93
  closable?: boolean;
80
94
  toolbarItems?: IBladeToolbar[];
95
+ hasUnsavedChanges?: boolean;
81
96
  }
82
97
 
83
98
  export interface Emits {
@@ -123,6 +138,7 @@ const { open } = usePopup({
123
138
  --blade-background-color: #ffffff;
124
139
  --blade-border-radius: 6px;
125
140
  --blade-color-error: #f14e4e;
141
+ --blade-color-unsaved-changes: #82a6bd;
126
142
  }
127
143
 
128
144
  .vc-app_mobile .vc-blade {
@@ -629,7 +629,7 @@ const mobileTemplateRenderer = ({ item }: { item: TableItem }) => {
629
629
  { class: "tw-border-b tw-border-solid tw-border-b-[#e3e7ec] tw-p-3 tw-gap-2 tw-flex tw-flex-wrap" },
630
630
  props.columns.map((x) => {
631
631
  return h("div", { class: "tw-grow tw-w-[33%] tw-ml-3 tw-truncate" }, [
632
- h(VcHint, { class: "tw-mb-1 tw-truncate" }, toValue(x.title)),
632
+ h(VcHint, { class: "tw-mb-1 tw-truncate" }, () => toValue(x.title)),
633
633
  h(VcTableCell, { cell: { ...x, class: "!tw-justify-start" }, item, class: "" }),
634
634
  ]);
635
635
  }),