@flyanra/vue-core 0.3.0 → 0.4.1

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 (139) hide show
  1. package/README.md +176 -176
  2. package/package.json +137 -128
  3. package/src/components/basic/fly-button/FlyButton.element.scss +3 -3
  4. package/src/components/basic/fly-button/FlyButton.mixins.scss +58 -58
  5. package/src/components/basic/fly-button/FlyButton.types.ts +29 -29
  6. package/src/components/basic/fly-button/FlyButton.vue +180 -180
  7. package/src/components/basic/fly-button/index.ts +11 -11
  8. package/src/components/basic/index.ts +2 -2
  9. package/src/components/basic/typography/FlyCollapseTitleRenderer.vue +46 -0
  10. package/src/components/feedback/index.ts +2 -2
  11. package/src/components/feedback/tooltip/FlyInfoTooltip.vue +48 -0
  12. package/src/components/feedback/tooltip/FlyTooltip.element.scss +4 -4
  13. package/src/components/feedback/tooltip/FlyTooltip.types.ts +5 -5
  14. package/src/components/feedback/tooltip/FlyTooltip.vue +60 -59
  15. package/src/components/feedback/tooltip/index.ts +6 -6
  16. package/src/components/form/form.utils.ts +57 -0
  17. package/src/components/form/index.ts +0 -0
  18. package/src/components/form/input-renderers/boolean/FlyBoolean.scss +1 -0
  19. package/src/components/form/input-renderers/boolean/FlyBoolean.types.ts +16 -0
  20. package/src/components/form/input-renderers/boolean/FlyBoolean.vue +35 -0
  21. package/src/components/form/input-renderers/date-time/FlyDateTime.scss +1 -0
  22. package/src/components/form/input-renderers/date-time/FlyDateTime.types.ts +21 -0
  23. package/src/components/form/input-renderers/date-time/FlyDateTime.vue +85 -0
  24. package/src/components/form/input-renderers/form-item-renderer/FlyFormItemRenderer.scss +4 -0
  25. package/src/components/form/input-renderers/form-item-renderer/FlyFormItemRenderer.vue +48 -0
  26. package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.types.ts +3 -0
  27. package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.utils.ts +246 -0
  28. package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.vue +75 -0
  29. package/src/components/form/input-renderers/form-schema-renderer/UseFormSchemaRenderer.ts +97 -0
  30. package/src/components/form/input-renderers/form-schema.types.ts +95 -0
  31. package/src/components/form/input-renderers/input-renderer/FlyInputRenderer.vue +49 -0
  32. package/src/components/form/input-renderers/input-renderer.types.ts +49 -0
  33. package/src/components/form/input-renderers/input-renderer.utils.ts +18 -0
  34. package/src/components/form/input-renderers/number/FlyNumber.scss +1 -0
  35. package/src/components/form/input-renderers/number/FlyNumber.types.ts +13 -0
  36. package/src/components/form/input-renderers/number/FlyNumber.utils.ts +6 -0
  37. package/src/components/form/input-renderers/number/FlyNumber.vue +48 -0
  38. package/src/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.types.ts +15 -0
  39. package/src/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.vue +99 -0
  40. package/src/components/form/input-renderers/select/FlySelect.scss +9 -0
  41. package/src/components/form/input-renderers/select/FlySelect.types.ts +25 -0
  42. package/src/components/form/input-renderers/select/FlySelect.utils.ts +37 -0
  43. package/src/components/form/input-renderers/select/FlySelect.vue +48 -0
  44. package/src/components/form/input-renderers/text/FlyText.scss +1 -0
  45. package/src/components/form/input-renderers/text/FlyText.types.ts +20 -0
  46. package/src/components/form/input-renderers/text/FlyText.vue +56 -0
  47. package/src/components/form/input-renderers/value-unit/FlyValueUnit.scss +2 -0
  48. package/src/components/form/input-renderers/value-unit/FlyValueUnit.types.ts +28 -0
  49. package/src/components/form/input-renderers/value-unit/FlyValueUnit.vue +101 -0
  50. package/src/components/form/input-validators.ts +121 -0
  51. package/src/components/general/fly-icon/FlyIcon.types.ts +12 -12
  52. package/src/components/general/fly-icon/FlyIcon.vue +24 -24
  53. package/src/components/general/fly-icon/index.ts +6 -6
  54. package/src/components/general/index.ts +2 -2
  55. package/src/components/index.ts +5 -11
  56. package/src/components/navigation/fly-steps/FlySteps.element.scss +100 -100
  57. package/src/components/navigation/fly-steps/FlySteps.types.ts +10 -10
  58. package/src/components/navigation/fly-steps/FlySteps.vue +30 -30
  59. package/src/components/navigation/fly-steps/index.ts +6 -6
  60. package/src/components/navigation/index.ts +2 -2
  61. package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.element.scss +2 -2
  62. package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.types.ts +8 -8
  63. package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.vue +46 -46
  64. package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebarItem.vue +55 -55
  65. package/src/components/navigation/menu/fly-mini-sidebar/index.ts +6 -6
  66. package/src/components/navigation/menu/fly-sidebar/FlySidebar.element.scss +9 -9
  67. package/src/components/navigation/menu/fly-sidebar/FlySidebar.types.ts +36 -36
  68. package/src/components/navigation/menu/fly-sidebar/FlySidebar.vue +150 -150
  69. package/src/components/navigation/menu/fly-sidebar/FlySidebarNode.vue +47 -47
  70. package/src/components/navigation/menu/fly-sidebar/index.ts +12 -12
  71. package/src/components/navigation/menu/index.ts +5 -5
  72. package/src/index.ts +1 -1
  73. package/src/styles/_scss-tokens.scss +76 -76
  74. package/src/styles/core/animations.scss +40 -40
  75. package/src/styles/core/index.scss +36 -36
  76. package/src/styles/core/scrollbar.scss +36 -36
  77. package/src/styles/core/typography-utils.scss +9 -9
  78. package/src/styles/element/common.scss +56 -56
  79. package/src/styles/element/dark.scss +38 -38
  80. package/src/styles/element/mixins/collapse.scss +61 -61
  81. package/src/styles/element/mixins/dialog.scss +101 -101
  82. package/src/styles/element/overrides/alerts.scss +28 -28
  83. package/src/styles/element/overrides/badge.scss +6 -6
  84. package/src/styles/element/overrides/cascader.scss +2 -2
  85. package/src/styles/element/overrides/collapse.scss +2 -2
  86. package/src/styles/element/overrides/date-time.scss +11 -0
  87. package/src/styles/element/overrides/dialog.scss +2 -2
  88. package/src/styles/element/overrides/dropdown.scss +11 -11
  89. package/src/styles/element/overrides/form.scss +107 -107
  90. package/src/styles/element/overrides/message.scss +39 -39
  91. package/src/styles/element/overrides/notification.scss +46 -46
  92. package/src/styles/element/overrides/segmented.scss +17 -17
  93. package/src/styles/element/overrides/table.scss +2 -2
  94. package/src/styles/element/overrides/tag.scss +19 -19
  95. package/src/styles/index.d.ts +1 -1
  96. package/src/styles/index.scss +5 -5
  97. package/src/styles/mixins/shadows.scss +15 -15
  98. package/src/styles/tokens.scss +84 -83
  99. package/dist/types/components/AppButton/AppButton.types.d.ts +0 -8
  100. package/dist/types/components/AppButton/AppButton.vue.d.ts +0 -20
  101. package/dist/types/components/AppButton/index.d.ts +0 -4
  102. package/dist/types/components/AppCard/AppCard.types.d.ts +0 -5
  103. package/dist/types/components/AppCard/AppCard.vue.d.ts +0 -17
  104. package/dist/types/components/AppCard/index.d.ts +0 -4
  105. package/dist/types/components/basic/fly-button/FlyButton.types.d.ts +0 -25
  106. package/dist/types/components/basic/fly-button/FlyButton.vue.d.ts +0 -26
  107. package/dist/types/components/basic/fly-button/index.d.ts +0 -4
  108. package/dist/types/components/basic/index.d.ts +0 -2
  109. package/dist/types/components/feedback/index.d.ts +0 -2
  110. package/dist/types/components/feedback/tooltip/FlyTooltip.types.d.ts +0 -4
  111. package/dist/types/components/feedback/tooltip/FlyTooltip.vue.d.ts +0 -16
  112. package/dist/types/components/feedback/tooltip/index.d.ts +0 -4
  113. package/dist/types/components/general/fly-icon/FlyIcon.types.d.ts +0 -7
  114. package/dist/types/components/general/fly-icon/FlyIcon.vue.d.ts +0 -6
  115. package/dist/types/components/general/fly-icon/index.d.ts +0 -4
  116. package/dist/types/components/general/index.d.ts +0 -2
  117. package/dist/types/components/index.d.ts +0 -8
  118. package/dist/types/components/navigation/fly-steps/FlySteps.types.d.ts +0 -9
  119. package/dist/types/components/navigation/fly-steps/FlySteps.vue.d.ts +0 -9
  120. package/dist/types/components/navigation/fly-steps/index.d.ts +0 -4
  121. package/dist/types/components/navigation/index.d.ts +0 -2
  122. package/dist/types/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.types.d.ts +0 -7
  123. package/dist/types/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.vue.d.ts +0 -8
  124. package/dist/types/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebarItem.vue.d.ts +0 -7
  125. package/dist/types/components/navigation/menu/fly-mini-sidebar/index.d.ts +0 -4
  126. package/dist/types/components/navigation/menu/fly-sidebar/FlySidebar.types.d.ts +0 -29
  127. package/dist/types/components/navigation/menu/fly-sidebar/FlySidebar.vue.d.ts +0 -8
  128. package/dist/types/components/navigation/menu/fly-sidebar/FlySidebarNode.vue.d.ts +0 -7
  129. package/dist/types/components/navigation/menu/fly-sidebar/index.d.ts +0 -4
  130. package/dist/types/components/navigation/menu/index.d.ts +0 -4
  131. package/dist/types/index.d.ts +0 -1
  132. package/dist/types/types/index.d.ts +0 -1
  133. package/src/components/AppButton/AppButton.element.scss +0 -2
  134. package/src/components/AppButton/AppButton.types.ts +0 -10
  135. package/src/components/AppButton/AppButton.vue +0 -65
  136. package/src/components/AppButton/index.ts +0 -6
  137. package/src/components/AppCard/AppCard.types.ts +0 -5
  138. package/src/components/AppCard/AppCard.vue +0 -58
  139. package/src/components/AppCard/index.ts +0 -6
@@ -1,5 +1,5 @@
1
- import type { UseTooltipProps } from 'element-plus'
2
-
3
- export type T_FlyTooltipProps = {
4
- tooltip?: UseTooltipProps
5
- }
1
+ import type { UseTooltipProps } from 'element-plus'
2
+
3
+ export type T_FlyTooltipProps = {
4
+ tooltip?: UseTooltipProps
5
+ }
@@ -1,59 +1,60 @@
1
- <template>
2
- <el-tooltip
3
- v-bind="mergedElProps"
4
- :popper-class="`fly-tooltip-popper ${popperClasses}`"
5
- class="fly-tooltip"
6
- >
7
- <template v-if="$slots.default">
8
- <slot></slot>
9
- </template>
10
-
11
- <template v-if="$slots.content" #content>
12
- <slot name="content"></slot>
13
- </template>
14
- </el-tooltip>
15
- </template>
16
-
17
- <script lang="ts" setup>
18
- import { computed } from 'vue'
19
-
20
- import { ElTooltip, type UseTooltipProps } from 'element-plus'
21
-
22
- import type { T_FlyTooltipProps } from './FlyTooltip.types'
23
-
24
- const props = defineProps<T_FlyTooltipProps>()
25
-
26
- const mergedElProps = computed<UseTooltipProps>(() => {
27
- return {
28
- enterable: false,
29
- showAfter: 1000,
30
- ...props.tooltip
31
- }
32
- })
33
-
34
- const popperClasses = computed(() => {
35
- const classes = []
36
-
37
- if (!mergedElProps.value.enterable) {
38
- classes.push('fly-tooltip-popper__no-enter')
39
- }
40
-
41
- return classes.join(' ')
42
- })
43
- </script>
44
-
45
- <style lang="scss">
46
- @use '../../../styles/mixins/shadows.scss' as shadow;
47
-
48
- .fly-tooltip-popper {
49
- @include shadow.shadow-lg;
50
- max-width: 400px;
51
-
52
- &__no-enter {
53
- .fly-tooltip {
54
- pointer-events: none;
55
- max-width: 400px;
56
- }
57
- }
58
- }
59
- </style>
1
+ <template>
2
+ <el-tooltip
3
+ v-bind="mergedElProps"
4
+ :popper-class="`fly-tooltip-popper ${popperClasses}`"
5
+ class="fly-tooltip"
6
+ >
7
+ <template v-if="$slots.default">
8
+ <slot></slot>
9
+ </template>
10
+
11
+ <template v-if="$slots.content" #content>
12
+ <slot name="content"></slot>
13
+ </template>
14
+ </el-tooltip>
15
+ </template>
16
+
17
+ <script lang="ts" setup>
18
+ import { computed } from 'vue'
19
+
20
+ import { ElTooltip, type UseTooltipProps } from 'element-plus'
21
+
22
+ import './FlyTooltip.element.scss'
23
+ import type { T_FlyTooltipProps } from './FlyTooltip.types'
24
+
25
+ const props = defineProps<T_FlyTooltipProps>()
26
+
27
+ const mergedElProps = computed<UseTooltipProps>(() => {
28
+ return {
29
+ enterable: false,
30
+ showAfter: 1000,
31
+ ...props.tooltip
32
+ }
33
+ })
34
+
35
+ const popperClasses = computed(() => {
36
+ const classes = []
37
+
38
+ if (!mergedElProps.value.enterable) {
39
+ classes.push('fly-tooltip-popper__no-enter')
40
+ }
41
+
42
+ return classes.join(' ')
43
+ })
44
+ </script>
45
+
46
+ <style lang="scss">
47
+ @use '../../../styles/mixins/shadows.scss' as shadow;
48
+
49
+ .fly-tooltip-popper {
50
+ @include shadow.shadow-lg;
51
+ max-width: 400px;
52
+
53
+ &__no-enter {
54
+ .fly-tooltip {
55
+ pointer-events: none;
56
+ max-width: 400px;
57
+ }
58
+ }
59
+ }
60
+ </style>
@@ -1,6 +1,6 @@
1
- import FlyTooltip from './FlyTooltip.vue'
2
-
3
- export default FlyTooltip
4
- export { FlyTooltip }
5
-
6
- export type { T_FlyTooltipProps } from './FlyTooltip.types'
1
+ import FlyTooltip from './FlyTooltip.vue'
2
+
3
+ export default FlyTooltip
4
+ export { FlyTooltip }
5
+
6
+ export type { T_FlyTooltipProps } from './FlyTooltip.types'
@@ -0,0 +1,57 @@
1
+ import type { Composer } from 'vue-i18n'
2
+
3
+ export type ValidateFieldsError = { [K: string]: { message?: string }[] }
4
+
5
+ /**
6
+ * @returns Translated error message based on active locale
7
+ */
8
+ export function formFieldErrorMessageFormatter(errors: ValidateFieldsError, composer?: Composer) {
9
+ const keys = Object.keys(errors)
10
+
11
+ const t = composer?.t
12
+
13
+ if (keys.length) {
14
+ const requiredFieldNames: (string | undefined)[] = []
15
+ const otherErrors: (string | undefined)[] = []
16
+ let formFieldErrorMessage = ''
17
+
18
+ keys.forEach((k) => {
19
+ const msg = errors[k][0].message
20
+ const index = msg?.indexOf(t ? t('validation.isRequired') : 'validation.isRequired')
21
+
22
+ if (index && index >= 0) {
23
+ requiredFieldNames.push(msg?.slice(0, index)?.trim())
24
+ } else {
25
+ otherErrors.push(msg)
26
+ }
27
+ })
28
+
29
+ const requiredFieldsLength = requiredFieldNames.length
30
+ const otherErrorsLength = otherErrors.length
31
+
32
+ if (requiredFieldsLength >= 1) {
33
+ const joinedList = new Intl.ListFormat(composer?.locale.value || 'en', {
34
+ style: 'long',
35
+ type: 'conjunction'
36
+ }).format(requiredFieldNames.filter((item): item is string => Boolean(item)))
37
+
38
+ formFieldErrorMessage = t
39
+ ? t('validation.requiredFields', {
40
+ field: joinedList,
41
+ count: requiredFieldNames.length
42
+ })
43
+ : joinedList
44
+ }
45
+
46
+ if (otherErrorsLength) {
47
+ if (formFieldErrorMessage) formFieldErrorMessage += ' || ' // temporary
48
+ otherErrors.forEach((e, i) => {
49
+ formFieldErrorMessage += e + `${i === otherErrorsLength - 1 ? '' : ' || '}` // temporary
50
+ })
51
+ }
52
+
53
+ return formFieldErrorMessage
54
+ }
55
+
56
+ return t ? t('validation.someInputsInvalid') : 'validation.someInputsInvalid'
57
+ }
File without changes
@@ -0,0 +1 @@
1
+ @use 'element-plus/theme-chalk/src/switch.scss' as *;
@@ -0,0 +1,16 @@
1
+ export type T_InputBooleanValues = string | number | boolean | undefined
2
+
3
+ export type T_InputBooleanBase = T_InputBoolean & {
4
+ type: 'boolean'
5
+ placeholder?: string
6
+ }
7
+
8
+ export type T_InputBoolean = {
9
+ /**
10
+ * Attrs are passed directly to the input element as props
11
+ */
12
+ attrs?: {
13
+ activeText?: string
14
+ inactiveText?: string
15
+ }
16
+ }
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <el-switch
3
+ v-model="inputProxy"
4
+ v-bind="input?.attrs"
5
+ @change="(v) => emit('change', v)"
6
+ ></el-switch>
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ import { computed } from 'vue'
11
+
12
+ import { ElSwitch } from 'element-plus'
13
+
14
+ import './FlyBoolean.scss'
15
+ import type { T_InputBoolean, T_InputBooleanValues } from './FlyBoolean.types'
16
+
17
+ const emit = defineEmits<{
18
+ (e: 'update:modelValue', v: T_InputBooleanValues): void
19
+ (e: 'change', v: T_InputBooleanValues): void
20
+ }>()
21
+
22
+ const props = defineProps<{
23
+ modelValue?: T_InputBooleanValues
24
+ input?: T_InputBoolean
25
+ }>()
26
+
27
+ const inputProxy = computed({
28
+ get: () => {
29
+ return props.modelValue
30
+ },
31
+ set: (v) => {
32
+ emit('update:modelValue', v)
33
+ }
34
+ })
35
+ </script>
@@ -0,0 +1 @@
1
+ @use '../../../../styles/element/overrides/date-time.scss';
@@ -0,0 +1,21 @@
1
+ export type T_DateTimeRawValue = Date | [Date, Date] | undefined
2
+ export type T_DateTimeValues = string | string[] | undefined
3
+
4
+ export type T_DateInputTypes = 'date' | 'dateTime' | 'dateRange' | 'dateTimeRange'
5
+
6
+ export type T_InputDateTimeBase = T_InputDateTime & {
7
+ type: 'dateTime'
8
+ }
9
+
10
+ export type T_InputDateTime = {
11
+ placeholder?: string
12
+ startPlaceholder?: string
13
+ endPlaceholder?: string
14
+ /**
15
+ * Attrs are passed directly to the input element as props
16
+ */
17
+ attrs?: { [K: string]: unknown }
18
+ config?: {
19
+ inputType?: T_DateInputTypes // defaults to dateTime
20
+ }
21
+ }
@@ -0,0 +1,85 @@
1
+ <template>
2
+ <el-date-picker
3
+ v-model="inputProxy"
4
+ style="width: 100%"
5
+ :type="inputTypeMap[input?.config?.inputType || 'dateTime']"
6
+ :popper-options="{
7
+ modifiers: [
8
+ {
9
+ name: 'preventOverflow',
10
+ options: {
11
+ padding: 8
12
+ }
13
+ }
14
+ ]
15
+ }"
16
+ :placeholder="input?.placeholder"
17
+ :start-placeholder="input?.startPlaceholder"
18
+ :end-placeholder="input?.endPlaceholder"
19
+ @change="(val: T_DateTimeRawValue) => emit('change', parseValueForEmit(val))"
20
+ @blur="() => emit('blur')"
21
+ @focus="() => emit('focus')"
22
+ />
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ import { computed } from 'vue'
27
+
28
+ import { type DatePickerProps, ElDatePicker } from 'element-plus'
29
+
30
+ import './FlyDateTime.scss'
31
+ import type { T_DateTimeRawValue, T_DateTimeValues, T_InputDateTime } from './FlyDateTime.types'
32
+
33
+ const emit = defineEmits<{
34
+ (e: 'update:modelValue', v: T_DateTimeValues): void
35
+ (e: 'change', v: T_DateTimeValues): void
36
+ (e: 'blur'): void
37
+ (e: 'focus'): void
38
+ }>()
39
+
40
+ const props = defineProps<{
41
+ modelValue?: T_DateTimeValues
42
+ input?: T_InputDateTime
43
+ }>()
44
+
45
+ const inputTypeMap: Record<string, DatePickerProps['type']> = {
46
+ date: 'date',
47
+ dateTime: 'datetime',
48
+ dateRange: 'daterange',
49
+ dateTimeRange: 'datetimerange'
50
+ }
51
+
52
+ const isRange = computed(
53
+ () =>
54
+ props.input?.config?.inputType === 'dateRange' ||
55
+ props.input?.config?.inputType === 'dateTimeRange'
56
+ )
57
+
58
+ const inputProxy = computed({
59
+ get: (): T_DateTimeRawValue => {
60
+ if (!props.modelValue) return undefined
61
+
62
+ if (isRange.value && Array.isArray(props.modelValue)) {
63
+ const d = props.modelValue.map((d) => new Date(d))
64
+ return [d[0], d[1]]
65
+ }
66
+
67
+ return new Date(props.modelValue as string)
68
+ },
69
+ set: (v) => {
70
+ emit('update:modelValue', parseValueForEmit(v))
71
+ }
72
+ })
73
+
74
+ function parseValueForEmit(v: T_DateTimeRawValue) {
75
+ if (!v) {
76
+ return undefined
77
+ }
78
+
79
+ if (isRange.value && Array.isArray(v)) {
80
+ return v.map((d: Date) => d.toISOString())
81
+ }
82
+
83
+ return (v as Date).toISOString()
84
+ }
85
+ </script>
@@ -0,0 +1,4 @@
1
+ @use 'element-plus/theme-chalk/src/form.scss';
2
+ @use 'element-plus/theme-chalk/src/form-item.scss';
3
+
4
+ @use 'element-plus/theme-chalk/src/icon.scss';
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <el-form-item :prop="input.prop || input.key">
3
+ <template #label>
4
+ <FlyInfoTooltip v-if="input.tooltip" :content="input.tooltip" />
5
+ {{ t(input.label) }}
6
+ </template>
7
+
8
+ <FlyInputRenderer
9
+ v-model="modelProxy"
10
+ :input="input"
11
+ @change="(val: unknown) => emit('change', val)"
12
+ @blur="() => emit('blur')"
13
+ @focus="() => emit('focus')"
14
+ />
15
+ </el-form-item>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import { computed } from 'vue'
20
+
21
+ import { ElFormItem } from 'element-plus'
22
+
23
+ import { UseLocaleInjector } from '../../../../composables/UseLocaleInjector'
24
+ import FlyInfoTooltip from '../../../feedback/tooltip/FlyInfoTooltip.vue'
25
+ import type { T_InputRendererBase } from '../input-renderer.types'
26
+ import FlyInputRenderer from '../input-renderer/FlyInputRenderer.vue'
27
+
28
+ import './FlyFormItemRenderer.scss'
29
+
30
+ const props = defineProps<{
31
+ modelValue: unknown
32
+ input: T_InputRendererBase
33
+ }>()
34
+
35
+ const emit = defineEmits<{
36
+ (e: 'update:modelValue', value: unknown): void
37
+ (e: 'change', value: unknown): void
38
+ (e: 'blur'): void
39
+ (e: 'focus'): void
40
+ }>()
41
+
42
+ const { t } = UseLocaleInjector()
43
+
44
+ const modelProxy = computed({
45
+ get: () => props.modelValue,
46
+ set: (val) => emit('update:modelValue', val)
47
+ })
48
+ </script>
@@ -0,0 +1,3 @@
1
+ import type FlyFormSchemaRenderer from './FlyFormSchemaRenderer.vue'
2
+
3
+ export type T_FlyFormSchemaRendererInstance = InstanceType<typeof FlyFormSchemaRenderer> | null
@@ -0,0 +1,246 @@
1
+ import type { FormInstance, FormItemRule } from 'element-plus'
2
+
3
+ import type { Composer } from 'vue-i18n'
4
+
5
+ import { checkInputRange } from '../../../../utils/validators'
6
+ import { formFieldErrorMessageFormatter } from '../../form.utils'
7
+ import {
8
+ checkInputRangeValidator,
9
+ requiredField,
10
+ requiredFieldArray,
11
+ requiredFieldNumber,
12
+ requiredFieldNumberSelect,
13
+ requiredFieldValueUnit
14
+ } from '../../input-validators'
15
+ import type {
16
+ T_FormSchemaLookupData,
17
+ T_InputSchema,
18
+ T_InputSchemaSelect,
19
+ T_InputSchemaValueUnit
20
+ } from '../form-schema.types'
21
+ import type { T_InputRendererBase } from '../input-renderer.types'
22
+ import type { T_InputSelectOption } from '../select/FlySelect.types'
23
+
24
+ export function getValidatorsFromInputFields(fields: T_InputRendererBase[]) {
25
+ const validators = fields.reduce(
26
+ (p, c) => {
27
+ if (c.validations) {
28
+ p[c.key] = c.validations
29
+ }
30
+ return p
31
+ },
32
+ {} as Record<string, FormItemRule[]>
33
+ )
34
+
35
+ return validators
36
+ }
37
+
38
+ export async function genericFormValidator(formRef: FormInstance): Promise<true> {
39
+ return new Promise((resolve, reject) => {
40
+ formRef.validate((valid, errors) => {
41
+ if (!valid) {
42
+ if (errors) {
43
+ return reject(formFieldErrorMessageFormatter(errors))
44
+ }
45
+ } else {
46
+ return resolve(true)
47
+ }
48
+ })
49
+ })
50
+ }
51
+
52
+ export function generateInputFromFormSchema(
53
+ field: T_InputSchema,
54
+ lookupData?: T_FormSchemaLookupData
55
+ ) {
56
+ switch (field.type) {
57
+ case 'text': {
58
+ const selectInput: T_InputRendererBase = {
59
+ label: field.label,
60
+ type: field.type,
61
+ key: field.unique_key,
62
+ attrs: {
63
+ maxlength: field.config?.maxLength,
64
+ minlength: field.config?.minLength,
65
+ showWordLimit: true,
66
+ type: field.config?.type || field.type,
67
+ rows: field.config?.rows
68
+ },
69
+ placeholder: field.placeholder,
70
+ tooltip: field.tooltip,
71
+ validations: generateFormRule(field)
72
+ }
73
+
74
+ return selectInput
75
+ }
76
+ case 'select': {
77
+ const selectInput: T_InputRendererBase = {
78
+ label: field.label,
79
+ type: field.type,
80
+ key: field.unique_key,
81
+ attrs: {
82
+ multiple: field.config.multiple
83
+ },
84
+ placeholder: field.placeholder,
85
+ tooltip: field.tooltip,
86
+ validations: generateFormRule(field),
87
+ config: {
88
+ options: generateSelectOptionsFromSchema(field, lookupData)
89
+ }
90
+ }
91
+
92
+ return selectInput
93
+ }
94
+ case 'valueUnit': {
95
+ const selectInput: T_InputRendererBase = {
96
+ label: field.label,
97
+ type: field.type,
98
+ key: field.unique_key,
99
+ attrs: {},
100
+ placeholder: field.placeholder,
101
+ tooltip: field.tooltip,
102
+ validations: generateFormRule(field),
103
+ config: {
104
+ options: generateSelectOptionsFromSchema(field, lookupData)
105
+ }
106
+ }
107
+
108
+ return selectInput
109
+ }
110
+ case 'number': {
111
+ const selectInput: T_InputRendererBase = {
112
+ label: field.label,
113
+ type: field.type,
114
+ key: field.unique_key,
115
+ attrs: {},
116
+ placeholder: field.placeholder,
117
+ tooltip: field.tooltip,
118
+ validations: generateFormRule(field)
119
+ }
120
+
121
+ return selectInput
122
+ }
123
+ case 'boolean': {
124
+ const selectInput: T_InputRendererBase = {
125
+ label: field.label,
126
+ type: field.type,
127
+ key: field.unique_key,
128
+ attrs: {
129
+ activeText: field.config?.activeText,
130
+ inactiveText: field.config?.inactiveText
131
+ },
132
+ placeholder: field.placeholder,
133
+ tooltip: field.tooltip,
134
+ validations: generateFormRule(field)
135
+ }
136
+
137
+ return selectInput
138
+ }
139
+ case 'dateTime': {
140
+ const selectInput: T_InputRendererBase = {
141
+ label: field.label,
142
+ type: field.type,
143
+ key: field.unique_key,
144
+ placeholder: field.placeholder,
145
+ tooltip: field.tooltip,
146
+ validations: generateFormRule(field),
147
+ config: {
148
+ inputType: field.config?.inputType
149
+ }
150
+ }
151
+
152
+ return selectInput
153
+ }
154
+ default:
155
+ break
156
+ }
157
+ }
158
+
159
+ export function generateFormRule(field: T_InputSchema, composer?: Composer): FormItemRule[] {
160
+ const validations = field.validation
161
+ const rules: FormItemRule[] = []
162
+
163
+ if (validations?.required) {
164
+ switch (field.type) {
165
+ case 'text': {
166
+ rules.push(requiredField(field.label, 'blur', true, composer))
167
+
168
+ if (field.validation?.minLength || field.validation?.maxLength) {
169
+ rules.push(
170
+ checkInputRangeValidator(
171
+ checkInputRange(
172
+ field.label,
173
+ {
174
+ min: field.validation?.minLength,
175
+ max: field.validation?.maxLength
176
+ },
177
+ undefined,
178
+ undefined,
179
+ composer
180
+ ),
181
+ 'blur'
182
+ )
183
+ )
184
+ }
185
+
186
+ break
187
+ }
188
+
189
+ case 'dateTime': {
190
+ rules.push(requiredField(field.label, 'blur', true, composer))
191
+ break
192
+ }
193
+
194
+ case 'number': {
195
+ rules.push(requiredFieldNumber(field.label, 'change', composer))
196
+ break
197
+ }
198
+
199
+ case 'select': {
200
+ if (field.config.multiple) {
201
+ rules.push(requiredFieldArray(field.label, 'change', true, composer))
202
+ } else {
203
+ rules.push(requiredField(field.label, 'change', true, composer))
204
+ }
205
+ break
206
+ }
207
+
208
+ case 'valueUnit': {
209
+ if (field.config.valueType === 'text') {
210
+ rules.push(
211
+ requiredFieldValueUnit(
212
+ field.label,
213
+ 'change',
214
+ undefined,
215
+ undefined,
216
+ {
217
+ valueType: 'text'
218
+ },
219
+ composer
220
+ )
221
+ )
222
+ } else {
223
+ rules.push(requiredFieldNumberSelect(field.label, 'change', true, composer))
224
+ }
225
+ }
226
+ }
227
+ }
228
+
229
+ return rules
230
+ }
231
+
232
+ export function generateSelectOptionsFromSchema(
233
+ field: T_InputSchemaSelect | T_InputSchemaValueUnit,
234
+ lookupData?: T_FormSchemaLookupData
235
+ ): T_InputSelectOption[] {
236
+ const optionsArr = field.config?.options
237
+ if (optionsArr) return optionsArr
238
+
239
+ if (!lookupData) return []
240
+ const lookupId = field.config.options_config_Lookup_id
241
+ if (!lookupId) return []
242
+
243
+ const record = lookupData[lookupId]
244
+
245
+ return record ? (record as T_InputSelectOption[]) : []
246
+ }