@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
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <div class="fly-form-schema-renderer">
3
+ <el-form
4
+ ref="formRef"
5
+ :rules="dynamicValidators"
6
+ :model="formProxy"
7
+ label-position="top"
8
+ status-icon
9
+ :disabled="disabled"
10
+ @submit.prevent
11
+ >
12
+ <div class="fly-form-schema-renderer__form-holder">
13
+ <div
14
+ v-for="(input, i) in generatedForm?.inputs"
15
+ :key="i"
16
+ :style="{
17
+ gridColumn: `span ${getSpan(input)} / span ${getSpan(input)}`
18
+ }"
19
+ >
20
+ <FlyFormItemRenderer v-model="formProxy[input.key]" :input="input" />
21
+ </div>
22
+ </div>
23
+ </el-form>
24
+ </div>
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import { ref } from 'vue'
29
+
30
+ import { ElForm, type FormInstance } from 'element-plus'
31
+
32
+ import '../../../../styles/element/overrides/form.scss'
33
+ import FlyFormItemRenderer from '../form-item-renderer/FlyFormItemRenderer.vue'
34
+ import type { T_InputRendererBase } from '../input-renderer.types'
35
+
36
+ import {
37
+ type T_FormSchemaRendererEmits,
38
+ type T_FormSchemaRendererProps,
39
+ UseFormSchemaRenderer
40
+ } from './UseFormSchemaRenderer'
41
+
42
+ const emit = defineEmits<T_FormSchemaRendererEmits>()
43
+
44
+ const props = defineProps<
45
+ T_FormSchemaRendererProps & {
46
+ /**
47
+ * Column span within a 12 column grid
48
+ */
49
+ columnSpan?: number
50
+ }
51
+ >()
52
+
53
+ const formRef = ref<FormInstance>()
54
+
55
+ const dynamicConfigFormComp = UseFormSchemaRenderer({ formRef, props, emit })
56
+ const { dynamicValidators, formProxy, generatedForm } = dynamicConfigFormComp
57
+
58
+ function getSpan(input?: T_InputRendererBase) {
59
+ return input?.columnSpan || props.columnSpan || 4
60
+ }
61
+
62
+ defineExpose({
63
+ validateForm: dynamicConfigFormComp.validateForm
64
+ })
65
+ </script>
66
+
67
+ <style lang="scss" scoped>
68
+ .fly-form-schema-renderer {
69
+ &__form-holder {
70
+ display: grid;
71
+ grid-template-columns: repeat(12, minmax(0, 1fr));
72
+ gap: 0.5rem;
73
+ }
74
+ }
75
+ </style>
@@ -0,0 +1,97 @@
1
+ import { type Ref, computed, ref, watch } from 'vue'
2
+
3
+ import type { FormInstance } from 'element-plus'
4
+
5
+ import { defaultsDeep } from 'lodash'
6
+
7
+ import type { T_FormSchemaLookupData, T_InputSchema } from '../form-schema.types'
8
+ import type { T_FormSchemaRendererConfig, T_InputRendererBase } from '../input-renderer.types'
9
+
10
+ import {
11
+ generateInputFromFormSchema,
12
+ genericFormValidator,
13
+ getValidatorsFromInputFields
14
+ } from './FlyFormSchemaRenderer.utils'
15
+
16
+ export type T_FormSchemaRendererProps = {
17
+ formConfig: T_InputSchema[]
18
+ lookupData?: T_FormSchemaLookupData
19
+ modelValue?: Record<string, unknown>
20
+ disabled?: boolean
21
+ }
22
+
23
+ export type T_FormSchemaRendererEmits = {
24
+ (e: 'update:modelValue', value: T_FormSchemaRendererProps['modelValue']): void
25
+ }
26
+
27
+ type ConfigFormCompArgs = {
28
+ formRef: Ref<FormInstance | undefined>
29
+ props: T_FormSchemaRendererProps
30
+ emit: T_FormSchemaRendererEmits
31
+ }
32
+
33
+ export function UseFormSchemaRenderer(args: ConfigFormCompArgs) {
34
+ const fallbackForm = {}
35
+
36
+ const formProxy = computed<Record<string, unknown>>({
37
+ get: () => args.props.modelValue || fallbackForm,
38
+ set: (val) => args.emit('update:modelValue', val)
39
+ })
40
+
41
+ const generatedForm = ref<T_FormSchemaRendererConfig>()
42
+ const dynamicFormGenerated = ref(false)
43
+
44
+ const dynamicValidators = computed(() => {
45
+ const validators =
46
+ generatedForm.value && getValidatorsFromInputFields(generatedForm.value.inputs)
47
+
48
+ return validators || {}
49
+ })
50
+
51
+ async function validateForm() {
52
+ return args.formRef.value && genericFormValidator(args.formRef.value)
53
+ }
54
+
55
+ function generateDynamicForm() {
56
+ try {
57
+ if (dynamicFormGenerated.value) return
58
+
59
+ const inputs: T_InputRendererBase[] = []
60
+ const baseForm: T_FormSchemaRendererConfig['baseForm'] = {}
61
+
62
+ args.props.formConfig.forEach((f) => {
63
+ const i = generateInputFromFormSchema(f, args.props.lookupData)
64
+ if (i) {
65
+ inputs.push(i)
66
+ baseForm[i.key] = f.default_value
67
+ }
68
+ })
69
+
70
+ dynamicFormGenerated.value = true
71
+
72
+ defaultsDeep(args.props.modelValue, baseForm)
73
+
74
+ generatedForm.value = { inputs, baseForm }
75
+ } catch (error) {
76
+ console.error(error)
77
+ }
78
+ }
79
+
80
+ watch(
81
+ () => args.props.formConfig,
82
+ () => {
83
+ dynamicFormGenerated.value = false
84
+ generateDynamicForm()
85
+ },
86
+ {
87
+ immediate: true
88
+ }
89
+ )
90
+
91
+ return {
92
+ dynamicValidators,
93
+ formProxy,
94
+ generatedForm,
95
+ validateForm
96
+ }
97
+ }
@@ -0,0 +1,95 @@
1
+ import type { T_DateInputTypes } from './date-time/FlyDateTime.types'
2
+ import type { T_InputSelectOption } from './select/FlySelect.types'
3
+ import type { T_ValueUnitValue } from './value-unit/FlyValueUnit.types'
4
+
5
+ export type T_FormSchemaLookupData = Record<string, Array<unknown>>
6
+
7
+ export type T_InputSchema =
8
+ | T_InputSchemaText
9
+ | T_InputSchemaNumber
10
+ | T_InputSchemaBoolean
11
+ | T_InputSchemaSelect
12
+ | T_InputSchemaValueUnit
13
+ | T_InputSchemaDateTime
14
+
15
+ type T_FieldValidationBase = {
16
+ required?: boolean
17
+ }
18
+
19
+ type T_InputSchemaBase<ValidationRules = object> = {
20
+ unique_key: string
21
+ label: string
22
+ tooltip?: string
23
+ placeholder?: string
24
+ validation?: T_FieldValidationBase & ValidationRules
25
+ }
26
+
27
+ export type T_InputSchemaText = T_InputSchemaBase<{
28
+ minLength?: number
29
+ maxLength?: number
30
+ }> & {
31
+ type: 'text'
32
+ default_value?: string
33
+ config?: {
34
+ maxLength?: number
35
+ minLength?: number
36
+ type?: string
37
+ rows?: number
38
+ }
39
+ }
40
+
41
+ export type T_InputSchemaNumber = T_InputSchemaBase<{
42
+ minLength?: number
43
+ maxLength?: number
44
+ }> & {
45
+ type: 'number'
46
+ default_value?: number
47
+ config?: {
48
+ minLength?: number
49
+ maxLength?: number
50
+ }
51
+ }
52
+
53
+ export type T_InputSchemaBoolean = T_InputSchemaBase & {
54
+ type: 'boolean'
55
+ default_value?: boolean
56
+ config?: {
57
+ activeText?: string
58
+ inactiveText?: string
59
+ }
60
+ }
61
+
62
+ type T_SelectOptions =
63
+ | {
64
+ options_config_Lookup_id: string
65
+ options?: never
66
+ }
67
+ | {
68
+ options?: T_InputSelectOption[]
69
+ options_config_Lookup_id?: never
70
+ }
71
+ type T_SelectBase<M extends boolean | undefined> = T_InputSchemaBase & {
72
+ type: 'select'
73
+ config: T_SelectOptions & {
74
+ multiple?: M
75
+ }
76
+ default_value?: M extends true ? (string | number)[] : string | number
77
+ }
78
+
79
+ export type T_InputSchemaSelect = T_SelectBase<true> | T_SelectBase<false | undefined>
80
+
81
+ export type T_InputSchemaValueUnit = T_InputSchemaBase & {
82
+ type: 'valueUnit'
83
+ config: T_SelectOptions & {
84
+ valueType?: 'text' | 'number'
85
+ }
86
+ default_value?: T_ValueUnitValue
87
+ }
88
+
89
+ export type T_InputSchemaDateTime = T_InputSchemaBase & {
90
+ type: 'dateTime'
91
+ default_value?: string | [string | string]
92
+ config?: {
93
+ inputType: T_DateInputTypes
94
+ }
95
+ }
@@ -0,0 +1,49 @@
1
+ <template>
2
+ <div style="width: 100%">
3
+ <component
4
+ :is="map[input.type]"
5
+ :model-value="modelValue"
6
+ :input="input"
7
+ @change="(v: unknown) => emit('change', v)"
8
+ @update:model-value="(v: unknown) => emit('update:modelValue', v)"
9
+ @blur="emit('blur')"
10
+ @focus="emit('focus')"
11
+ />
12
+ </div>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import FlyBoolean from '../boolean/FlyBoolean.vue'
17
+ import FlyDateTime from '../date-time/FlyDateTime.vue'
18
+ import type {
19
+ T_DynamicInputComponent,
20
+ T_InputRendererBase,
21
+ T_InputTypes
22
+ } from '../input-renderer.types'
23
+ import FlyNumber from '../number/FlyNumber.vue'
24
+ import FlySelect from '../select/FlySelect.vue'
25
+ import FlyText from '../text/FlyText.vue'
26
+ import FlyValueUnit from '../value-unit/FlyValueUnit.vue'
27
+
28
+ const emit = defineEmits<{
29
+ (e: 'update:modelValue', v: unknown): void
30
+ (e: 'change', v: unknown): void
31
+ (e: 'blur'): void
32
+ (e: 'focus'): void
33
+ }>()
34
+
35
+ defineProps<{
36
+ modelValue: unknown
37
+ input: T_InputRendererBase
38
+ }>()
39
+
40
+ const map: Record<T_InputTypes, T_DynamicInputComponent> = {
41
+ text: FlyText,
42
+ textarea: FlyText,
43
+ number: FlyNumber,
44
+ valueUnit: FlyValueUnit,
45
+ select: FlySelect,
46
+ boolean: FlyBoolean,
47
+ dateTime: FlyDateTime
48
+ }
49
+ </script>
@@ -0,0 +1,49 @@
1
+ import type { Component } from 'vue'
2
+
3
+ import type { FormItemRule } from 'element-plus'
4
+
5
+ import type { T_InputBoolean, T_InputBooleanBase } from './boolean/FlyBoolean.types'
6
+ import type { T_InputDateTime, T_InputDateTimeBase } from './date-time/FlyDateTime.types'
7
+ import type { T_InputNumber, T_InputNumberBase } from './number/FlyNumber.types'
8
+ import type { T_InputSelect, T_InputSelectBase } from './select/FlySelect.types'
9
+ import type { T_InputText, T_InputTextBase } from './text/FlyText.types'
10
+ import type { T_InputValueUnit, T_InputValueUnitBase } from './value-unit/FlyValueUnit.types'
11
+
12
+ export type T_DynamicInputPropsBase = {
13
+ key: string
14
+ prop?: string // for form validation. falls back to key
15
+ label: string
16
+ tooltip?: string
17
+ columnSpan?: number
18
+ validations?: FormItemRule[]
19
+ }
20
+
21
+ export type T_InputRendererBase = T_DynamicInputPropsBase & T_SupportedInputTypeBase
22
+
23
+ export type T_SupportedInputTypeBase =
24
+ | T_InputTextBase
25
+ | T_InputBooleanBase
26
+ | T_InputDateTimeBase
27
+ | T_InputNumberBase
28
+ | T_InputSelectBase
29
+ | T_InputValueUnitBase
30
+
31
+ export type T_SupportedInputType =
32
+ | T_InputText
33
+ | T_InputNumber
34
+ | T_InputValueUnit
35
+ | T_InputSelect
36
+ | T_InputBoolean
37
+ | T_InputDateTime
38
+
39
+ export type T_InputTypes = T_SupportedInputTypeBase['type']
40
+
41
+ export type T_DynamicInputComponent = Component<{
42
+ modelValue?: unknown
43
+ input?: T_SupportedInputType
44
+ }>
45
+
46
+ export type T_FormSchemaRendererConfig = {
47
+ inputs: T_InputRendererBase[]
48
+ baseForm: { [K: string]: unknown }
49
+ }
@@ -0,0 +1,18 @@
1
+ import { isNil } from 'lodash'
2
+
3
+ import type { T_InputTypes } from './input-renderer.types'
4
+
5
+ export function getInputDisplayValue(v: unknown, inputType: T_InputTypes) {
6
+ switch (inputType) {
7
+ case 'number':
8
+ if (v === null || v === undefined) return ''
9
+ return String(v)
10
+
11
+ case 'text':
12
+ default:
13
+ if (isNil(v)) {
14
+ return ''
15
+ }
16
+ return typeof v === 'string' ? v : String(v)
17
+ }
18
+ }
@@ -0,0 +1 @@
1
+ @use 'element-plus/theme-chalk/src/input.scss';
@@ -0,0 +1,13 @@
1
+ export type T_InputTextValues = string | number | undefined
2
+
3
+ export type T_InputNumberBase = T_InputNumber & {
4
+ type: 'number'
5
+ }
6
+
7
+ export type T_InputNumber = {
8
+ placeholder?: string
9
+ /**
10
+ * Attrs are passed directly to the input element as props
11
+ */
12
+ attrs?: { [K: string]: unknown }
13
+ }
@@ -0,0 +1,6 @@
1
+ export function displayToNumber(v: unknown): number | undefined {
2
+ if (v === '' || v === undefined || v === undefined) return undefined
3
+
4
+ const n = Number(v)
5
+ return Number.isNaN(n) ? undefined : n
6
+ }
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <el-input
3
+ v-model.number="inputProxy"
4
+ style="width: 100%"
5
+ type="number"
6
+ v-bind="input?.attrs"
7
+ :placeholder="input?.placeholder"
8
+ @change="(val) => emit('change', displayToNumber(val))"
9
+ @blur="() => emit('blur')"
10
+ @focus="() => emit('focus')"
11
+ >
12
+ </el-input>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { computed } from 'vue'
17
+
18
+ import { ElInput } from 'element-plus'
19
+
20
+ import { getInputDisplayValue } from '../input-renderer.utils'
21
+
22
+ import './FlyNumber.scss'
23
+ import type { T_InputNumber, T_InputTextValues } from './FlyNumber.types'
24
+ import { displayToNumber } from './FlyNumber.utils'
25
+
26
+ const emit = defineEmits<{
27
+ (e: 'update:modelValue', v: T_InputTextValues): void
28
+ (e: 'change', v: T_InputTextValues): void
29
+ (e: 'blur'): void
30
+ (e: 'focus'): void
31
+ }>()
32
+
33
+ const props = defineProps<{
34
+ modelValue?: unknown
35
+ input?: T_InputNumber
36
+ }>()
37
+
38
+ const inputProxy = computed({
39
+ get: () => {
40
+ return getInputDisplayValue(props.modelValue, 'number')
41
+ },
42
+ set: (v) => {
43
+ const parsed = displayToNumber(v)
44
+ emit('update:modelValue', parsed)
45
+ emit('change', parsed)
46
+ }
47
+ })
48
+ </script>
@@ -0,0 +1,15 @@
1
+ import type { T_FormSchemaLookupData, T_InputSchema } from '../form-schema.types'
2
+
3
+ export type T_TenantRegionalFormSection = {
4
+ key: string
5
+ fields: T_InputSchema[]
6
+ title: string
7
+ description?: string
8
+ lookupData?: T_FormSchemaLookupData
9
+ modelValue?: Record<string, unknown>
10
+ }
11
+
12
+ export type T_TenantRegionalFormProps = {
13
+ mainFormTitle: string
14
+ sections?: T_TenantRegionalFormSection[]
15
+ }
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <div class="fly-regional-tenant-form-renderer">
3
+ <el-collapse v-if="sections?.length" v-model="activeNames" accordion>
4
+ <el-collapse-item :name="E_CollapsibleSections.mainForm">
5
+ <template #title>
6
+ <FlyCollapseTitleRenderer :title="mainFormTitle" />
7
+ </template>
8
+
9
+ <div style="padding: 1rem">
10
+ <slot></slot>
11
+ </div>
12
+ </el-collapse-item>
13
+
14
+ <template v-for="section in sections">
15
+ <el-collapse-item v-if="section.fields?.length" :key="section.key" :name="section.key">
16
+ <template #title>
17
+ <FlyCollapseTitleRenderer :title="section.title" />
18
+ </template>
19
+ <div style="padding: 1rem">
20
+ <div v-if="section.description" style="margin-bottom: 1.25rem">
21
+ <p style="font-size: 0.875; line-height: 1.25rem">
22
+ {{ t(section.description) }}
23
+ </p>
24
+ </div>
25
+
26
+ <FlyFormSchemaRenderer
27
+ :ref="(el) => setFormRef(el, section.key)"
28
+ v-model="section.modelValue"
29
+ :lookup-data="section.lookupData"
30
+ :form-config="section.fields"
31
+ :column-span="6"
32
+ />
33
+ </div>
34
+ </el-collapse-item>
35
+ </template>
36
+ </el-collapse>
37
+
38
+ <div v-else>
39
+ <slot></slot>
40
+ </div>
41
+ </div>
42
+ </template>
43
+
44
+ <script setup lang="ts">
45
+ import { type ComponentPublicInstance, reactive, ref } from 'vue'
46
+
47
+ import { ElCollapse, ElCollapseItem } from 'element-plus'
48
+
49
+ import { UseLocaleInjector } from '../../../../composables/UseLocaleInjector'
50
+ import '../../../../styles/element/overrides/collapse.scss'
51
+ import FlyCollapseTitleRenderer from '../../../basic/typography/FlyCollapseTitleRenderer.vue'
52
+ import type { T_FlyFormSchemaRendererInstance } from '../form-schema-renderer/FlyFormSchemaRenderer.types'
53
+ import FlyFormSchemaRenderer from '../form-schema-renderer/FlyFormSchemaRenderer.vue'
54
+
55
+ import type { T_TenantRegionalFormProps } from './FlyRegionalTenantFormRenderer.types'
56
+
57
+ enum E_CollapsibleSections {
58
+ mainForm
59
+ }
60
+
61
+ defineProps<T_TenantRegionalFormProps>()
62
+
63
+ const { t } = UseLocaleInjector()
64
+
65
+ const activeNames = ref<string | number>(E_CollapsibleSections.mainForm)
66
+ const formRefs = reactive<{ [K: string]: T_FlyFormSchemaRendererInstance }>({})
67
+
68
+ function setFormRef(formRef: Element | ComponentPublicInstance | null, key: string) {
69
+ if (formRef) {
70
+ formRefs[key] = formRef as T_FlyFormSchemaRendererInstance
71
+ }
72
+ }
73
+
74
+ async function validateForms() {
75
+ const keys = Object.keys(formRefs)
76
+ for (let index = 0; index < keys.length; index++) {
77
+ const element = formRefs[keys[index]]
78
+ const hasErrors = await element?.validateForm()
79
+ if (!hasErrors) continue
80
+ return hasErrors
81
+ }
82
+
83
+ return
84
+ }
85
+
86
+ defineExpose({
87
+ validateForms
88
+ })
89
+ </script>
90
+
91
+ <style lang="scss" scoped>
92
+ @use '../../../../styles/element/mixins/collapse.scss' as el-collapse-mixin;
93
+
94
+ .fly-regional-tenant-form-renderer {
95
+ :deep(.el-collapse) {
96
+ @include el-collapse-mixin.el-collapse-operation-style;
97
+ }
98
+ }
99
+ </style>
@@ -0,0 +1,9 @@
1
+ @use 'element-plus/theme-chalk/src/select.scss';
2
+ @use 'element-plus/theme-chalk/src/option.scss';
3
+
4
+ @use 'element-plus/theme-chalk/src/input.scss';
5
+ @use 'element-plus/theme-chalk/src/tag.scss';
6
+
7
+ @use 'element-plus/theme-chalk/src/popper.scss';
8
+ @use 'element-plus/theme-chalk/src/scrollbar.scss';
9
+ @use 'element-plus/theme-chalk/src/icon.scss';
@@ -0,0 +1,25 @@
1
+ export type T_InputSelectValue = string | number | (string | number)[] | undefined
2
+
3
+ export type T_InputLabelValue = {
4
+ label: string
5
+ value: string | number
6
+ }
7
+ export type T_InputSelectOption = T_InputLabelValue | (number | string)
8
+ export type T_InputSelectOptionList = T_InputSelectOption[] | Record<string, T_InputLabelValue>
9
+
10
+ export type T_InputSelectBase = T_InputSelect & {
11
+ type: 'select'
12
+ }
13
+
14
+ export type T_InputSelect = {
15
+ placeholder?: string
16
+ /**
17
+ * Attrs are passed directly to the input element as props
18
+ */
19
+ attrs?: {
20
+ multiple?: boolean
21
+ }
22
+ config?: {
23
+ options: T_InputSelectOptionList
24
+ }
25
+ }
@@ -0,0 +1,37 @@
1
+ import { isArray, isObject } from 'lodash'
2
+
3
+ import type {
4
+ T_InputLabelValue,
5
+ T_InputSelectOption,
6
+ T_InputSelectOptionList
7
+ } from './FlySelect.types'
8
+
9
+ export function normalizeSelectOptionsToDict(
10
+ options: T_InputSelectOptionList
11
+ ): Record<string, T_InputLabelValue> {
12
+ // already a dict: Record<string, {label,value}>
13
+ if (!isArray(options)) {
14
+ const out: Record<string, T_InputLabelValue> = {}
15
+ Object.keys(options).forEach((k) => {
16
+ const item = options[k]
17
+ out[String(item.value)] = item
18
+ })
19
+ return out
20
+ }
21
+
22
+ // array: (string|number) OR {label,value}
23
+ const out: Record<string, T_InputLabelValue> = {}
24
+ options.forEach((opt: T_InputSelectOption) => {
25
+ if (isObject(opt)) {
26
+ const lv = opt as T_InputLabelValue
27
+ out[String(lv.value)] = lv
28
+ } else {
29
+ // primitive option => label=value
30
+ out[String(opt)] = {
31
+ label: String(opt),
32
+ value: opt
33
+ }
34
+ }
35
+ })
36
+ return out
37
+ }