adata-ui 2.1.40-beta.18 → 2.1.40-beta.19

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 (211) hide show
  1. package/.playground/app.vue +102 -0
  2. package/assets/styles/index.scss +67 -5
  3. package/components/elements/a-select-row/ASelectRowV2.vue +214 -0
  4. package/components/elements/a-select-row/index.vue +3 -5
  5. package/components/elements/accordion/AAccordion.vue +5 -3
  6. package/components/elements/accordion/AAccordionGroup/AAccordionGroup.vue +3 -3
  7. package/components/elements/alert/AAlert.vue +34 -47
  8. package/components/elements/bg-block/ABgBlock.vue +1 -1
  9. package/components/elements/button/AButton.vue +3 -3
  10. package/components/elements/button/AButtonV2.vue +133 -0
  11. package/components/elements/button-login/index.vue +6 -10
  12. package/components/elements/chip-wrapper/AChipWrapper.vue +1 -1
  13. package/components/elements/chips/AChips.vue +2 -2
  14. package/components/elements/companies/AOurClients.vue +3 -1
  15. package/components/elements/curve-block-v2/ACurveBlockV2.vue +85 -0
  16. package/components/elements/digit-badge/ADigitBadge.vue +24 -22
  17. package/components/elements/feature-description/AFeatureDescription.vue +1 -1
  18. package/components/elements/leave-note/ALeaveNote.vue +39 -18
  19. package/components/elements/pagination/APagination.vue +7 -7
  20. package/components/elements/segmented/ASegmentedV2.vue +151 -0
  21. package/components/elements/select/ASelect.vue +4 -4
  22. package/components/elements/select/ASelectMobile.vue +2 -2
  23. package/components/elements/select/ASelectV2.vue +588 -0
  24. package/components/elements/select/ui/select-button.vue +1 -1
  25. package/components/elements/show-more/AShowMoreV2.vue +26 -0
  26. package/components/elements/slider/ASlider.vue +174 -0
  27. package/components/elements/slider/ASliderItem.vue +31 -0
  28. package/components/elements/slider/types.ts +21 -0
  29. package/components/elements/star-rating/AStarRating.vue +12 -4
  30. package/components/elements/status-badge/AStatusBadge.vue +91 -44
  31. package/components/elements/step-slider/AStepSliderColCard.vue +232 -0
  32. package/components/elements/step-slider/AStepSliderColNumber.vue +178 -0
  33. package/components/elements/table/ATable.vue +1 -1
  34. package/components/elements/table/table.config.ts +2 -2
  35. package/components/elements/tree-select/ATreeSelect.vue +97 -113
  36. package/components/elements/tree-select/TreeService.ts +142 -207
  37. package/components/elements/tree-select/components/ATreeSelectNode.vue +104 -0
  38. package/components/elements/tree-select/types.ts +40 -11
  39. package/components/elements/tree-select/utils.ts +30 -0
  40. package/components/elements/tree-select-modal/ATreeSelectModal.vue +217 -0
  41. package/components/features/color-mode/AColorMode.client.vue +74 -32
  42. package/components/features/dropdown/ADropdownV2.vue +140 -0
  43. package/components/features/lang-switcher/lang-switcher.vue +125 -40
  44. package/components/features/payment/banner/BasicPlusLimitBanner.vue +3 -3
  45. package/components/features/payment/banner/PaymentBanner.vue +3 -3
  46. package/components/features/payment/banner/UpSellBanner.vue +3 -3
  47. package/components/features/payment/process/PaymentKaspiQrSidePanel.vue +45 -27
  48. package/components/features/payment/process/PaymentKaspiRedirectSidePanel.vue +34 -23
  49. package/components/features/payment/process/PaymentMethodSidePanel.vue +66 -49
  50. package/components/features/payment/process/PaymentProcess.vue +6 -6
  51. package/components/features/payment/process/PaymentTopUpSidePanel.vue +49 -63
  52. package/components/features/pk-mobile-services/APkMobileServices.vue +6 -28
  53. package/components/features//321/201hange-version/AChangeVersion.vue +2 -2
  54. package/components/forms/checkbox/ACheckbox.vue +1 -1
  55. package/components/forms/checkbox/ACheckboxV2.vue +229 -0
  56. package/components/forms/feedback-form/FeedbackForm.vue +8 -8
  57. package/components/forms/feedback-form/FeedbackFormV2.vue +182 -0
  58. package/components/forms/input/AInputV2.vue +542 -0
  59. package/components/forms/input/date/AInputDate.vue +2 -2
  60. package/components/forms/input/password/AInputPassword.vue +8 -2
  61. package/components/forms/input/standard/AInputStandard.vue +3 -3
  62. package/components/forms/input/textarea/ATextarea.vue +2 -2
  63. package/components/forms/input/textarea/ATextareaV2.vue +248 -0
  64. package/components/forms/toggle/AToggle.vue +2 -3
  65. package/components/forms/toggle/AToggleV2.vue +71 -0
  66. package/components/modals/AnotherDeviceModal.vue +22 -18
  67. package/components/modals/ApplicationAcceptedModal.vue +12 -15
  68. package/components/modals/ConnectingTariffModal.vue +13 -20
  69. package/components/modals/ContactsMobileModel.vue +1 -1
  70. package/components/modals/ContentNavigationModal.vue +77 -333
  71. package/components/modals/Insufficient-funds-modal.vue +18 -33
  72. package/components/modals/LimitReachedModal.vue +17 -14
  73. package/components/modals/NoAccessModal.vue +9 -11
  74. package/components/modals/PaymentMethodModal.vue +1 -1
  75. package/components/modals/ReportBugConfirmModal.vue +12 -10
  76. package/components/modals/ReportBugModal.vue +46 -38
  77. package/components/modals/Resend.vue +9 -10
  78. package/components/modals/SubmitApplicationModal.vue +27 -24
  79. package/components/modals/id/IdBanner.vue +3 -3
  80. package/components/modals/id/IdConfirmAccountOtpModal.vue +4 -9
  81. package/components/modals/id/IdLoginModal.vue +3 -8
  82. package/components/modals/id/IdModals.vue +23 -10
  83. package/components/modals/id/IdRecoveryModal.vue +1 -1
  84. package/components/modals/id/IdTwoFactorModal.vue +3 -8
  85. package/components/navigation/bottom-navigation/ABottomNavigation.vue +1 -1
  86. package/components/navigation/breadcrumbs/ABreadcrumbs.vue +106 -45
  87. package/components/navigation/breadcrumbs/types.ts +3 -0
  88. package/components/navigation/footer/AFooter.vue +39 -40
  89. package/components/navigation/footer/ui/a-footer-accordion.vue +9 -9
  90. package/components/navigation/header/AHeader.vue +68 -51
  91. package/components/navigation/header/AlmatyContacts.vue +78 -78
  92. package/components/navigation/header/CardGallery.vue +9 -7
  93. package/components/navigation/header/ContactMenu.vue +26 -92
  94. package/components/navigation/header/HeaderLink.vue +181 -213
  95. package/components/navigation/header/HeaderUsage.vue +139 -0
  96. package/components/navigation/header/ListItem.vue +2 -2
  97. package/components/navigation/header/NavCard.vue +1 -1
  98. package/components/navigation/header/NavList.vue +33 -92
  99. package/components/navigation/header/NotificationsMenu.vue +2 -3
  100. package/components/navigation/header/ProductMenu.vue +81 -127
  101. package/components/navigation/header/ProfileMenu.vue +122 -151
  102. package/components/navigation/header/SystemNotification.vue +108 -0
  103. package/components/navigation/mobile-navigation/AMobileNavigation.vue +23 -15
  104. package/components/navigation/pill-tabs/APillTabs.vue +2 -2
  105. package/components/navigation/pill-tabs/APillTabsV2.vue +226 -0
  106. package/components/overlays/drawer/ADrawerV2.vue +335 -0
  107. package/components/overlays/modal/AModal.vue +4 -4
  108. package/components/overlays/modal/AModalV2.vue +397 -0
  109. package/components/overlays/side-panel/ASidePanel.vue +10 -7
  110. package/components/overlays/sideover/ASlideover.vue +6 -6
  111. package/components/overlays/tooltip/ATooltip.vue +1 -1
  112. package/components/overlays/tooltip/ATooltipV2.vue +223 -0
  113. package/components/overlays/tooltip/types.ts +26 -0
  114. package/components/overlays/tooltip/useTooltipTrigger.ts +101 -0
  115. package/components/transitions/ATransitionHeight.vue +1 -1
  116. package/composables/useAccessTokenCookie.ts +25 -0
  117. package/composables/useActiveNavigation.ts +84 -0
  118. package/composables/useChipOverflow.ts +92 -0
  119. package/composables/useHeaderNavigationLinks.ts +140 -98
  120. package/icons/archive.vue +16 -0
  121. package/icons/arrow/arrow-left-right.vue +8 -0
  122. package/icons/arrow/arrow-right.vue +14 -0
  123. package/icons/arrow/arrows-in.vue +11 -0
  124. package/icons/arrow/arrows-out.vue +11 -0
  125. package/icons/arrow/arrows-resize-in.vue +38 -0
  126. package/icons/arrow/arrows-resize-out.vue +17 -0
  127. package/icons/bill.vue +3 -0
  128. package/icons/bot.vue +52 -0
  129. package/icons/briefcase.vue +14 -0
  130. package/icons/building.vue +9 -0
  131. package/icons/car-side.vue +16 -0
  132. package/icons/cart.vue +15 -0
  133. package/icons/chart-no-axes-column.vue +3 -0
  134. package/icons/clock-time.vue +24 -0
  135. package/icons/cloud/cloud-upload.vue +3 -0
  136. package/icons/code.vue +9 -0
  137. package/icons/compare-outlined.vue +8 -0
  138. package/icons/dots-horizontal.vue +31 -0
  139. package/icons/download-line.vue +13 -0
  140. package/icons/download-rounded.vue +15 -0
  141. package/icons/egov.vue +41 -0
  142. package/icons/elicense.vue +38 -0
  143. package/icons/favourite-bookmark-outline.vue +17 -0
  144. package/icons/file/file-check-corner.vue +3 -0
  145. package/icons/file/file-spreadsheet.vue +3 -0
  146. package/icons/file-pen.vue +31 -0
  147. package/icons/file-stack.vue +31 -0
  148. package/icons/file-types/excel.vue +131 -0
  149. package/icons/file-types/html.vue +13 -0
  150. package/icons/file-types/jpeg.vue +16 -0
  151. package/icons/file-types/pdf.vue +11 -0
  152. package/icons/file-types/png.vue +11 -0
  153. package/icons/file-types/rar.vue +11 -0
  154. package/icons/file-types/word.vue +50 -0
  155. package/icons/file-types/zip.vue +11 -0
  156. package/icons/gauge.vue +17 -0
  157. package/icons/git-compare.vue +38 -0
  158. package/icons/git-fork.vue +3 -0
  159. package/icons/graduation-cap.vue +31 -0
  160. package/icons/graph-loading.vue +34 -0
  161. package/icons/headset.vue +6 -0
  162. package/icons/help-question-circle.vue +26 -0
  163. package/icons/in-row-type.vue +46 -0
  164. package/icons/in-table-type.vue +29 -0
  165. package/icons/landmark.vue +3 -0
  166. package/icons/layers.vue +3 -0
  167. package/icons/letter/letter-a.vue +6 -0
  168. package/icons/letter/letter-b.vue +6 -0
  169. package/icons/letter/letter-c.vue +6 -0
  170. package/icons/letter/letter-d.vue +6 -0
  171. package/icons/letter/letter-e.vue +6 -0
  172. package/icons/link-url.vue +3 -0
  173. package/icons/list-tree.vue +3 -0
  174. package/icons/mail-question-mark.vue +8 -0
  175. package/icons/message/message-square.vue +3 -0
  176. package/icons/message-dotted.vue +30 -0
  177. package/icons/network.vue +3 -0
  178. package/icons/newspaper.vue +3 -0
  179. package/icons/notification-error.vue +17 -0
  180. package/icons/person.vue +22 -0
  181. package/icons/phone-call.vue +6 -0
  182. package/icons/phone-reversed.vue +3 -0
  183. package/icons/route.vue +7 -0
  184. package/icons/scan-search.vue +3 -0
  185. package/icons/settings.vue +26 -0
  186. package/icons/shield-alert.vue +31 -0
  187. package/icons/shield-verified.vue +14 -0
  188. package/icons/socials/facebook-color.vue +16 -0
  189. package/icons/socials/globe-color.vue +16 -0
  190. package/icons/socials/instagram-color.vue +46 -0
  191. package/icons/socials/linkedin-color.vue +14 -0
  192. package/icons/socials/telegram-color.vue +16 -0
  193. package/icons/socials/tiktok-color.vue +14 -0
  194. package/icons/socials/vk-color.vue +16 -0
  195. package/icons/socials/youtube-color.vue +16 -0
  196. package/icons/sparkles.vue +3 -0
  197. package/icons/sun.vue +13 -3
  198. package/icons/users-round.vue +3 -0
  199. package/icons/view-eye-open.vue +13 -0
  200. package/icons/workflow.vue +3 -0
  201. package/icons/zap.vue +3 -0
  202. package/lang/en.ts +49 -5
  203. package/lang/kk.ts +50 -6
  204. package/lang/ru.ts +51 -7
  205. package/package.json +1 -1
  206. package/plugins/toast.client.ts +38 -55
  207. package/shared/constans/pages.ts +8 -2
  208. package/tailwind.config.ts +147 -116
  209. package/utils/twMerge.ts +34 -0
  210. package/components/elements/tree-select/components/tree-select-nodes.vue +0 -91
  211. package/components/navigation/header/TopHeader.vue +0 -196
@@ -0,0 +1,178 @@
1
+ <script setup lang="ts">
2
+ interface Step {
3
+ title: string
4
+ description: string
5
+ }
6
+
7
+ const props = withDefaults(defineProps<{
8
+ steps: Step[]
9
+ interval?: number
10
+ autoplay?: boolean
11
+ pauseOnHover?: boolean
12
+ modelValue?: number
13
+ colsClass?: string
14
+ }>(), {
15
+ interval: 5000,
16
+ autoplay: true,
17
+ pauseOnHover: true,
18
+ modelValue: undefined,
19
+ colsClass: 'lg:grid-cols-2',
20
+ })
21
+
22
+ const emit = defineEmits<{
23
+ (e: 'update:modelValue', value: number): void
24
+ (e: 'change', value: number): void
25
+ }>()
26
+
27
+ const TICK = 50
28
+
29
+ const internal = ref(props.modelValue ?? 0)
30
+
31
+ const active = computed<number>({
32
+ get: () => props.modelValue ?? internal.value,
33
+ set: (value) => {
34
+ internal.value = value
35
+ emit('update:modelValue', value)
36
+ emit('change', value)
37
+ },
38
+ })
39
+
40
+ const elapsed = ref(0)
41
+ let ticker: ReturnType<typeof setInterval> | null = null
42
+ let lastTs = 0
43
+
44
+ const progress = computed(() => {
45
+ if (!props.autoplay || props.steps.length <= 1)
46
+ return 1
47
+ return Math.min(1, elapsed.value / props.interval)
48
+ })
49
+
50
+ const fillWidth = computed(() => `${progress.value * 100}%`)
51
+
52
+ function stopTicker() {
53
+ if (ticker) {
54
+ clearInterval(ticker)
55
+ ticker = null
56
+ }
57
+ lastTs = 0
58
+ }
59
+
60
+ function startTicker() {
61
+ stopTicker()
62
+ if (!props.autoplay || props.steps.length <= 1)
63
+ return
64
+ ticker = setInterval(() => {
65
+ const now = Date.now()
66
+ const dt = lastTs ? now - lastTs : TICK
67
+ lastTs = now
68
+ elapsed.value += dt
69
+ if (elapsed.value >= props.interval) {
70
+ elapsed.value = 0
71
+ active.value = (active.value + 1) % props.steps.length
72
+ }
73
+ }, TICK)
74
+ }
75
+
76
+ function goTo(index: number) {
77
+ active.value = index
78
+ elapsed.value = 0
79
+ startTicker()
80
+ }
81
+
82
+ function onMouseEnter() {
83
+ if (props.pauseOnHover)
84
+ stopTicker()
85
+ }
86
+
87
+ function onMouseLeave() {
88
+ if (props.pauseOnHover)
89
+ startTicker()
90
+ }
91
+
92
+ onMounted(startTicker)
93
+ onBeforeUnmount(stopTicker)
94
+ watch(() => [props.interval, props.autoplay, props.steps.length], () => {
95
+ elapsed.value = 0
96
+ startTicker()
97
+ })
98
+ </script>
99
+
100
+ <template>
101
+ <div
102
+ class="grid grid-cols-1 items-center gap-4 lg:gap-16"
103
+ :class="colsClass"
104
+ >
105
+ <ol class="flex flex-col gap-4">
106
+ <li
107
+ v-for="(step, i) in steps"
108
+ :key="i"
109
+ class="group relative flex cursor-pointer items-start gap-4 px-4 py-3"
110
+ @click="goTo(i)"
111
+ >
112
+ <span
113
+ v-if="i === active"
114
+ class="ss-card-glow absolute inset-0 z-[1] rounded-2xl bg-white"
115
+ />
116
+ <span
117
+ v-if="i < steps.length - 1"
118
+ class="absolute left-[34px] top-[46px] z-0 h-[calc(100%_-_18px)] w-0.5 -translate-x-1/2 rounded transition-colors"
119
+ :class="i < active ? 'bg-blue-600' : 'bg-gray-200'"
120
+ />
121
+ <span class="relative z-10 flex w-9 shrink-0 justify-center">
122
+ <span
123
+ class="text-body-md flex items-center justify-center rounded-full font-bold transition-all duration-300"
124
+ :class="i === active
125
+ ? 'ss-num-glow size-9 bg-blue-600 text-white'
126
+ : i < active
127
+ ? 'size-[34px] bg-blue-50 text-blue-600 group-hover:bg-blue-100'
128
+ : 'size-[34px] bg-gray-100 text-gray-400 group-hover:bg-gray-200'"
129
+ >
130
+ {{ i + 1 }}
131
+ </span>
132
+ </span>
133
+ <div class="relative z-10">
134
+ <p
135
+ class="text-body-lg-strong transition-colors"
136
+ :class="i === active
137
+ ? 'text-gray-900'
138
+ : i < active
139
+ ? 'text-[#5b6472]'
140
+ : 'text-gray-400'"
141
+ >
142
+ {{ step.title }}
143
+ </p>
144
+ <p class="text-body-md text-[#9ca3af]">
145
+ {{ step.description }}
146
+ </p>
147
+ </div>
148
+ </li>
149
+ </ol>
150
+
151
+ <div
152
+ @mouseenter="onMouseEnter"
153
+ @mouseleave="onMouseLeave"
154
+ >
155
+ <div class="flex justify-center">
156
+ <slot
157
+ name="panel"
158
+ :active="active"
159
+ :step="steps[active]"
160
+ :progress="progress"
161
+ :count="steps.length"
162
+ :fill-width="fillWidth"
163
+ :go-to="goTo"
164
+ />
165
+ </div>
166
+ </div>
167
+ </div>
168
+ </template>
169
+
170
+ <style scoped>
171
+ .ss-num-glow {
172
+ box-shadow: 0 4px 12px rgb(6 141 255 / 45%);
173
+ }
174
+
175
+ .ss-card-glow {
176
+ box-shadow: 0 22px 60px -18px rgb(6 141 255 / 32%);
177
+ }
178
+ </style>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { twMerge } from '#adata-ui/utils/twMerge'
2
3
  import {ui} from './table.config'
3
- import { twMerge } from 'tailwind-merge'
4
4
  type Column = {
5
5
  label: string
6
6
  key: string | number
@@ -14,7 +14,7 @@ export const ui = {
14
14
  padding: 'px-4 py-3.5',
15
15
  color: 'text-deepblue-900 dark:text-gray-200',
16
16
  font: 'font-semibold',
17
- size: 'text-xs',
17
+ size: 'text-body-sm',
18
18
  },
19
19
  td: {
20
20
  base: '',
@@ -24,7 +24,7 @@ export const ui = {
24
24
  },
25
25
  color: 'text-deepblue-900 dark:text-gray-200',
26
26
  font: '',
27
- size: 'text-sm',
27
+ size: 'text-body-md',
28
28
  },
29
29
  progress: {
30
30
  wrapper: 'absolute h-[2px] bg-deepblue-700 inset-x-0 animate-pulse',
@@ -1,30 +1,7 @@
1
- <template>
2
- <div>
3
- <ul>
4
- <template
5
- v-for="node in nestedTree"
6
- :key="node.id"
7
- >
8
- <TreeSelectNodes
9
- v-if="!node?.hidden"
10
- :node="node"
11
- :toggle-expand="toggleExpand"
12
- :toggle-checkbox="toggleCheckbox"
13
- :type="type"
14
- :disabled="isDisabled(node.id)"
15
- />
16
- </template>
17
- </ul>
18
- </div>
19
- </template>
20
-
21
1
  <script lang="ts" setup>
22
- import { useTreeService } from '#adata-ui/components/elements/tree-select/TreeService.ts'
23
- import TreeSelectNodes from './components/tree-select-nodes.vue'
24
- import type { TreeData } from '#adata-ui/components/elements/tree-select/types'
25
- import type { TreeNestedNode } from '#adata-ui/components/elements/tree-select/types'
26
- import highlight from '#adata-ui/composables/highlight'
27
2
  import { useDebounceFn } from '@vueuse/core'
3
+ import { useTreeService } from '#adata-ui/components/elements/tree-select/TreeService'
4
+ import type { TreeData, TreeViewNode } from '#adata-ui/components/elements/tree-select/types'
28
5
 
29
6
  interface Props {
30
7
  options: TreeData[]
@@ -34,140 +11,147 @@ interface Props {
34
11
  disabled?: boolean
35
12
  onlyOne?: boolean
36
13
  searchText?: string
37
- // eslint-disable-next-line vue/require-default-prop
38
- asyncSearch?: (keyword: string) => TreeData[]
14
+ asyncSearch?: (keyword: string) => TreeData[] | Promise<TreeData[]>
39
15
  withoutId?: boolean
16
+ idKey?: string
17
+ nameKey?: string
18
+ childrenKey?: string
19
+ hasChildrenKey?: string
20
+ lazy?: boolean
21
+ loadChildren?: (node: TreeViewNode) => TreeData[] | Promise<TreeData[]>
40
22
  }
41
23
 
42
24
  interface Emits {
43
25
  (e: 'update:modelValue', item: (string | number)[]): void
44
26
  }
45
27
 
46
- const emits = defineEmits<Emits>()
47
28
  const props = withDefaults(defineProps<Props>(), {
48
29
  type: 'checkbox',
49
30
  searchText: '',
50
31
  withoutId: false,
51
32
  disabled: false,
52
33
  onlyOne: false,
34
+ idKey: 'id',
35
+ nameKey: 'name',
36
+ childrenKey: 'children',
37
+ lazy: false,
53
38
  })
39
+
40
+ const emits = defineEmits<Emits>()
41
+
54
42
  const {
55
- nestedTree,
56
- tree,
43
+ nodes,
44
+ build,
57
45
  setState,
58
- setExpandableClosed,
59
- initTree,
46
+ applyModel,
60
47
  collectSelectedIds,
61
- updateNestedTree,
62
- searchedData,
63
- toggleHiddenNodes,
64
48
  reset,
65
- toggleExpandableNodes,
66
- } = useTreeService( props.withoutId )
67
- const selected = computed({
68
- get() {
69
- return props.modelValue
70
- },
71
- set(val) {
72
- emits('update:modelValue', val)
73
- }
49
+ toggleExpand,
50
+ applySearch,
51
+ clearSearch,
52
+ } = useTreeService({
53
+ withoutId: props.withoutId,
54
+ idKey: props.idKey,
55
+ nameKey: props.nameKey,
56
+ childrenKey: props.childrenKey,
57
+ hasChildrenKey: props.hasChildrenKey,
58
+ lazy: props.lazy,
59
+ loadChildren: props.loadChildren,
74
60
  })
75
61
 
76
- initTree(props.options)
77
- const toggleExpand = (node) => {
78
- if (node.expandable) {
79
- setExpandableClosed(node.id, !node.expandableClosed)
80
- }
62
+ function emitSelection() {
63
+ emits('update:modelValue', collectSelectedIds())
81
64
  }
82
65
 
83
- const toggleCheckbox = (id, checked) => {
66
+ function toggleCheckbox(id: string | number, checked: boolean) {
84
67
  if (props.onlyOne && !checked) {
85
68
  reset()
86
- } else {
69
+ }
70
+ else {
87
71
  setState(id, checked ? 'checked' : 'unchecked')
88
72
  }
73
+ emitSelection()
89
74
  }
90
75
 
91
- function openFounded(nodes: TreeNestedNode[]) {
92
- nodes.forEach((node) => {
93
- node.expandableClosed = false
94
- node.text = highlight(node.text, props.searchText)
95
- if (node.child.length) {
96
- openFounded(node.child)
97
- }
98
- })
76
+ const selected = computed(() => props.modelValue ?? [])
77
+ function isDisabled(id: string | number) {
78
+ return props.onlyOne ? selected.value.length > 0 && !selected.value.includes(id) : false
99
79
  }
100
80
 
101
- function filterOptions(options: any[], search: string) {
81
+ function filterOptions(options: TreeData[], search: string): TreeData[] {
82
+ const needle = search.toLowerCase()
102
83
  return options
103
84
  .map((option) => {
104
- const matches = option.name.toLowerCase().includes(search.toLowerCase())
105
- const matchesWithId = option.id?.toString().toLowerCase().includes(search.toLowerCase())
106
- let filteredChildren = []
107
-
108
- if (option.children) {
109
- filteredChildren = filterOptions(option.children, search)
110
- }
111
-
112
- if (matches || matchesWithId || filteredChildren.length > 0) {
113
- return {
114
- ...option,
115
- children: filteredChildren
116
- }
85
+ const name = String(option[props.nameKey] ?? '').toLowerCase()
86
+ const id = option[props.idKey] as string | number | undefined
87
+ const matches = name.includes(needle)
88
+ const matchesId = id?.toString().toLowerCase().includes(needle)
89
+ const children = (option[props.childrenKey] as TreeData[] | undefined) ?? []
90
+ const filteredChildren = children.length ? filterOptions(children, search) : []
91
+
92
+ if (matches || matchesId || filteredChildren.length > 0) {
93
+ return { ...option, [props.childrenKey]: filteredChildren }
117
94
  }
118
-
119
95
  return null
120
96
  })
121
- .filter(Boolean)
97
+ .filter(Boolean) as TreeData[]
122
98
  }
123
99
 
124
100
  const debouncedSearch = useDebounceFn(async () => {
125
101
  if (props.searchText !== '') {
126
- if (props?.asyncSearch) {
127
- const searchData = await props.asyncSearch(props.searchText)
128
- searchedData(searchData, props.searchText)
129
- } else {
130
- const searchData = filterOptions(props.options, props.searchText)
131
- searchedData(searchData, props.searchText)
132
- }
133
- } else {
134
- toggleHiddenNodes(false)
135
- toggleExpandableNodes(true)
136
- updateNestedTree()
102
+ const data = props.asyncSearch
103
+ ? await props.asyncSearch(props.searchText)
104
+ : filterOptions(props.options, props.searchText)
105
+ applySearch(data, props.searchText)
106
+ }
107
+ else {
108
+ clearSearch()
137
109
  }
138
110
  }, 300)
139
111
 
140
- watch(
141
- () => props.searchText,
142
- (newVal) => debouncedSearch()
143
- )
112
+ watch(() => props.searchText, () => debouncedSearch())
144
113
 
114
+ function initFromOptions() {
115
+ build(props.options)
116
+ applyModel(props.modelValue)
117
+ emitSelection()
118
+ }
145
119
 
120
+ build(props.options)
146
121
  onMounted(() => {
147
- if (props.modelValue && props.modelValue.length) {
148
- props.modelValue.forEach((id) => {
149
- setState(id, 'checked')
150
- })
151
- }
152
-
153
- if (props.isSearch) {
154
- // openFounded(nestedTree.value)
155
- }
122
+ applyModel(props.modelValue)
123
+ emitSelection()
156
124
  })
125
+ watch(() => props.options, initFromOptions)
157
126
 
158
- const isDisabled = (id: string | number) => {
159
- return props.onlyOne ? selected.value.length > 0 && !selected.value.includes(id) : false
127
+ function resetSelection() {
128
+ reset()
129
+ emitSelection()
160
130
  }
161
- watch(
162
- tree,
163
- () => {
164
- if (tree.value) {
165
- selected.value = collectSelectedIds(tree.value)
166
- }
167
- },
168
- { deep: true }
169
- )
170
- defineExpose({
171
- reset
172
- })
131
+
132
+ defineExpose({ reset: resetSelection })
173
133
  </script>
134
+
135
+ <template>
136
+ <div>
137
+ <ul>
138
+ <template
139
+ v-for="node in nodes"
140
+ :key="node.id"
141
+ >
142
+ <a-tree-select-node
143
+ v-if="!node.hidden"
144
+ :node="node"
145
+ :toggle-expand="toggleExpand"
146
+ :toggle-checkbox="toggleCheckbox"
147
+ :type="type"
148
+ :disabled="isDisabled(node.id)"
149
+ >
150
+ <template v-if="$slots.label" #label="slotProps">
151
+ <slot name="label" v-bind="slotProps" />
152
+ </template>
153
+ </a-tree-select-node>
154
+ </template>
155
+ </ul>
156
+ </div>
157
+ </template>