@flyanra/vue-core 1.3.9 → 1.5.0

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 (53) hide show
  1. package/dist/types/components/form/index.d.ts +1 -3
  2. package/dist/types/components/form/input-renderers/country-input/FlyCountryCitySelect.vue.d.ts +19 -0
  3. package/dist/types/components/form/input-renderers/country-input/FlyCountrySelect.types.d.ts +4 -0
  4. package/dist/types/components/form/input-renderers/country-input/FlyCountrySelect.vue.d.ts +30 -0
  5. package/dist/types/components/form/input-renderers/country-input/FlyCountryStatesSelect.vue.d.ts +19 -0
  6. package/dist/types/components/form/input-renderers/country-input/countries.d.ts +49 -0
  7. package/dist/types/components/form/input-renderers/country-input/index.d.ts +5 -0
  8. package/dist/types/components/form/input-renderers/index.d.ts +8 -0
  9. package/dist/types/components/form/input-renderers/otp-input/FlyOTPInput.vue.d.ts +15 -0
  10. package/dist/types/components/form/input-renderers/otp-input/index.d.ts +3 -0
  11. package/dist/types/components/form/input-renderers/phone-number/FlyPhoneNumberInput.types.d.ts +1 -0
  12. package/dist/types/components/form/input-renderers/phone-number/FlyPhoneNumberInput.vue.d.ts +17 -0
  13. package/dist/types/components/form/input-renderers/phone-number/index.d.ts +3 -0
  14. package/dist/types/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.types.d.ts +8 -1
  15. package/dist/types/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.vue.d.ts +8 -4
  16. package/dist/types/components/form/input-renderers/regional-tenant-form-renderer/index.d.ts +4 -0
  17. package/dist/types/components/form/input-validators.d.ts +5 -0
  18. package/dist/types/composables/useLocaleInjector/index.d.ts +2 -2
  19. package/dist/types/composables/useLocaleInjector/useLocaleInjector.d.ts +13 -0
  20. package/dist/types/utils/country-utils.d.ts +3 -0
  21. package/dist/types/utils/index.d.ts +1 -0
  22. package/package.json +5 -1
  23. package/src/components/basic/typography/FlyCollapseTitleRenderer.vue +2 -2
  24. package/src/components/form/form.utils.ts +3 -3
  25. package/src/components/form/index.ts +1 -4
  26. package/src/components/form/input-renderers/country-input/FlyCountryCitySelect.vue +73 -0
  27. package/src/components/form/input-renderers/country-input/FlyCountrySelect.types.ts +4 -0
  28. package/src/components/form/input-renderers/country-input/FlyCountrySelect.vue +76 -0
  29. package/src/components/form/input-renderers/country-input/FlyCountryStatesSelect.vue +81 -0
  30. package/src/components/form/input-renderers/country-input/countries.ts +5746 -0
  31. package/src/components/form/input-renderers/country-input/index.ts +6 -0
  32. package/src/components/form/input-renderers/form-item-renderer/FlyFormItemRenderer.vue +2 -2
  33. package/src/components/form/input-renderers/index.ts +19 -0
  34. package/src/components/form/input-renderers/otp-input/FlyOTPInput.scss +27 -0
  35. package/src/components/form/input-renderers/otp-input/FlyOTPInput.vue +98 -0
  36. package/src/components/form/input-renderers/otp-input/index.ts +4 -0
  37. package/src/components/form/input-renderers/phone-number/FlyPhoneNumberInput.scss +1 -0
  38. package/src/components/form/input-renderers/phone-number/FlyPhoneNumberInput.types.ts +0 -0
  39. package/src/components/form/input-renderers/phone-number/FlyPhoneNumberInput.vue +98 -0
  40. package/src/components/form/input-renderers/phone-number/index.ts +4 -0
  41. package/src/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.types.ts +13 -1
  42. package/src/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.vue +18 -19
  43. package/src/components/form/input-renderers/regional-tenant-form-renderer/index.ts +10 -0
  44. package/src/components/form/input-validators.ts +109 -2
  45. package/src/composables/useLocaleInjector/index.ts +2 -2
  46. package/src/composables/useLocaleInjector/useLocaleInjector.ts +34 -0
  47. package/src/styles/element/overrides/date-time.scss +4 -0
  48. package/src/styles/element/overrides/form.scss +13 -2
  49. package/src/utils/country-utils.ts +27 -0
  50. package/src/utils/index.ts +2 -0
  51. package/src/utils/validators.ts +3 -3
  52. package/dist/types/composables/useLocaleInjector/UseLocaleInjector.d.ts +0 -14
  53. package/src/composables/useLocaleInjector/UseLocaleInjector.ts +0 -37
@@ -1,5 +1,3 @@
1
- export * from './input-renderers/form-item-renderer';
2
- export * from './input-renderers/input-renderer';
3
- export type { T_InputRendererBase } from './input-renderers/input-renderer.types';
1
+ export * from './input-renderers';
4
2
  export * from './input-validators';
5
3
  export * from './form.utils';
@@ -0,0 +1,19 @@
1
+ import '../select/FlySelect.scss';
2
+ type __VLS_Props = {
3
+ modelValue?: string;
4
+ country?: string;
5
+ state?: string;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
8
+ focus: () => any;
9
+ "update:modelValue": (value: string | undefined) => any;
10
+ change: (value: string | undefined) => any;
11
+ blur: () => any;
12
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
13
+ onFocus?: (() => any) | undefined;
14
+ "onUpdate:modelValue"?: ((value: string | undefined) => any) | undefined;
15
+ onChange?: ((value: string | undefined) => any) | undefined;
16
+ onBlur?: (() => any) | undefined;
17
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ declare const _default: typeof __VLS_export;
19
+ export default _default;
@@ -0,0 +1,4 @@
1
+ export type T_CountryValueLabel = {
2
+ label: string;
3
+ value: string;
4
+ };
@@ -0,0 +1,30 @@
1
+ import '../select/FlySelect.scss';
2
+ import type { T_CountryValueLabel } from './FlyCountrySelect.types';
3
+ type __VLS_Props = {
4
+ modelValue?: string | undefined;
5
+ };
6
+ declare var __VLS_13: {
7
+ scope: T_CountryValueLabel;
8
+ };
9
+ type __VLS_Slots = {} & {
10
+ label?: (props: typeof __VLS_13) => any;
11
+ };
12
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
13
+ focus: () => any;
14
+ "update:modelValue": (v?: string | undefined) => any;
15
+ change: (v: string | undefined) => any;
16
+ blur: () => any;
17
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
18
+ onFocus?: (() => any) | undefined;
19
+ "onUpdate:modelValue"?: ((v?: string | undefined) => any) | undefined;
20
+ onChange?: ((v: string | undefined) => any) | undefined;
21
+ onBlur?: (() => any) | undefined;
22
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
23
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
24
+ declare const _default: typeof __VLS_export;
25
+ export default _default;
26
+ type __VLS_WithSlots<T, S> = T & {
27
+ new (): {
28
+ $slots: S;
29
+ };
30
+ };
@@ -0,0 +1,19 @@
1
+ import '../select/FlySelect.scss';
2
+ import '../text/FlyText.scss';
3
+ type __VLS_Props = {
4
+ modelValue?: string;
5
+ country?: string;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
8
+ focus: () => any;
9
+ "update:modelValue": (value: string | undefined) => any;
10
+ change: (value: string | undefined) => any;
11
+ blur: () => any;
12
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
13
+ onFocus?: (() => any) | undefined;
14
+ "onUpdate:modelValue"?: ((value: string | undefined) => any) | undefined;
15
+ onChange?: ((value: string | undefined) => any) | undefined;
16
+ onBlur?: (() => any) | undefined;
17
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ declare const _default: typeof __VLS_export;
19
+ export default _default;
@@ -0,0 +1,49 @@
1
+ interface I_CountryFlags {
2
+ png: string;
3
+ svg: string;
4
+ alt: string;
5
+ }
6
+ interface I_CountryPostalCode {
7
+ format?: string;
8
+ regex?: string;
9
+ }
10
+ interface I_CountryNativeName {
11
+ official: string;
12
+ common: string;
13
+ }
14
+ interface I_CountryName {
15
+ common: string;
16
+ official: string;
17
+ nativeName: {
18
+ [key: string]: I_CountryNativeName;
19
+ };
20
+ }
21
+ interface I_CountryCurrency {
22
+ name: string;
23
+ symbol: string;
24
+ }
25
+ interface I_CountryCurrencies {
26
+ [key: string]: I_CountryCurrency;
27
+ }
28
+ interface I_CountryId {
29
+ root: string;
30
+ suffixes: string[];
31
+ }
32
+ export interface I_Country {
33
+ capital: string[];
34
+ cca2: string;
35
+ currencies: I_CountryCurrencies;
36
+ flags: I_CountryFlags;
37
+ idd: I_CountryId;
38
+ latlng: number[];
39
+ name: I_CountryName;
40
+ postalCode: I_CountryPostalCode;
41
+ }
42
+ export declare const countryList: I_Country[];
43
+ /**
44
+ * Map of country codes to country objects.
45
+ * Generated once to avoid performance issues.
46
+ */
47
+ export declare const countryListMap: Map<string, I_Country>;
48
+ export declare const getCountryName: (countryCode: string) => string;
49
+ export {};
@@ -0,0 +1,5 @@
1
+ import FlyCountryCitySelect from './FlyCountryCitySelect.vue';
2
+ import FlyCountrySelect from './FlyCountrySelect.vue';
3
+ import FlyCountryStatesSelect from './FlyCountryStatesSelect.vue';
4
+ export default FlyCountrySelect;
5
+ export { FlyCountrySelect, FlyCountryCitySelect, FlyCountryStatesSelect };
@@ -0,0 +1,8 @@
1
+ export * from './form-item-renderer';
2
+ export * from './input-renderer';
3
+ export * from './country-input';
4
+ export * from './phone-number';
5
+ export * from './otp-input';
6
+ export * from './regional-tenant-form-renderer';
7
+ export type { T_InputRendererBase } from './input-renderer.types';
8
+ export type { T_FormSchemaLookupData, T_InputSchema, T_InputSchemaText, T_InputSchemaNumber, T_InputSchemaBoolean, T_InputSchemaSelect, T_InputSchemaValueUnit, T_InputSchemaDateTime } from './form-schema.types';
@@ -0,0 +1,15 @@
1
+ import './FlyOTPInput.scss';
2
+ type __VLS_Props = {
3
+ modelValue: string;
4
+ length?: number;
5
+ disabled?: boolean;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
8
+ "update:modelValue": (value: string) => any;
9
+ complete: (value: string) => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
12
+ onComplete?: ((value: string) => any) | undefined;
13
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import FlyOTPInput from './FlyOTPInput.vue';
2
+ export default FlyOTPInput;
3
+ export { FlyOTPInput };
@@ -0,0 +1,17 @@
1
+ import './FlyPhoneNumberInput.scss';
2
+ type __VLS_Props = {
3
+ modelValue?: string;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
6
+ focus: () => any;
7
+ "update:modelValue": (value: string | undefined) => any;
8
+ change: (value: string | undefined) => any;
9
+ blur: () => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
11
+ onFocus?: (() => any) | undefined;
12
+ "onUpdate:modelValue"?: ((value: string | undefined) => any) | undefined;
13
+ onChange?: ((value: string | undefined) => any) | undefined;
14
+ onBlur?: (() => any) | undefined;
15
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import FlyPhoneNumberInput from './FlyPhoneNumberInput.vue';
2
+ export default FlyPhoneNumberInput;
3
+ export { FlyPhoneNumberInput };
@@ -1,4 +1,10 @@
1
1
  import type { T_FormSchemaLookupData, T_InputSchema } from '../form-schema.types';
2
+ import type FlyRegionalTenantFormRenderer from './FlyRegionalTenantFormRenderer.vue';
3
+ export type T_FlyRegionalTenantFormRendererInstance = InstanceType<typeof FlyRegionalTenantFormRenderer> | null;
4
+ export type T_TenantRegionalFormMainSection = {
5
+ key: string;
6
+ title: string;
7
+ };
2
8
  export type T_TenantRegionalFormSection = {
3
9
  key: string;
4
10
  fields: T_InputSchema[];
@@ -8,6 +14,7 @@ export type T_TenantRegionalFormSection = {
8
14
  modelValue?: Record<string, unknown>;
9
15
  };
10
16
  export type T_TenantRegionalFormProps = {
11
- mainFormTitle: string;
17
+ mainSections: T_TenantRegionalFormMainSection[];
12
18
  sections?: T_TenantRegionalFormSection[];
19
+ activeSection?: string | number;
13
20
  };
@@ -1,15 +1,19 @@
1
1
  import '../../../../styles/element/overrides/collapse.scss';
2
2
  import type { T_TenantRegionalFormProps } from './FlyRegionalTenantFormRenderer.types';
3
3
  declare function validateForms(): Promise<true | undefined>;
4
- declare var __VLS_19: {}, __VLS_38: {};
4
+ declare var __VLS_20: string, __VLS_21: {}, __VLS_40: {};
5
5
  type __VLS_Slots = {} & {
6
- default?: (props: typeof __VLS_19) => any;
6
+ [K in NonNullable<typeof __VLS_20>]?: (props: typeof __VLS_21) => any;
7
7
  } & {
8
- default?: (props: typeof __VLS_38) => any;
8
+ default?: (props: typeof __VLS_40) => any;
9
9
  };
10
10
  declare const __VLS_base: import("vue").DefineComponent<T_TenantRegionalFormProps, {
11
11
  validateForms: typeof validateForms;
12
- }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<T_TenantRegionalFormProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
+ "update:activeSection": (value: string | number) => any;
14
+ }, string, import("vue").PublicProps, Readonly<T_TenantRegionalFormProps> & Readonly<{
15
+ "onUpdate:activeSection"?: ((value: string | number) => any) | undefined;
16
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
17
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
18
  declare const _default: typeof __VLS_export;
15
19
  export default _default;
@@ -0,0 +1,4 @@
1
+ import FlyRegionalTenantFormRenderer from './FlyRegionalTenantFormRenderer.vue';
2
+ export default FlyRegionalTenantFormRenderer;
3
+ export { FlyRegionalTenantFormRenderer };
4
+ export type { T_TenantRegionalFormMainSection, T_TenantRegionalFormSection, T_TenantRegionalFormProps, T_FlyRegionalTenantFormRendererInstance } from './FlyRegionalTenantFormRenderer.types';
@@ -9,4 +9,9 @@ export declare const requiredFieldValueUnit: (label: string | undefined, trigger
9
9
  valueType?: "text" | "number";
10
10
  }) => FormItemRule;
11
11
  export declare const requiredFieldArray: (label?: string, trigger?: InputTriggers, useRequiredMessage?: boolean) => FormItemRule;
12
+ export declare const requiredFieldEmail: (label?: string, trigger?: InputTriggers, useRequiredMessage?: boolean) => FormItemRule;
13
+ export declare const fieldEmail: (languageKey?: string, trigger?: InputTriggers) => FormItemRule;
14
+ export declare const requiredFieldEmailArray: (label?: string, trigger?: InputTriggers, useRequiredMessage?: boolean, required?: boolean) => FormItemRule;
15
+ export declare const requiredFieldE164PhoneNumber: (label?: string, trigger?: InputTriggers, useRequiredMessage?: boolean) => FormItemRule;
16
+ export declare const fieldE164PhoneNumber: (trigger?: InputTriggers) => FormItemRule;
12
17
  export {};
@@ -1,2 +1,2 @@
1
- export { initLocaleInjector, UseLocaleInjector } from './UseLocaleInjector';
2
- export type { T_LocaleInjector } from './UseLocaleInjector';
1
+ export { initLocaleInjector, useLocaleInjector } from './useLocaleInjector';
2
+ export type { T_LocaleInjector, T_I18nAdapter as I18nAdapter } from './useLocaleInjector';
@@ -0,0 +1,13 @@
1
+ import type { ComputedRef, MaybeRef } from 'vue';
2
+ import type { Locale } from '@flyanra/js-utils/locales';
3
+ import type { ComposerTranslation } from 'vue-i18n';
4
+ export type T_LocaleInjector = {
5
+ t: ComposerTranslation;
6
+ locale: ComputedRef<Locale>;
7
+ };
8
+ export type T_I18nAdapter = {
9
+ t: ComposerTranslation;
10
+ locale: MaybeRef<Locale>;
11
+ };
12
+ export declare function initLocaleInjector(i18n: T_I18nAdapter): void;
13
+ export declare function useLocaleInjector(): T_LocaleInjector;
@@ -0,0 +1,3 @@
1
+ declare function getAdministrativeAreaLabel(countryCode?: string): string;
2
+ declare function getNationalIdLabel(countryCode?: string): string;
3
+ export { getAdministrativeAreaLabel, getNationalIdLabel };
@@ -1,2 +1,3 @@
1
1
  export { checkRange } from './pure-functions';
2
2
  export { checkInputRange, isRequiredError } from './validators';
3
+ export * from './country-utils';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flyanra/vue-core",
3
- "version": "1.3.9",
3
+ "version": "1.5.0",
4
4
  "private": false,
5
5
  "description": "Source-distributed Vue component library for Vite and Nuxt consumers.",
6
6
  "sideEffects": false,
@@ -96,6 +96,10 @@
96
96
  "eslint --fix"
97
97
  ]
98
98
  },
99
+ "dependencies": {
100
+ "country-state-city": "^3.2.1",
101
+ "libphonenumber-js": "^1.13.10"
102
+ },
99
103
  "devDependencies": {
100
104
  "@changesets/cli": "^2.30.0",
101
105
  "@eslint/js": "^10.0.1",
@@ -11,13 +11,13 @@
11
11
  </template>
12
12
 
13
13
  <script lang="ts" setup>
14
- import { UseLocaleInjector } from '../../../composables/useLocaleInjector/UseLocaleInjector'
14
+ import { useLocaleInjector } from '../../../composables/useLocaleInjector/useLocaleInjector'
15
15
 
16
16
  defineProps<{
17
17
  title: string
18
18
  }>()
19
19
 
20
- const { t } = UseLocaleInjector()
20
+ const { t } = useLocaleInjector()
21
21
  </script>
22
22
 
23
23
  <style lang="scss" scoped>
@@ -1,6 +1,6 @@
1
1
  import type { FormInstance } from 'element-plus'
2
2
 
3
- import { UseLocaleInjector } from '../../composables/useLocaleInjector/UseLocaleInjector'
3
+ import { useLocaleInjector } from '../../composables/useLocaleInjector/useLocaleInjector'
4
4
 
5
5
  export type ValidateFieldsError = { [K: string]: { message?: string }[] }
6
6
 
@@ -8,7 +8,7 @@ export type ValidateFieldsError = { [K: string]: { message?: string }[] }
8
8
  * @returns Translated error message based on active locale
9
9
  */
10
10
  export function formFieldErrorMessageFormatter(errors: ValidateFieldsError) {
11
- const { t, locale } = UseLocaleInjector()
11
+ const { t, locale } = useLocaleInjector()
12
12
  const keys = Object.keys(errors)
13
13
 
14
14
  if (keys.length) {
@@ -31,7 +31,7 @@ export function formFieldErrorMessageFormatter(errors: ValidateFieldsError) {
31
31
  const otherErrorsLength = otherErrors.length
32
32
 
33
33
  if (requiredFieldsLength >= 1) {
34
- const joinedList = new Intl.ListFormat(locale, {
34
+ const joinedList = new Intl.ListFormat(locale.value, {
35
35
  style: 'long',
36
36
  type: 'conjunction'
37
37
  }).format(requiredFieldNames.filter((item): item is string => Boolean(item)))
@@ -1,6 +1,3 @@
1
- export * from './input-renderers/form-item-renderer'
2
- export * from './input-renderers/input-renderer'
3
-
4
- export type { T_InputRendererBase } from './input-renderers/input-renderer.types'
1
+ export * from './input-renderers'
5
2
  export * from './input-validators'
6
3
  export * from './form.utils'
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <el-select
3
+ v-if="options.length"
4
+ v-model="inputProxy"
5
+ style="width: 100%"
6
+ filterable
7
+ clearable
8
+ :disabled="!country || !state"
9
+ @change="(value: string) => emit('change', value)"
10
+ @blur="emit('blur')"
11
+ @focus="emit('focus')"
12
+ >
13
+ <el-option v-for="city in options" :key="city.name" :value="city.name" :label="city.name" />
14
+ </el-select>
15
+
16
+ <el-input
17
+ v-else
18
+ v-model="inputProxy"
19
+ style="width: 100%"
20
+ show-word-limit
21
+ :disabled="!country || !state"
22
+ @change="(value: string) => emit('change', value)"
23
+ @blur="emit('blur')"
24
+ @focus="emit('focus')"
25
+ />
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ import { computed, watch } from 'vue'
30
+
31
+ import { ElOption, ElSelect } from 'element-plus'
32
+
33
+ import { City } from 'country-state-city'
34
+
35
+ import '../select/FlySelect.scss'
36
+
37
+ const emit = defineEmits<{
38
+ (e: 'update:modelValue', value: string | undefined): void
39
+ (e: 'change', value: string | undefined): void
40
+ (e: 'blur'): void
41
+ (e: 'focus'): void
42
+ }>()
43
+
44
+ const props = defineProps<{
45
+ modelValue?: string
46
+ country?: string
47
+ state?: string
48
+ }>()
49
+
50
+ const options = computed(() => {
51
+ if (!props.country || !props.state) return []
52
+
53
+ return City.getCitiesOfState(props.country.toUpperCase(), props.state.toUpperCase())
54
+ })
55
+
56
+ const inputProxy = computed({
57
+ get: () => props.modelValue,
58
+ set: (value: string | undefined) => {
59
+ emit('update:modelValue', value)
60
+ }
61
+ })
62
+
63
+ watch([() => props.country, () => props.state], () => {
64
+ if (!props.modelValue) return
65
+
66
+ const cityStillExists = options.value.some((city) => city.name === props.modelValue)
67
+
68
+ if (!cityStillExists) {
69
+ emit('update:modelValue', undefined)
70
+ emit('change', undefined)
71
+ }
72
+ })
73
+ </script>
@@ -0,0 +1,4 @@
1
+ export type T_CountryValueLabel = {
2
+ label: string
3
+ value: string
4
+ }
@@ -0,0 +1,76 @@
1
+ <template>
2
+ <el-select
3
+ v-model="inputProxy"
4
+ class="fly-country-select"
5
+ filterable
6
+ clearable
7
+ @change="(val) => emit('change', val)"
8
+ @blur="() => emit('blur')"
9
+ @focus="() => emit('focus')"
10
+ >
11
+ <template #label="valueObject: T_CountryValueLabel">
12
+ <slot name="label" :scope="valueObject">
13
+ <span>{{ valueObject.label }}</span>
14
+ </slot>
15
+ </template>
16
+ <el-option
17
+ v-for="country in countryList"
18
+ :key="country.cca2"
19
+ :label="country.name.common"
20
+ :value="country.cca2"
21
+ class="flex items-center justify-between space-x-2"
22
+ >
23
+ <div class="fly-country-select-option">
24
+ <span>{{ country.name.common }}</span>
25
+ <img :src="country.flags.svg" loading="lazy" />
26
+ </div>
27
+ <!-- <span class="text-xs text-gray-500">
28
+ {{ country.cca2 }}
29
+ </span> -->
30
+ </el-option>
31
+ </el-select>
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ import { computed } from 'vue'
36
+
37
+ import { ElOption, ElSelect } from 'element-plus'
38
+
39
+ import '../select/FlySelect.scss'
40
+
41
+ import type { T_CountryValueLabel } from './FlyCountrySelect.types'
42
+ import { countryList } from './countries'
43
+
44
+ const emit = defineEmits<{
45
+ (e: 'update:modelValue', v?: string | undefined): void
46
+ (e: 'change', v: string | undefined): void
47
+ (e: 'blur'): void
48
+ (e: 'focus'): void
49
+ }>()
50
+
51
+ const props = defineProps<{
52
+ modelValue?: string | undefined
53
+ }>()
54
+
55
+ const inputProxy = computed({
56
+ get: (): string | undefined => {
57
+ return props.modelValue
58
+ },
59
+ set: (v) => {
60
+ emit('update:modelValue', v)
61
+ }
62
+ })
63
+ </script>
64
+
65
+ <style scoped>
66
+ .fly-country-select-option {
67
+ display: flex;
68
+ flex-grow: 1;
69
+ justify-content: space-between;
70
+ align-items: center;
71
+
72
+ img {
73
+ width: 20px;
74
+ }
75
+ }
76
+ </style>
@@ -0,0 +1,81 @@
1
+ <template>
2
+ <el-select
3
+ v-if="options.length"
4
+ v-model="inputProxy"
5
+ style="width: 100%"
6
+ filterable
7
+ clearable
8
+ :disabled="!country"
9
+ @change="(value) => emit('change', value)"
10
+ @blur="emit('blur')"
11
+ @focus="emit('focus')"
12
+ >
13
+ <el-option
14
+ v-for="state in options"
15
+ :key="state.isoCode"
16
+ :value="state.isoCode"
17
+ :label="state.name"
18
+ />
19
+ </el-select>
20
+
21
+ <el-input
22
+ v-else
23
+ v-model="inputProxy"
24
+ style="width: 100%"
25
+ show-word-limit
26
+ :disabled="!country"
27
+ @change="(value: string) => emit('change', value)"
28
+ @blur="emit('blur')"
29
+ @focus="emit('focus')"
30
+ />
31
+ </template>
32
+
33
+ <script setup lang="ts">
34
+ import { computed, watch } from 'vue'
35
+
36
+ import { ElInput, ElOption, ElSelect } from 'element-plus'
37
+
38
+ import { State } from 'country-state-city'
39
+
40
+ import '../select/FlySelect.scss'
41
+ import '../text/FlyText.scss'
42
+
43
+ const emit = defineEmits<{
44
+ (e: 'update:modelValue', value: string | undefined): void
45
+ (e: 'change', value: string | undefined): void
46
+ (e: 'blur'): void
47
+ (e: 'focus'): void
48
+ }>()
49
+
50
+ const props = defineProps<{
51
+ modelValue?: string
52
+ country?: string
53
+ }>()
54
+
55
+ const options = computed(() => {
56
+ if (!props.country) return []
57
+
58
+ return State.getStatesOfCountry(props.country.toUpperCase())
59
+ })
60
+
61
+ const inputProxy = computed({
62
+ get: () => props.modelValue,
63
+ set: (value: string | undefined) => {
64
+ emit('update:modelValue', value)
65
+ }
66
+ })
67
+
68
+ watch(
69
+ () => props.country,
70
+ () => {
71
+ if (!props.modelValue) return
72
+
73
+ const stateStillExists = options.value.some((state) => state.isoCode === props.modelValue)
74
+
75
+ if (!stateStillExists) {
76
+ emit('update:modelValue', undefined)
77
+ emit('change', undefined)
78
+ }
79
+ }
80
+ )
81
+ </script>