@vc-shell/framework 1.0.117 → 1.0.119

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 (96) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/framework.mjs +8937 -8593
  3. package/dist/index.css +1 -1
  4. package/dist/shared/modules/dynamic/components/FIELD_MAP.d.ts.map +1 -1
  5. package/dist/shared/modules/dynamic/components/factories.d.ts +5 -2
  6. package/dist/shared/modules/dynamic/components/factories.d.ts.map +1 -1
  7. package/dist/shared/modules/dynamic/components/fields/Button.d.ts +8 -4
  8. package/dist/shared/modules/dynamic/components/fields/Button.d.ts.map +1 -1
  9. package/dist/shared/modules/dynamic/components/fields/Card.d.ts +8 -4
  10. package/dist/shared/modules/dynamic/components/fields/Card.d.ts.map +1 -1
  11. package/dist/shared/modules/dynamic/components/fields/Checkbox.d.ts +8 -4
  12. package/dist/shared/modules/dynamic/components/fields/Checkbox.d.ts.map +1 -1
  13. package/dist/shared/modules/dynamic/components/fields/ContentField.d.ts +135 -0
  14. package/dist/shared/modules/dynamic/components/fields/ContentField.d.ts.map +1 -0
  15. package/dist/shared/modules/dynamic/components/fields/DynamicProperty.d.ts +8 -4
  16. package/dist/shared/modules/dynamic/components/fields/DynamicProperty.d.ts.map +1 -1
  17. package/dist/shared/modules/dynamic/components/fields/EditorField.d.ts +8 -4
  18. package/dist/shared/modules/dynamic/components/fields/EditorField.d.ts.map +1 -1
  19. package/dist/shared/modules/dynamic/components/fields/Fieldset.d.ts +8 -4
  20. package/dist/shared/modules/dynamic/components/fields/Fieldset.d.ts.map +1 -1
  21. package/dist/shared/modules/dynamic/components/fields/GalleryField.d.ts +8 -4
  22. package/dist/shared/modules/dynamic/components/fields/GalleryField.d.ts.map +1 -1
  23. package/dist/shared/modules/dynamic/components/fields/ImageField.d.ts +135 -0
  24. package/dist/shared/modules/dynamic/components/fields/ImageField.d.ts.map +1 -0
  25. package/dist/shared/modules/dynamic/components/fields/InputCurrency.d.ts +8 -4
  26. package/dist/shared/modules/dynamic/components/fields/InputCurrency.d.ts.map +1 -1
  27. package/dist/shared/modules/dynamic/components/fields/InputField.d.ts +13 -9
  28. package/dist/shared/modules/dynamic/components/fields/InputField.d.ts.map +1 -1
  29. package/dist/shared/modules/dynamic/components/fields/SelectField.d.ts +8 -4
  30. package/dist/shared/modules/dynamic/components/fields/SelectField.d.ts.map +1 -1
  31. package/dist/shared/modules/dynamic/components/fields/StatusField.d.ts +8 -4
  32. package/dist/shared/modules/dynamic/components/fields/StatusField.d.ts.map +1 -1
  33. package/dist/shared/modules/dynamic/components/fields/VideoField.d.ts +135 -0
  34. package/dist/shared/modules/dynamic/components/fields/VideoField.d.ts.map +1 -0
  35. package/dist/shared/modules/dynamic/components/fields/props.d.ts +9 -5
  36. package/dist/shared/modules/dynamic/components/fields/props.d.ts.map +1 -1
  37. package/dist/shared/modules/dynamic/factories/types/index.d.ts.map +1 -1
  38. package/dist/shared/modules/dynamic/helpers/nodeBuilder.d.ts +2 -2
  39. package/dist/shared/modules/dynamic/helpers/nodeBuilder.d.ts.map +1 -1
  40. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts +8 -0
  41. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
  42. package/dist/shared/modules/dynamic/types/index.d.ts +29 -2
  43. package/dist/shared/modules/dynamic/types/index.d.ts.map +1 -1
  44. package/dist/shared/modules/dynamic/types/models.d.ts +15 -2
  45. package/dist/shared/modules/dynamic/types/models.d.ts.map +1 -1
  46. package/dist/tsconfig.tsbuildinfo +1 -1
  47. package/dist/ui/components/atoms/vc-col/index.d.ts +1 -80
  48. package/dist/ui/components/atoms/vc-col/index.d.ts.map +1 -1
  49. package/dist/ui/components/atoms/vc-col/vc-col.vue.d.ts +3 -3
  50. package/dist/ui/components/atoms/vc-col/vc-col.vue.d.ts.map +1 -1
  51. package/dist/ui/components/atoms/vc-row/index.d.ts +1 -52
  52. package/dist/ui/components/atoms/vc-row/index.d.ts.map +1 -1
  53. package/dist/ui/components/atoms/vc-row/vc-row.vue.d.ts +3 -3
  54. package/dist/ui/components/atoms/vc-row/vc-row.vue.d.ts.map +1 -1
  55. package/dist/ui/components/molecules/index.d.ts +1 -0
  56. package/dist/ui/components/molecules/index.d.ts.map +1 -1
  57. package/dist/ui/components/molecules/vc-field/_internal/vc-field-type/vc-field-type.vue.d.ts +33 -0
  58. package/dist/ui/components/molecules/vc-field/_internal/vc-field-type/vc-field-type.vue.d.ts.map +1 -0
  59. package/dist/ui/components/molecules/vc-field/index.d.ts +2 -0
  60. package/dist/ui/components/molecules/vc-field/index.d.ts.map +1 -0
  61. package/dist/ui/components/molecules/vc-field/vc-field.vue.d.ts +45 -0
  62. package/dist/ui/components/molecules/vc-field/vc-field.vue.d.ts.map +1 -0
  63. package/dist/ui/components/organisms/vc-popup/vc-popup.vue.d.ts.map +1 -1
  64. package/dist/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue.d.ts.map +1 -1
  65. package/dist/ui/types/index.d.ts +1 -0
  66. package/dist/ui/types/index.d.ts.map +1 -1
  67. package/package.json +4 -4
  68. package/shared/modules/dynamic/components/FIELD_MAP.ts +7 -0
  69. package/shared/modules/dynamic/components/SchemaRender.ts +3 -3
  70. package/shared/modules/dynamic/components/factories.ts +35 -1
  71. package/shared/modules/dynamic/components/fields/ContentField.ts +25 -0
  72. package/shared/modules/dynamic/components/fields/EditorField.ts +3 -6
  73. package/shared/modules/dynamic/components/fields/Fieldset.ts +12 -5
  74. package/shared/modules/dynamic/components/fields/GalleryField.ts +8 -5
  75. package/shared/modules/dynamic/components/fields/ImageField.ts +30 -0
  76. package/shared/modules/dynamic/components/fields/InputField.ts +25 -3
  77. package/shared/modules/dynamic/components/fields/VideoField.ts +28 -0
  78. package/shared/modules/dynamic/components/fields/props.ts +5 -5
  79. package/shared/modules/dynamic/factories/types/index.ts +1 -1
  80. package/shared/modules/dynamic/helpers/nodeBuilder.ts +19 -14
  81. package/shared/modules/dynamic/pages/dynamic-blade-list.vue +39 -2
  82. package/shared/modules/dynamic/types/index.ts +35 -2
  83. package/shared/modules/dynamic/types/models.ts +22 -1
  84. package/ui/components/atoms/vc-col/index.ts +1 -10
  85. package/ui/components/atoms/vc-col/vc-col.vue +10 -5
  86. package/ui/components/atoms/vc-image/vc-image.vue +1 -1
  87. package/ui/components/atoms/vc-label/vc-label.vue +1 -1
  88. package/ui/components/atoms/vc-row/index.ts +1 -10
  89. package/ui/components/atoms/vc-row/vc-row.vue +8 -1
  90. package/ui/components/molecules/index.ts +1 -0
  91. package/ui/components/molecules/vc-field/_internal/vc-field-type/vc-field-type.vue +66 -0
  92. package/ui/components/molecules/vc-field/index.ts +1 -0
  93. package/ui/components/molecules/vc-field/vc-field.vue +67 -0
  94. package/ui/components/organisms/vc-popup/vc-popup.vue +5 -0
  95. package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +4 -2
  96. package/ui/types/index.ts +1 -0
@@ -1,8 +1,16 @@
1
- import { ExtractPropTypes, h } from "vue";
1
+ import { ExtractPropTypes, h, VNode } from "vue";
2
2
  import { InputField } from "../factories";
3
3
  import componentProps from "./props";
4
4
  import ValidationField from "./ValidationField";
5
- import { InputSchema } from "../../types";
5
+ import { InputSchema, ControlSchema } from "../../types";
6
+ import { nodeBuilder } from "../../helpers/nodeBuilder";
7
+
8
+ const slotsMap = {
9
+ append: "append",
10
+ prepend: "prepend",
11
+ appendInner: "append-inner",
12
+ prependInner: "prepend-inner",
13
+ };
6
14
 
7
15
  export default {
8
16
  name: "InputField",
@@ -17,9 +25,23 @@ export default {
17
25
  clearable: props.element.clearable || false,
18
26
  },
19
27
  options: props.baseOptions,
28
+ slots: Object.entries(slotsMap).reduce((acc, [key, value]: [keyof InputSchema, keyof InputSchema]) => {
29
+ if (props.element[key]) {
30
+ acc[value] = () =>
31
+ nodeBuilder({
32
+ controlSchema: props.element[key] as ControlSchema,
33
+ parentId: `${(props.element[key] as ControlSchema).id}`,
34
+ internalContext: props.fieldContext,
35
+ bladeContext: props.bladeContext,
36
+ currentLocale: props.currentLocale,
37
+ formData: props.formData,
38
+ });
39
+ }
40
+ return acc;
41
+ }, {} as Record<keyof InputSchema, () => VNode | false>),
20
42
  });
21
43
 
22
- const render = h(field.component, field.props);
44
+ const render = h(field.component, field.props, field.slots);
23
45
 
24
46
  if (field.props.rules) {
25
47
  return props.baseOptions.visibility
@@ -0,0 +1,28 @@
1
+ import { ExtractPropTypes, h } from "vue";
2
+ import { VideoField } from "../factories";
3
+ import componentProps from "./props";
4
+ import { VideoSchema } from "../../types";
5
+
6
+ export default {
7
+ name: "VideoField",
8
+ props: componentProps,
9
+ setup(props: ExtractPropTypes<typeof componentProps> & { element: VideoSchema }) {
10
+ return () => {
11
+ const field = VideoField({
12
+ props: {
13
+ ...props.baseProps,
14
+ source: props.baseProps.modelValue,
15
+ size: props.element.size,
16
+ rounded: props.element.rounded,
17
+ bordered: props.element.bordered,
18
+ clickable: props.element.clickable,
19
+ },
20
+ options: props.baseOptions,
21
+ });
22
+
23
+ const render = h(field.component, field.props);
24
+
25
+ return props.baseOptions.visibility ? render : null;
26
+ };
27
+ },
28
+ };
@@ -1,4 +1,4 @@
1
- import { ComputedRef, PropType, UnwrapNestedRefs, VNodeArrayChildren } from "vue";
1
+ import { ComputedRef, MaybeRef, PropType, UnwrapNestedRefs, VNode, VNodeArrayChildren } from "vue";
2
2
  import { DetailsBladeContext } from "../../factories";
3
3
  import { IControlBaseOptions, IControlBaseProps } from "../../types/models";
4
4
  import { ControlSchema } from "../../types";
@@ -21,12 +21,12 @@ export default {
21
21
  default: () => ({} as DetailsBladeContext),
22
22
  },
23
23
  fields: {
24
- type: Object as PropType<ComputedRef<VNodeArrayChildren>>,
25
- default: () => ({} as ComputedRef<VNodeArrayChildren>),
24
+ type: Object as PropType<ComputedRef<VNode[][]>>,
25
+ default: () => ({} as ComputedRef<VNode[][]>),
26
26
  },
27
27
  formData: {
28
- type: Object,
29
- default: () => ({}),
28
+ type: Object as PropType<MaybeRef<Record<string, unknown>>>,
29
+ default: () => ({} as MaybeRef<Record<string, unknown>>),
30
30
  },
31
31
  fieldContext: {
32
32
  type: Object,
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { ComputedRef, MaybeRef, Ref, UnwrapNestedRefs } from "vue";
2
+ import { ComputedRef, MaybeRef, Ref, UnwrapNestedRefs, UnwrapRef } from "vue";
3
3
  import { AsyncAction } from "../../../../../core/composables";
4
4
  import { SettingsSchema } from "../../types";
5
5
  import { Asset, AssetsHandler, IBladeToolbar, IImage } from "../../../../../core/types";
@@ -19,10 +19,14 @@ function disabledHandler(
19
19
  return false;
20
20
  }
21
21
 
22
- function nodeBuilder<Context, BContext extends UnwrapNestedRefs<DetailsBladeContext>, FormData>(args: {
22
+ function nodeBuilder<
23
+ Context extends Record<string, unknown>,
24
+ BContext extends UnwrapNestedRefs<DetailsBladeContext>,
25
+ FormData
26
+ >(args: {
23
27
  controlSchema: ControlSchema;
24
28
  parentId: string | number;
25
- internalContext: Context;
29
+ internalContext: MaybeRef<Context>;
26
30
  bladeContext: BContext;
27
31
  currentLocale: MaybeRef<string>;
28
32
  formData: FormData;
@@ -32,7 +36,7 @@ function nodeBuilder<Context, BContext extends UnwrapNestedRefs<DetailsBladeCont
32
36
 
33
37
  const baseProps = reactive<IControlBaseProps>({
34
38
  key: `${parentId}`,
35
- label: controlSchema.label ? unref(unwrapInterpolation(controlSchema.label, internalContext)) : undefined,
39
+ label: controlSchema.label ? unref(unwrapInterpolation(controlSchema.label, toValue(internalContext))) : undefined,
36
40
  disabled:
37
41
  ("disabled" in bladeContext.scope && bladeContext.scope.disabled) ||
38
42
  disabledHandler("disabled" in controlSchema && controlSchema.disabled, bladeContext),
@@ -40,14 +44,14 @@ function nodeBuilder<Context, BContext extends UnwrapNestedRefs<DetailsBladeCont
40
44
  rules: controlSchema.rules,
41
45
  placeholder: controlSchema.placeholder,
42
46
  required: controlSchema.rules?.required,
43
- modelValue: getModel(controlSchema.property, internalContext),
44
- "onUpdate:modelValue": (e) => {
45
- setModel({ property: controlSchema.property, value: e, context: internalContext });
47
+ modelValue: getModel(controlSchema.property, toValue(internalContext)),
48
+ "onUpdate:modelValue": (e: unknown) => {
49
+ setModel({ property: controlSchema.property, value: e, context: toValue(internalContext) });
46
50
 
47
51
  if (_.has(controlSchema, "update.method")) {
48
52
  controlSchema.update.method in bladeContext.scope &&
49
53
  typeof bladeContext.scope[controlSchema.update.method] === "function"
50
- ? bladeContext.scope[controlSchema.update.method](e, controlSchema.property, internalContext)
54
+ ? bladeContext.scope[controlSchema.update.method](e, controlSchema.property, toValue(internalContext))
51
55
  : undefined;
52
56
  }
53
57
  },
@@ -57,7 +61,7 @@ function nodeBuilder<Context, BContext extends UnwrapNestedRefs<DetailsBladeCont
57
61
 
58
62
  const baseOptions = reactive<IControlBaseOptions>({
59
63
  visibility: computed(() =>
60
- controlSchema.visibility?.method ? toValue(bladeContext.scope[controlSchema.visibility?.method]) : true
64
+ controlSchema.visibility?.method ? bladeContext.scope[controlSchema.visibility?.method] : true
61
65
  ),
62
66
  });
63
67
 
@@ -65,10 +69,11 @@ function nodeBuilder<Context, BContext extends UnwrapNestedRefs<DetailsBladeCont
65
69
 
66
70
  const fieldsHandler = computed(() => {
67
71
  if (!("fields" in controlSchema)) return null;
68
- const fieldsModel = getModel(controlSchema.property, internalContext);
72
+ const fieldsModel = getModel(controlSchema.property, toValue(internalContext));
69
73
 
70
- if (toValue(fieldsModel) && Array.isArray(toValue(fieldsModel))) {
71
- return toValue(fieldsModel).map((model: { [x: string]: unknown; id: string }) =>
74
+ const model = toValue(fieldsModel);
75
+ if (model && Array.isArray(model)) {
76
+ return model.map((model: { [x: string]: unknown; id: string }) =>
72
77
  controlSchema.fields.map((fieldItem) =>
73
78
  nodeBuilder({
74
79
  controlSchema: fieldItem,
@@ -86,7 +91,7 @@ function nodeBuilder<Context, BContext extends UnwrapNestedRefs<DetailsBladeCont
86
91
  nodeBuilder({
87
92
  controlSchema: field,
88
93
  parentId: `fieldset-${parentId}-${field.id}`,
89
- internalContext,
94
+ internalContext: reactive(unref(internalContext)),
90
95
  bladeContext,
91
96
  currentLocale,
92
97
  formData,
@@ -100,10 +105,10 @@ function nodeBuilder<Context, BContext extends UnwrapNestedRefs<DetailsBladeCont
100
105
  baseOptions,
101
106
  bladeContext,
102
107
  element: controlSchema,
103
- currentLocale,
108
+ currentLocale: unref(currentLocale),
104
109
  fields: fieldsHandler,
105
110
  formData,
106
- fieldContext: internalContext,
111
+ fieldContext: reactive(unref(internalContext)),
107
112
  };
108
113
 
109
114
  return h(component, elProps);
@@ -15,7 +15,7 @@
15
15
  :expanded="expanded"
16
16
  v-bind="bladeOptions?.table"
17
17
  :state-key="tableData?.id"
18
- :items="items"
18
+ :items="itemsProxy"
19
19
  :multiselect="tableData?.multiselect"
20
20
  :header="tableData?.header"
21
21
  :sort="sort"
@@ -26,6 +26,7 @@
26
26
  :total-label="$t(`${settings.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.TABLE.TOTALS`)"
27
27
  :total-count="pagination?.totalCount"
28
28
  :active-filter-count="activeFilterCount"
29
+ :reorderable-rows="tableData?.reorderableRows"
29
30
  @item-click="onItemClick"
30
31
  @pagination-click="onPaginationClick"
31
32
  @selection-changed="onSelectionChanged"
@@ -33,6 +34,7 @@
33
34
  @load:change="onSearchList"
34
35
  @scroll:ptr="reload"
35
36
  @search:change="onSearchList"
37
+ @row:reorder="sortRows"
36
38
  >
37
39
  <template
38
40
  v-if="isFilterVisible"
@@ -133,6 +135,8 @@ import { ITableColumns } from "../../../../core/types";
133
135
  import { toolbarReducer } from "../helpers/toolbarReducer";
134
136
  import { notification, usePopup } from "../../../components";
135
137
  import { ListBaseBladeScope, ListBladeContext, UseList } from "../factories/types";
138
+ import { IParentCallArgs } from "../../../index";
139
+ import * as _ from "lodash-es";
136
140
 
137
141
  export interface Props {
138
142
  expanded?: boolean;
@@ -144,6 +148,7 @@ export interface Props {
144
148
  }
145
149
 
146
150
  export interface Emits {
151
+ (event: "parent:call", args: IParentCallArgs): void;
147
152
  (event: "close:blade"): void;
148
153
  (event: "collapse:blade"): void;
149
154
  (event: "expand:blade"): void;
@@ -174,6 +179,8 @@ const selectedItemId = ref();
174
179
  const sort = ref("createdDate:DESC");
175
180
  const selectedIds = ref<string[]>([]);
176
181
  const isDesktop = inject<Ref<boolean>>("isDesktop");
182
+ const itemsProxy = ref<Record<string, any>[]>();
183
+ const modified = ref(false);
177
184
 
178
185
  const { moduleNotifications, markAsRead } = useNotifications(settings.value.pushNotificationType);
179
186
 
@@ -231,7 +238,7 @@ const {
231
238
  const bladeContext = ref<ListBladeContext>({
232
239
  load,
233
240
  remove,
234
- items,
241
+ items: computed(() => itemsProxy.value),
235
242
  loading,
236
243
  pagination,
237
244
  query,
@@ -242,6 +249,12 @@ const bladeContext = ref<ListBladeContext>({
242
249
  const toolbarComputed = toolbarReducer({
243
250
  defaultToolbarSchema: settings.value.toolbar,
244
251
  defaultToolbarBindings: {
252
+ save: {
253
+ clickHandler() {
254
+ emit("close:blade");
255
+ },
256
+ disabled: computed(() => !modified.value),
257
+ },
245
258
  openAddBlade: {
246
259
  async clickHandler() {
247
260
  if (
@@ -274,10 +287,22 @@ onMounted(async () => {
274
287
  await load({ ...query.value, sort: sort.value });
275
288
  });
276
289
 
290
+ watch(
291
+ () => itemsProxy.value,
292
+ (newVal) => {
293
+ modified.value = !_.isEqual(newVal, items.value);
294
+ },
295
+ { deep: true }
296
+ );
297
+
277
298
  watch(sort, async (value) => {
278
299
  await load({ ...query.value, sort: value });
279
300
  });
280
301
 
302
+ watch(items, (newVal) => {
303
+ itemsProxy.value = newVal;
304
+ });
305
+
281
306
  watch(
282
307
  () => props.param,
283
308
  (newVal) => {
@@ -465,8 +490,20 @@ function resolveTemplateComponent(name: keyof ListContentSchema) {
465
490
  }
466
491
  }
467
492
 
493
+ function sortRows(event: { dragIndex: number; dropIndex: number; value: any[] }) {
494
+ if (event.dragIndex !== event.dropIndex) {
495
+ const sorted = event.value.map((item, index) => {
496
+ item.sortOrder = index;
497
+ return item;
498
+ });
499
+
500
+ itemsProxy.value = sorted;
501
+ }
502
+ }
503
+
468
504
  defineExpose({
469
505
  reload,
470
506
  title,
507
+ ...scope.value,
471
508
  });
472
509
  </script>
@@ -1,4 +1,4 @@
1
- import { VcButton, VcIcon, VcInput, VcStatus } from "./../../../../ui/components";
1
+ import { VcButton, VcField, VcIcon, VcImage, VcInput, VcStatus, VcVideo } from "./../../../../ui/components";
2
2
  import { ITableColumns, IValidationRules } from "../../../../core/types";
3
3
  import type { ComponentProps, ComponentEmit, ComponentSlots } from "vue-component-type-helpers";
4
4
 
@@ -95,6 +95,7 @@ export interface ListContentSchema extends SchemaBase {
95
95
  type?: string;
96
96
  customTemplate?: GridTemplateOverride;
97
97
  })[];
98
+ reorderableRows?: boolean;
98
99
  mobileTemplate?: {
99
100
  component: string;
100
101
  };
@@ -148,6 +149,34 @@ export interface InputSchema extends SchemaBase {
148
149
  component: "vc-input";
149
150
  variant?: ComponentProps<typeof VcInput>["type"];
150
151
  clearable?: boolean;
152
+ prepend?: ControlSchema;
153
+ append?: ControlSchema;
154
+ appendInner?: ControlSchema;
155
+ prependInner?: ControlSchema;
156
+ }
157
+
158
+ export interface VideoSchema extends SchemaBase {
159
+ component: "vc-video";
160
+ size?: ComponentProps<typeof VcVideo>["size"];
161
+ rounded?: boolean;
162
+ bordered?: boolean;
163
+ clickable?: boolean;
164
+ }
165
+
166
+ export interface FieldSchema extends SchemaBase {
167
+ component: "vc-field";
168
+ variant?: ComponentProps<typeof VcField>["type"];
169
+ copyable?: boolean;
170
+ }
171
+
172
+ export interface ImageSchema extends SchemaBase {
173
+ component: "vc-image";
174
+ aspect?: ComponentProps<typeof VcImage>["aspect"];
175
+ size?: ComponentProps<typeof VcImage>["size"];
176
+ background?: ComponentProps<typeof VcImage>["background"];
177
+ rounded?: boolean;
178
+ bordered?: boolean;
179
+ clickable?: boolean;
151
180
  }
152
181
 
153
182
  export interface StatusSchema extends SchemaBase {
@@ -209,6 +238,7 @@ export interface CheckboxSchema extends SchemaBase {
209
238
  export interface FieldsetSchema extends SchemaBase {
210
239
  component: "vc-fieldset";
211
240
  columns?: number;
241
+ aspectRatio?: number[];
212
242
  fields: Exclude<ControlSchema[], FieldsetSchema>;
213
243
  remove?: {
214
244
  method: string;
@@ -237,7 +267,10 @@ export type ControlSchema =
237
267
  | FieldsetSchema
238
268
  | ButtonSchema
239
269
  | InputCurrencySchema
240
- | StatusSchema;
270
+ | StatusSchema
271
+ | FieldSchema
272
+ | VideoSchema
273
+ | ImageSchema;
241
274
 
242
275
  export interface FilterBase {
243
276
  columns: {
@@ -6,11 +6,14 @@ import {
6
6
  VcCheckbox,
7
7
  VcDynamicProperty,
8
8
  VcEditor,
9
+ VcField,
9
10
  VcGallery,
11
+ VcImage,
10
12
  VcInput,
11
13
  VcInputCurrency,
12
14
  VcSelect,
13
15
  VcStatus,
16
+ VcVideo,
14
17
  } from "../../../../ui/components";
15
18
  import type { ComponentProps, ComponentEmit, ComponentSlots } from "vue-component-type-helpers";
16
19
 
@@ -44,7 +47,9 @@ export type ControlType =
44
47
  | ICheckbox
45
48
  | IButton
46
49
  | IInputCurrency
47
- | IStatusField;
50
+ | IStatusField
51
+ | IContentField
52
+ | IImageField;
48
53
 
49
54
  export type ControlTypeWithSlots = Extract<
50
55
  ControlType,
@@ -90,8 +95,24 @@ export type IStatusField = {
90
95
  export type IInputField = {
91
96
  props: ComponentProps<typeof VcInput> | IControlBaseProps;
92
97
  options: IControlBaseOptions;
98
+ slots?: Partial<Pick<ComponentSlots<typeof VcInput>, "append" | "prepend" | "append-inner" | "prepend-inner">>;
93
99
  } & FieldOpts<typeof VcInput>;
94
100
 
101
+ export type IContentField = {
102
+ props: ComponentProps<typeof VcField> | IControlBaseProps;
103
+ options: IControlBaseOptions;
104
+ } & FieldOpts<typeof VcField>;
105
+
106
+ export type IVideoField = {
107
+ props: ComponentProps<typeof VcVideo> | IControlBaseProps;
108
+ options: IControlBaseOptions;
109
+ } & FieldOpts<typeof VcVideo>;
110
+
111
+ export type IImageField = {
112
+ props: ComponentProps<typeof VcImage> | IControlBaseProps;
113
+ options: IControlBaseOptions;
114
+ } & FieldOpts<typeof VcImage>;
115
+
95
116
  export type IInputCurrency = {
96
117
  props: Partial<ComponentProps<typeof VcInputCurrency>> | IControlBaseProps;
97
118
  options: IControlBaseOptions;
@@ -1,10 +1 @@
1
- import { VNode } from "vue";
2
- import _Col from "./vc-col.vue";
3
-
4
- export const VcCol = _Col as typeof _Col & {
5
- new (): {
6
- $slots: {
7
- default: () => VNode[];
8
- };
9
- };
10
- };
1
+ export { default as VcCol } from "./vc-col.vue";
@@ -15,12 +15,17 @@ export interface Props {
15
15
  withDefaults(defineProps<Props>(), {
16
16
  size: "1",
17
17
  });
18
+
19
+ defineSlots<{
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ default: (props: any) => any;
22
+ }>();
18
23
  </script>
19
24
 
20
25
  <style lang="scss">
21
- .vc-col {
22
- .vc-app_mobile & {
23
- @apply tw-grow #{!important};
24
- }
25
- }
26
+ // .vc-col {
27
+ // .vc-app_mobile & {
28
+ // @apply tw-grow #{!important};
29
+ // }
30
+ // }
26
31
  </style>
@@ -99,7 +99,7 @@ $paddings: xs, s, m, l, xl, xxl;
99
99
 
100
100
  @each $padding in $paddings {
101
101
  &_#{$padding} {
102
- @apply tw-w-[var(--image-size-#{$padding})];
102
+ @apply tw-w-[var(--image-size-#{$padding})] tw-max-w-full tw-min-w-0;
103
103
  }
104
104
  }
105
105
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="tw-flex tw-flex-nowrap tw-font-bold tw-relative">
3
- <span><slot></slot></span>
3
+ <span class="tw-truncate"><slot></slot></span>
4
4
  <span
5
5
  v-if="required"
6
6
  class="tw-text-[color:var(--label-required-color)] tw-ml-1"
@@ -1,10 +1 @@
1
- import { VNode } from "vue";
2
- import _Row from "./vc-row.vue";
3
-
4
- export const VcRow = _Row as typeof _Row & {
5
- new (): {
6
- $slots: {
7
- default: () => VNode[];
8
- };
9
- };
10
- };
1
+ export { default as VcRow } from "./vc-row.vue";
@@ -4,10 +4,17 @@
4
4
  </div>
5
5
  </template>
6
6
 
7
+ <script setup lang="ts">
8
+ defineSlots<{
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ default: (props: any) => any;
11
+ }>();
12
+ </script>
13
+
7
14
  <style lang="scss">
8
15
  .vc-row {
9
16
  .vc-app_mobile & {
10
- display: block;
17
+ display: grid;
11
18
  }
12
19
  }
13
20
  </style>
@@ -12,3 +12,4 @@ export * from "./vc-select";
12
12
  export * from "./vc-slider";
13
13
  export * from "./vc-textarea";
14
14
  export * from "./vc-multivalue";
15
+ export * from "./vc-field";
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <!-- Text -->
3
+ <template v-if="type === 'text'">
4
+ <div class="tw-flex tw-flex-row tw-justify-stretch tw-truncate">
5
+ <div class="tw-truncate">
6
+ <VcHint class="tw-text-s">{{ value }}</VcHint>
7
+ </div>
8
+ </div>
9
+ </template>
10
+
11
+ <!-- Date -->
12
+ <template v-if="type === 'date'">
13
+ <div class="tw-flex tw-flex-row tw-justify-stretch tw-truncate">
14
+ <div class="tw-truncate">
15
+ <VcHint class="tw-text-s"> {{ value.toLocaleDateString() }}</VcHint>
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <!-- Date ago -->
21
+ <template v-if="type === 'date-ago'">
22
+ <div class="tw-flex tw-flex-row tw-justify-stretch tw-truncate">
23
+ <div class="tw-truncate">
24
+ <VcHint class="tw-text-s"> {{ moment(value).fromNow() ?? "N/A" }}</VcHint>
25
+ </div>
26
+ </div>
27
+ </template>
28
+
29
+ <!-- Link -->
30
+ <template v-if="type === 'link'">
31
+ <div class="tw-flex tw-flex-row tw-justify-stretch tw-truncate">
32
+ <div class="tw-truncate">
33
+ <VcLink
34
+ class="vc-link tw-text-s tw-truncate tw-w-full"
35
+ @click="onLinkClick"
36
+ >{{ value }}</VcLink
37
+ >
38
+ </div>
39
+ <slot></slot>
40
+ </div>
41
+ </template>
42
+ </template>
43
+
44
+ <script lang="ts" setup>
45
+ import moment from "moment";
46
+
47
+ export interface Props {
48
+ type: "text" | "date" | "date-ago" | "link";
49
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
+ value: any;
51
+ }
52
+
53
+ export interface Emits {
54
+ (event: "click"): void;
55
+ (event: "copy"): void;
56
+ }
57
+
58
+ defineEmits<Emits>();
59
+ const props = defineProps<Props>();
60
+
61
+ function onLinkClick() {
62
+ location.href = props.value;
63
+ }
64
+ </script>
65
+
66
+ <style lang="scss" scoped></style>
@@ -0,0 +1 @@
1
+ export { default as VcField } from "./vc-field.vue";
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <div>
3
+ <!-- Field label -->
4
+ <VcLabel v-if="label">
5
+ <span>{{ label }}</span>
6
+ <template
7
+ v-if="tooltip"
8
+ #tooltip
9
+ >{{ tooltip }}</template
10
+ ></VcLabel
11
+ >
12
+ <!-- <div> -->
13
+ <VcFieldType
14
+ :value="modelValue"
15
+ :type="type"
16
+ >
17
+ <VcButton
18
+ v-if="copyable"
19
+ icon="far fa-copy"
20
+ size="m"
21
+ class="tw-ml-2"
22
+ text
23
+ @click="copy(modelValue)"
24
+ ></VcButton>
25
+ </VcFieldType>
26
+ </div>
27
+ <!-- </div> -->
28
+ </template>
29
+
30
+ <script lang="ts" setup>
31
+ import { VcLabel } from "./../../";
32
+ import VcFieldType from "./_internal/vc-field-type/vc-field-type.vue";
33
+
34
+ export interface Props {
35
+ /**
36
+ * Field label text
37
+ */
38
+ label?: string;
39
+ /**
40
+ * Field tooltip information
41
+ */
42
+ tooltip?: string;
43
+ /**
44
+ * Field type
45
+ */
46
+ type?: "text" | "date" | "date-ago" | "link";
47
+ /**
48
+ * Field content
49
+ */
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
+ modelValue?: any;
52
+ /**
53
+ * Add button for field content copying
54
+ */
55
+ copyable?: boolean;
56
+ }
57
+
58
+ withDefaults(defineProps<Props>(), {
59
+ type: "text",
60
+ });
61
+
62
+ function copy(value: string) {
63
+ navigator.clipboard?.writeText(value);
64
+ }
65
+ </script>
66
+
67
+ <style lang="scss" scoped></style>
@@ -47,6 +47,11 @@ import VcPopupError from "./_internal/vc-popup-error/vc-popup-error.vue";
47
47
  import { defineComponent, PropType } from "vue";
48
48
 
49
49
  export default defineComponent({
50
+ components: {
51
+ VcIcon,
52
+ VcPopupWarning,
53
+ VcPopupError,
54
+ },
50
55
  props: {
51
56
  title: {
52
57
  type: String,