adata-ui 2.1.40-beta.11 → 2.1.40-beta.12

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 (133) hide show
  1. package/assets/styles/index.scss +67 -5
  2. package/components/elements/a-select-row/ASelectRowV2.vue +8 -8
  3. package/components/elements/a-select-row/index.vue +3 -5
  4. package/components/elements/accordion/AAccordion.vue +5 -3
  5. package/components/elements/accordion/AAccordionGroup/AAccordionGroup.vue +3 -3
  6. package/components/elements/alert/AAlert.vue +34 -47
  7. package/components/elements/bg-block/ABgBlock.vue +1 -1
  8. package/components/elements/button/AButton.vue +3 -3
  9. package/components/elements/button/AButtonV2.vue +7 -5
  10. package/components/elements/button-login/index.vue +1 -1
  11. package/components/elements/chip-wrapper/AChipWrapper.vue +1 -1
  12. package/components/elements/chips/AChips.vue +2 -2
  13. package/components/elements/digit-badge/ADigitBadge.vue +21 -19
  14. package/components/elements/feature-description/AFeatureDescription.vue +1 -1
  15. package/components/elements/leave-note/ALeaveNote.vue +1 -1
  16. package/components/elements/pagination/APagination.vue +7 -7
  17. package/components/elements/segmented/ASegmentedV2.vue +103 -10
  18. package/components/elements/select/ASelect.vue +4 -4
  19. package/components/elements/select/ASelectMobile.vue +2 -2
  20. package/components/elements/select/ASelectV2.vue +10 -11
  21. package/components/elements/select/ui/select-button.vue +1 -1
  22. package/components/elements/status-badge/AStatusBadge.vue +22 -19
  23. package/components/elements/status-badge-v2/StatusBadgeV2.vue +1 -3
  24. package/components/elements/table/ATable.vue +1 -1
  25. package/components/elements/table/table.config.ts +2 -2
  26. package/components/elements/tree-select/ATreeSelect.vue +97 -113
  27. package/components/elements/tree-select/TreeService.ts +142 -207
  28. package/components/elements/tree-select/components/ATreeSelectNode.vue +104 -0
  29. package/components/elements/tree-select/types.ts +40 -11
  30. package/components/elements/tree-select/utils.ts +30 -0
  31. package/components/elements/tree-select-modal/ATreeSelectModal.vue +217 -0
  32. package/components/features/color-mode/AColorMode.client.vue +1 -1
  33. package/components/features/dropdown/ADropdownV2.vue +1 -2
  34. package/components/features/lang-switcher/lang-switcher.vue +9 -4
  35. package/components/features/payment/banner/BasicPlusLimitBanner.vue +3 -3
  36. package/components/features/payment/banner/PaymentBanner.vue +3 -3
  37. package/components/features/payment/banner/UpSellBanner.vue +3 -3
  38. package/components/features/payment/process/PaymentKaspiQrSidePanel.vue +3 -3
  39. package/components/features/payment/process/PaymentKaspiRedirectSidePanel.vue +1 -1
  40. package/components/features/payment/process/PaymentMethodSidePanel.vue +3 -3
  41. package/components/features/payment/process/PaymentTopUpSidePanel.vue +2 -2
  42. package/components/features/pk-mobile-services/APkMobileServices.vue +1 -1
  43. package/components/features//321/201hange-version/AChangeVersion.vue +2 -2
  44. package/components/forms/checkbox/ACheckbox.vue +1 -1
  45. package/components/forms/checkbox/ACheckboxV2.vue +5 -5
  46. package/components/forms/input/AInputV2.vue +4 -4
  47. package/components/forms/input/date/AInputDate.vue +2 -2
  48. package/components/forms/input/password/AInputPassword.vue +8 -2
  49. package/components/forms/input/standard/AInputStandard.vue +3 -3
  50. package/components/forms/input/textarea/ATextarea.vue +2 -2
  51. package/components/forms/toggle/AToggle.vue +2 -3
  52. package/components/forms/toggle/AToggleV2.vue +3 -3
  53. package/components/modals/AnotherDeviceModal.vue +1 -1
  54. package/components/modals/ContactsMobileModel.vue +1 -1
  55. package/components/modals/ContentNavigationModal.vue +3 -3
  56. package/components/modals/Insufficient-funds-modal.vue +1 -1
  57. package/components/modals/PaymentMethodModal.vue +1 -1
  58. package/components/modals/id/IdBanner.vue +3 -3
  59. package/components/modals/id/IdRecoveryModal.vue +1 -1
  60. package/components/navigation/breadcrumbs/ABreadcrumbs.vue +106 -45
  61. package/components/navigation/breadcrumbs/types.ts +3 -0
  62. package/components/navigation/footer/AFooter.vue +39 -40
  63. package/components/navigation/footer/ui/a-footer-accordion.vue +9 -9
  64. package/components/navigation/header/AHeader.vue +2 -4
  65. package/components/navigation/header/AlmatyContacts.vue +78 -78
  66. package/components/navigation/header/CardGallery.vue +4 -4
  67. package/components/navigation/header/HeaderUsage.vue +4 -6
  68. package/components/navigation/header/ListItem.vue +2 -2
  69. package/components/navigation/header/NavCard.vue +1 -1
  70. package/components/navigation/header/NavList.vue +2 -2
  71. package/components/navigation/header/NotificationsMenu.vue +2 -3
  72. package/components/navigation/header/ProductMenu.vue +1 -1
  73. package/components/navigation/header/ProfileMenu.vue +26 -35
  74. package/components/navigation/header/SystemNotification.vue +1 -3
  75. package/components/navigation/pill-tabs/APillTabs.vue +2 -2
  76. package/components/navigation/pill-tabs/APillTabsV2.vue +5 -5
  77. package/components/overlays/drawer/ADrawerV2.vue +335 -0
  78. package/components/overlays/modal/AModal.vue +4 -4
  79. package/components/overlays/modal/AModalV2.vue +4 -4
  80. package/components/overlays/side-panel/ASidePanel.vue +6 -6
  81. package/components/overlays/sideover/ASlideover.vue +6 -6
  82. package/components/overlays/tooltip/ATooltip.vue +1 -1
  83. package/components/overlays/tooltip/ATooltipV2.vue +2 -12
  84. package/components/transitions/ATransitionHeight.vue +1 -1
  85. package/composables/useHeaderNavigationLinks.ts +100 -94
  86. package/icons/archive.vue +16 -0
  87. package/icons/arrow/arrows-in.vue +11 -0
  88. package/icons/arrow/arrows-out.vue +11 -0
  89. package/icons/arrow/arrows-resize-in.vue +38 -0
  90. package/icons/arrow/arrows-resize-out.vue +17 -0
  91. package/icons/bot.vue +52 -0
  92. package/icons/clock-time.vue +24 -0
  93. package/icons/compare-outlined.vue +8 -0
  94. package/icons/dots-horizontal.vue +31 -0
  95. package/icons/download-line.vue +13 -0
  96. package/icons/egov.vue +41 -0
  97. package/icons/elicense.vue +38 -0
  98. package/icons/favourite-bookmark-outline.vue +17 -0
  99. package/icons/file-pen.vue +31 -0
  100. package/icons/file-stack.vue +31 -0
  101. package/icons/file-types/excel.vue +131 -0
  102. package/icons/file-types/html.vue +13 -0
  103. package/icons/file-types/jpeg.vue +16 -0
  104. package/icons/file-types/pdf.vue +11 -0
  105. package/icons/file-types/png.vue +11 -0
  106. package/icons/file-types/rar.vue +11 -0
  107. package/icons/file-types/word.vue +50 -0
  108. package/icons/file-types/zip.vue +11 -0
  109. package/icons/git-compare.vue +38 -0
  110. package/icons/graduation-cap.vue +31 -0
  111. package/icons/graph-loading.vue +34 -0
  112. package/icons/help-question-circle.vue +26 -0
  113. package/icons/in-row-type.vue +46 -0
  114. package/icons/in-table-type.vue +29 -0
  115. package/icons/message-dotted.vue +30 -0
  116. package/icons/notification-error.vue +17 -0
  117. package/icons/person.vue +22 -0
  118. package/icons/settings.vue +26 -0
  119. package/icons/shield-alert.vue +31 -0
  120. package/icons/socials/facebook-color.vue +16 -0
  121. package/icons/socials/globe-color.vue +16 -0
  122. package/icons/socials/instagram-color.vue +46 -0
  123. package/icons/socials/linkedin-color.vue +14 -0
  124. package/icons/socials/telegram-color.vue +16 -0
  125. package/icons/socials/tiktok-color.vue +14 -0
  126. package/icons/socials/vk-color.vue +16 -0
  127. package/icons/socials/youtube-color.vue +16 -0
  128. package/icons/view-eye-open.vue +13 -0
  129. package/package.json +1 -1
  130. package/plugins/toast.client.ts +38 -55
  131. package/tailwind.config.ts +147 -116
  132. package/utils/twMerge.ts +34 -0
  133. package/components/elements/tree-select/components/tree-select-nodes.vue +0 -91
@@ -0,0 +1,104 @@
1
+ <script lang="ts" setup>
2
+ import type { TreeViewNode } from '#adata-ui/components/elements/tree-select/types'
3
+
4
+ interface Props {
5
+ node: TreeViewNode
6
+ toggleExpand: (node: TreeViewNode) => void | Promise<void>
7
+ toggleCheckbox: (id: string | number, checked: boolean) => void
8
+ type: 'checkbox' | 'select'
9
+ disabled: boolean
10
+ }
11
+
12
+ const props = defineProps<Props>()
13
+
14
+ // explicit slot type breaks the recursive self-reference inference (TS7022)
15
+ defineSlots<{ label?: (props: { node: TreeViewNode }) => unknown }>()
16
+
17
+ const isDisabled = computed(() => props.disabled && props.node.state === 'unchecked')
18
+
19
+ function onSelectToggle() {
20
+ if (isDisabled.value) return
21
+ props.toggleCheckbox(props.node.id, props.node.state !== 'checked')
22
+ }
23
+ </script>
24
+
25
+ <template>
26
+ <li
27
+ :style="{ paddingLeft: `${node.level * 20}px` }"
28
+ :class="[{ 'bg-[#2C3E500D] dark:bg-[#E3E5E80D]': node.state === 'checked' && type === 'select' }]"
29
+ >
30
+ <div
31
+ v-if="!node.hidden"
32
+ class="flex items-center gap-1 p-2"
33
+ :class="{ 'bg-deepblue-50 dark:bg-gray-200/5': isDisabled }"
34
+ >
35
+ <div class="flex min-w-4 items-center">
36
+ <a-icon-loader-circle
37
+ v-if="node.loading"
38
+ class="size-4 animate-spin text-gray-400 dark:text-gray-500"
39
+ />
40
+ <a-icon-chevron-down
41
+ v-else-if="node.expandable"
42
+ width="16"
43
+ height="16"
44
+ class="cursor-pointer transition-all"
45
+ :class="{ '-rotate-90': !node.expanded }"
46
+ @click="toggleExpand(node)"
47
+ />
48
+ </div>
49
+
50
+ <a-checkbox-v2
51
+ v-if="type === 'checkbox'"
52
+ size="lg"
53
+ side="left"
54
+ class="flex w-full items-center justify-between text-left"
55
+ :model-value="node.state === 'checked'"
56
+ :intermediate="node.state === 'indeterminate'"
57
+ :disabled="isDisabled"
58
+ :name="`${node.id}`"
59
+ @update:model-value="(checked) => toggleCheckbox(node.id, checked as boolean)"
60
+ >
61
+ <slot name="label" :node="node">
62
+ <span class="text-body-md-strong" v-html="node.text" />
63
+ </slot>
64
+ </a-checkbox-v2>
65
+
66
+ <div
67
+ v-else
68
+ role="button"
69
+ tabindex="0"
70
+ class="flex w-full cursor-pointer items-center justify-between gap-4"
71
+ :class="{ 'pointer-events-none opacity-60': isDisabled }"
72
+ @click="onSelectToggle"
73
+ @keydown.enter.prevent="onSelectToggle"
74
+ @keydown.space.prevent="onSelectToggle"
75
+ >
76
+ <slot name="label" :node="node">
77
+ <span :class="{ 'font-semibold': node.level === 0 }" v-html="node.text" />
78
+ </slot>
79
+ <a-icon-check
80
+ v-if="node.state === 'checked'"
81
+ class="min-w-4 text-blue-700 dark:text-blue-400"
82
+ />
83
+ </div>
84
+ </div>
85
+
86
+ <a-transition-height>
87
+ <ul v-if="node.expandable && node.expanded">
88
+ <a-tree-select-node
89
+ v-for="child in node.children"
90
+ :key="child.id"
91
+ :node="child"
92
+ :toggle-expand="toggleExpand"
93
+ :toggle-checkbox="toggleCheckbox"
94
+ :type="type"
95
+ :disabled="disabled"
96
+ >
97
+ <template v-if="$slots.label" #label="slotProps">
98
+ <slot name="label" v-bind="slotProps" />
99
+ </template>
100
+ </a-tree-select-node>
101
+ </ul>
102
+ </a-transition-height>
103
+ </li>
104
+ </template>
@@ -1,3 +1,43 @@
1
+ export type TreeNodeState = 'checked' | 'unchecked' | 'indeterminate'
2
+ export type TreeNodeStateEditable = 'checked' | 'unchecked'
3
+
4
+ export type TreeData = {
5
+ id?: number | string
6
+ name?: string
7
+ children?: TreeData[]
8
+ [key: string]: unknown
9
+ }
10
+
11
+ export interface TreeViewNode {
12
+ id: string | number
13
+ name: string
14
+ text: string
15
+ baseText: string
16
+ level: number
17
+ state: TreeNodeState
18
+ expandable: boolean
19
+ expanded: boolean
20
+ hidden: boolean
21
+ loaded: boolean
22
+ loading: boolean
23
+ parent: TreeViewNode | null
24
+ children: TreeViewNode[]
25
+ raw: TreeData
26
+ }
27
+
28
+ export interface TreeKeyConfig {
29
+ idKey?: string
30
+ nameKey?: string
31
+ childrenKey?: string
32
+ hasChildrenKey?: string
33
+ }
34
+
35
+ export interface TreeServiceOptions extends TreeKeyConfig {
36
+ withoutId?: boolean
37
+ lazy?: boolean
38
+ loadChildren?: (node: TreeViewNode) => Promise<TreeData[]> | TreeData[]
39
+ }
40
+
1
41
  export interface TreeNode {
2
42
  id: string | number
3
43
  name: string
@@ -19,16 +59,5 @@ export interface TreeNestedNode {
19
59
  expandableClosed: boolean
20
60
  text: string
21
61
  hidden: boolean
22
- // parent: TreeNestedNode | null;
23
62
  child: TreeNestedNode[]
24
63
  }
25
-
26
- export type TreeData = {
27
- // [key: string]: null | string[] | TreeData;
28
- id: number | string
29
- name: string
30
- children?: TreeData[]
31
- }
32
-
33
- export type TreeNodeState = 'checked' | 'unchecked' | 'indeterminate'
34
- export type TreeNodeStateEditable = 'checked' | 'unchecked'
@@ -0,0 +1,30 @@
1
+ import type { TreeData, TreeKeyConfig } from '#adata-ui/components/elements/tree-select/types'
2
+
3
+ export interface SelectedItem {
4
+ id: string | number
5
+ name: string
6
+ }
7
+
8
+ export function getSelectedItems(
9
+ options: TreeData[],
10
+ ids: (string | number)[],
11
+ keys: TreeKeyConfig = {},
12
+ ): SelectedItem[] {
13
+ const { idKey = 'id', nameKey = 'name', childrenKey = 'children' } = keys
14
+ const wanted = new Set(ids ?? [])
15
+ const result: SelectedItem[] = []
16
+
17
+ const walk = (items: TreeData[]): void => {
18
+ items.forEach((item) => {
19
+ const id = item[idKey] as string | number
20
+ if (wanted.has(id)) {
21
+ result.push({ id, name: String(item[nameKey] ?? '') })
22
+ }
23
+ const children = item[childrenKey] as TreeData[] | undefined
24
+ if (children?.length) walk(children)
25
+ })
26
+ }
27
+
28
+ walk(options ?? [])
29
+ return result
30
+ }
@@ -0,0 +1,217 @@
1
+ <script lang="ts" setup>
2
+ import type { TreeData, TreeViewNode } from '#adata-ui/components/elements/tree-select/types'
3
+ import { getSelectedItems } from '#adata-ui/components/elements/tree-select/utils'
4
+ import AIconSearch from '#adata-ui/icons/search.vue'
5
+
6
+ type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | 'container' | 'fullscreen'
7
+
8
+ interface Props {
9
+ options: TreeData[]
10
+ label?: string
11
+ title?: string
12
+ searchLabel?: string
13
+ type?: 'checkbox' | 'select'
14
+ onlyOne?: boolean
15
+ withoutId?: boolean
16
+ loading?: boolean
17
+ disabled?: boolean
18
+ asyncSearch?: (keyword: string) => TreeData[] | Promise<TreeData[]>
19
+ filteringLabel?: string
20
+ applyLabel?: string
21
+ resetLabel?: string
22
+ btnClass?: string
23
+ size?: ModalSize
24
+ width?: string
25
+ bodyHeight?: string
26
+ idKey?: string
27
+ nameKey?: string
28
+ childrenKey?: string
29
+ hasChildrenKey?: string
30
+ lazy?: boolean
31
+ loadChildren?: (node: TreeViewNode) => TreeData[] | Promise<TreeData[]>
32
+ }
33
+
34
+ const props = withDefaults(defineProps<Props>(), {
35
+ label: '',
36
+ title: '',
37
+ searchLabel: '',
38
+ type: 'checkbox',
39
+ onlyOne: false,
40
+ withoutId: false,
41
+ loading: false,
42
+ disabled: false,
43
+ filteringLabel: '',
44
+ applyLabel: 'Применить',
45
+ resetLabel: 'Сбросить',
46
+ btnClass: '',
47
+ size: 'lg',
48
+ bodyHeight: '50vh',
49
+ idKey: 'id',
50
+ nameKey: 'name',
51
+ childrenKey: 'children',
52
+ lazy: false,
53
+ })
54
+
55
+ const emit = defineEmits<{
56
+ (e: 'submit'): void
57
+ (e: 'cancel'): void
58
+ }>()
59
+
60
+ const selected = defineModel<(string | number)[]>({ default: () => [] })
61
+ const search = defineModel<string>('search', { default: '' })
62
+ const isOpen = defineModel<boolean>('open', { default: false })
63
+
64
+ const treeRef = ref<{ reset: () => void } | null>(null)
65
+ const isSearch = ref(false)
66
+
67
+ const count = computed(() => selected.value?.length ?? 0)
68
+
69
+ const dataForDisplay = computed(() =>
70
+ getSelectedItems(props.options, selected.value ?? [], {
71
+ idKey: props.idKey,
72
+ nameKey: props.nameKey,
73
+ childrenKey: props.childrenKey,
74
+ }),
75
+ )
76
+
77
+ const treeAreaStyle = computed(() =>
78
+ props.bodyHeight && props.bodyHeight !== 'auto' ? { height: props.bodyHeight } : undefined,
79
+ )
80
+
81
+ function openModal() {
82
+ if (props.disabled) return
83
+ isOpen.value = true
84
+ }
85
+
86
+ function onApply() {
87
+ isOpen.value = false
88
+ search.value = ''
89
+ nextTick(() => emit('submit'))
90
+ }
91
+
92
+ function onReset() {
93
+ treeRef.value?.reset()
94
+ selected.value = []
95
+ search.value = ''
96
+ emit('cancel')
97
+ }
98
+
99
+ watch(
100
+ () => props.loading,
101
+ (loading) => {
102
+ if (!loading) isSearch.value = !!search.value.length
103
+ },
104
+ )
105
+
106
+ defineExpose({ open: openModal, close: () => (isOpen.value = false) })
107
+ </script>
108
+
109
+ <template>
110
+ <div class="tree-select-modal w-full">
111
+ <slot
112
+ name="trigger"
113
+ :open="openModal"
114
+ :selected="dataForDisplay"
115
+ :count="count"
116
+ >
117
+ <a-select-row-v2
118
+ v-model:is-open="isOpen"
119
+ :label="label"
120
+ :selected-items="dataForDisplay"
121
+ :disabled="disabled"
122
+ :btn-class="btnClass"
123
+ :clearable="false"
124
+ :deletable="false"
125
+ />
126
+ </slot>
127
+
128
+ <a-modal-v2
129
+ v-model="isOpen"
130
+ :title="title"
131
+ :size="size"
132
+ :width="width"
133
+ >
134
+ <template #header>
135
+ <slot name="header" :title="title">
136
+ <h2 class="text-h5 text-gray-900 dark:text-gray-100">
137
+ {{ title }}
138
+ </h2>
139
+ </slot>
140
+ </template>
141
+
142
+ <div class="flex flex-col">
143
+ <div class="sticky top-0 z-[1] flex flex-col gap-4 bg-white px-5 pb-4 pt-4 dark:bg-gray-900">
144
+ <a-input-v2
145
+ v-model="search"
146
+ type="search"
147
+ :label="searchLabel"
148
+ :start-icon="AIconSearch"
149
+ clearable
150
+ />
151
+
152
+ <p v-if="filteringLabel" class="text-body-sm text-gray-500 dark:text-gray-400">
153
+ {{ filteringLabel }}
154
+ </p>
155
+ </div>
156
+
157
+ <div
158
+ class="tree-select-modal__body px-5 pb-4"
159
+ :class="{ 'overflow-auto': treeAreaStyle }"
160
+ :style="treeAreaStyle"
161
+ >
162
+ <a-tree-select
163
+ v-if="!loading"
164
+ ref="treeRef"
165
+ v-model="selected"
166
+ :options="options"
167
+ :type="type"
168
+ :only-one="onlyOne"
169
+ :is-search="isSearch"
170
+ :search-text="search"
171
+ :async-search="asyncSearch"
172
+ :without-id="withoutId"
173
+ :id-key="idKey"
174
+ :name-key="nameKey"
175
+ :children-key="childrenKey"
176
+ :has-children-key="hasChildrenKey"
177
+ :lazy="lazy"
178
+ :load-children="loadChildren"
179
+ >
180
+ <template v-if="$slots.label" #label="slotProps">
181
+ <slot name="label" v-bind="slotProps" />
182
+ </template>
183
+ </a-tree-select>
184
+
185
+ <div v-else class="flex items-center justify-center py-10 text-gray-400 dark:text-gray-500">
186
+ <a-icon-loader-circle class="size-6 animate-spin" />
187
+ </div>
188
+ </div>
189
+ </div>
190
+
191
+ <template #footer="{ close }">
192
+ <slot
193
+ name="footer"
194
+ :reset="onReset"
195
+ :apply="onApply"
196
+ :close="close"
197
+ :count="count"
198
+ >
199
+ <div class="flex justify-end gap-2">
200
+ <a-button-v2
201
+ view="outline"
202
+ color="gray"
203
+ @click="onReset"
204
+ >
205
+ {{ resetLabel }}
206
+ </a-button-v2>
207
+ <a-button-v2 @click="onApply">
208
+ {{ applyLabel }}<template v-if="count">
209
+ ({{ count }})
210
+ </template>
211
+ </a-button-v2>
212
+ </div>
213
+ </slot>
214
+ </template>
215
+ </a-modal-v2>
216
+ </div>
217
+ </template>
@@ -37,7 +37,7 @@ useEventListener(window, 'storage', (event: StorageEvent) => {
37
37
  <client-only>
38
38
  <button
39
39
  type="button"
40
- class="relative inline-flex size-8 items-center justify-center overflow-hidden rounded-xl text-deepblue-900/80 transition-colors duration-150 hover:bg-deepblue-900/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 focus-visible:ring-offset-1 dark:text-gray-200 dark:hover:bg-white/10 dark:focus-visible:ring-offset-gray-900"
40
+ class="relative inline-flex size-8 items-center justify-center overflow-hidden rounded-lg text-deepblue-900/80 transition-colors duration-150 hover:bg-deepblue-900/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 focus-visible:ring-offset-1 dark:text-gray-200 dark:hover:bg-white/10 dark:focus-visible:ring-offset-gray-900"
41
41
  :aria-label="isDark ? 'Switch to light mode' : 'Switch to dark mode'"
42
42
  data-test-id="header-switch-theme-toggle"
43
43
  @click="toggle"
@@ -24,7 +24,6 @@ const { x, y, strategy, update, placement: resolvedPlacement } = useFloating(ref
24
24
  middleware: computed(() => [offsetMiddleware(props.offset), flip(), shift({ padding: 8 })]),
25
25
  })
26
26
 
27
- // Anchor the grow/shrink animation to the trigger so the panel feels attached.
28
27
  const transformOrigin = computed(() => {
29
28
  const [side, align] = resolvedPlacement.value.split('-')
30
29
  const vertical = side === 'top' ? 'bottom' : 'top'
@@ -85,7 +84,7 @@ onKeyStroke('Escape', () => {
85
84
  <div
86
85
  v-if="isOpen"
87
86
  ref="floating"
88
- class="z-[60] overflow-hidden rounded-xl shadow-lg shadow-gray-900/10 dark:shadow-black/30"
87
+ class="z-[60] overflow-hidden rounded-lg shadow-lg shadow-gray-900/10 dark:shadow-black/30"
89
88
  :style="{
90
89
  position: strategy,
91
90
  left: x != null ? `${x}px` : '',
@@ -66,7 +66,7 @@ function onSelect(loc: LocaleItem) {
66
66
  <button
67
67
  ref="reference"
68
68
  type="button"
69
- class="inline-flex size-8 items-center justify-center rounded-xl text-xs font-semibold text-gray-900 transition-colors duration-150 hover:bg-deepblue-900/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 focus-visible:ring-offset-1 dark:text-gray-100 dark:hover:bg-white/10 dark:focus-visible:ring-offset-gray-900"
69
+ class="inline-flex size-8 items-center justify-center rounded-lg text-body-sm font-semibold text-gray-900 transition-colors duration-150 hover:bg-deepblue-900/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 focus-visible:ring-offset-1 dark:text-gray-100 dark:hover:bg-white/10 dark:focus-visible:ring-offset-gray-900"
70
70
  :class="[
71
71
  isOpen
72
72
  ? 'bg-blue-50 text-blue-700 ring-2 ring-blue-500/20 dark:bg-blue-900/40 dark:text-blue-300'
@@ -91,7 +91,7 @@ function onSelect(loc: LocaleItem) {
91
91
  <div
92
92
  v-if="isOpen"
93
93
  ref="floating"
94
- class="z-[10000] w-fit rounded-xl border border-gray-200 bg-white shadow-lg shadow-gray-900/10 dark:border-gray-700 dark:bg-gray-900 dark:shadow-black/30"
94
+ class="z-[10000] w-fit rounded-lg border border-gray-200 bg-white shadow-lg shadow-gray-900/10 dark:border-gray-700 dark:bg-gray-900 dark:shadow-black/30"
95
95
  :style="{
96
96
  position: strategy,
97
97
  left: x != null ? `${x}px` : '',
@@ -99,11 +99,16 @@ function onSelect(loc: LocaleItem) {
99
99
  }"
100
100
  >
101
101
  <ul class="flex flex-col gap-1 p-1.5" role="listbox">
102
- <li v-for="loc in locales" :key="localeCode(loc)" role="option" :aria-selected="localeCode(loc) === locale">
102
+ <li
103
+ v-for="loc in locales"
104
+ :key="localeCode(loc)"
105
+ role="option"
106
+ :aria-selected="localeCode(loc) === locale"
107
+ >
103
108
  <nuxt-link
104
109
  :data-test-id="`header-switch-${localeCode(loc)}-language-button${testIdSuffix}`"
105
110
  :to="switchLocalePath(localeCode(loc))"
106
- class="flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-sm transition-colors duration-100"
111
+ class="flex w-full items-center justify-between gap-3 rounded-md px-3 py-2 text-body-md transition-colors duration-100"
107
112
  :class="[
108
113
  localeCode(loc) === locale
109
114
  ? 'bg-blue-50 font-medium text-blue-700 dark:bg-blue-900/30 dark:text-blue-400'
@@ -51,15 +51,15 @@ function onUpdate() {
51
51
  </script>
52
52
 
53
53
  <template>
54
- <div class="gradient flex justify-between rounded-lg p-4 ring-1 ring-inset ring-blue-700/80 dark:bg-gray-800">
54
+ <div class="gradient flex justify-between rounded-md p-4 ring-1 ring-inset ring-blue-700/80 dark:bg-gray-800">
55
55
  <div>
56
- <p class="mb-2 font-semibold">
56
+ <p class="mb-2 text-h5">
57
57
  {{ t('modals.id.banners.basicPlusLimit.title') }}
58
58
  </p>
59
59
  <i18n-t
60
60
  keypath="modals.id.banners.basicPlusLimit.subtitle"
61
61
  tag="p"
62
- class="text-sm text-gray-600 dark:text-gray-200"
62
+ class="text-body-md text-gray-600 dark:text-gray-200"
63
63
  >
64
64
  <template #topUp>
65
65
  <button
@@ -56,15 +56,15 @@ function onBuy() {
56
56
  </script>
57
57
 
58
58
  <template>
59
- <div class="gradient flex justify-between rounded-lg p-4 ring-1 ring-inset ring-blue-700/80 dark:bg-gray-800">
59
+ <div class="gradient flex justify-between rounded-md p-4 ring-1 ring-inset ring-blue-700/80 dark:bg-gray-800">
60
60
  <div>
61
- <p class="mb-2 font-semibold">
61
+ <p class="mb-2 text-h5">
62
62
  {{ t('payment.banner.title') }}
63
63
  </p>
64
64
  <i18n-t
65
65
  keypath="payment.banner.subtitle"
66
66
  tag="p"
67
- class="text-sm text-gray-600 dark:text-gray-200"
67
+ class="text-body-md text-gray-600 dark:text-gray-200"
68
68
  >
69
69
  <template #tariffs>
70
70
  <nuxt-link
@@ -72,16 +72,16 @@ function onBuy() {
72
72
  </script>
73
73
 
74
74
  <template>
75
- <div class="relative gradient flex justify-between rounded-lg p-4 ring-1 ring-inset ring-blue-700/80 dark:bg-gray-800">
75
+ <div class="relative gradient flex justify-between rounded-md p-4 ring-1 ring-inset ring-blue-700/80 dark:bg-gray-800">
76
76
  <div class="flex flex-col gap-3">
77
- <p class="font-semibold">
77
+ <p class="text-h5">
78
78
  {{ t(`payment.upsell.${code}.title`) }}
79
79
  </p>
80
80
 
81
81
  <i18n-t
82
82
  :keypath="`payment.upsell.${code}.description`"
83
83
  tag="p"
84
- class="text-sm whitespace-pre-line"
84
+ class="text-body-md whitespace-pre-line"
85
85
  >
86
86
  <template #highlight>
87
87
  <span class="font-semibold">{{ t(`payment.upsell.${code}.highlight`) }}</span>
@@ -121,7 +121,7 @@ watch(isOpen, async (value) => {
121
121
  <div class="flex items-center gap-2">
122
122
  <button
123
123
  type="button"
124
- class="rounded-lg p-1 transition-colors hover:bg-gray-100 dark:hover:bg-white/[0.06]"
124
+ class="rounded-md p-1 transition-colors hover:bg-gray-100 dark:hover:bg-white/[0.06]"
125
125
  @click="onBack"
126
126
  >
127
127
  <a-icon-chevron-left class="size-6" />
@@ -137,7 +137,7 @@ watch(isOpen, async (value) => {
137
137
  {{ t('payment.kaspi.description') }}
138
138
  </p>
139
139
 
140
- <div class="flex flex-col items-center gap-5 rounded-2xl border border-gray-200 bg-white p-6 dark:border-gray-700 dark:bg-gray-900">
140
+ <div class="flex flex-col items-center gap-5 rounded-xl border border-gray-200 bg-white p-6 dark:border-gray-700 dark:bg-gray-900">
141
141
  <div class="flex items-center gap-3">
142
142
  <a-icon-kaspi-qr class="size-14" />
143
143
  <span class="text-[40px] font-bold leading-none text-deepblue-900 dark:text-white">
@@ -151,7 +151,7 @@ watch(isOpen, async (value) => {
151
151
 
152
152
  <canvas
153
153
  id="kaspiQr"
154
- class="rounded-lg"
154
+ class="rounded-md"
155
155
  />
156
156
 
157
157
  <p class="text-center text-base text-gray-600 dark:text-gray-300">
@@ -83,7 +83,7 @@ watch(isOpen, async (value) => {
83
83
  {{ t('payment.redirect.title') }}
84
84
  </p>
85
85
 
86
- <div class="flex flex-col items-center gap-1 rounded-2xl bg-gray-50 p-5 text-center dark:bg-white/[0.03]">
86
+ <div class="flex flex-col items-center gap-1 rounded-xl bg-gray-50 p-5 text-center dark:bg-white/[0.03]">
87
87
  <span class="text-xs text-gray-500 dark:text-gray-400">
88
88
  {{ t('payment.redirect.paymentId') }}
89
89
  </span>
@@ -46,7 +46,7 @@ function onBack() {
46
46
  <div class="flex items-center gap-2">
47
47
  <button
48
48
  type="button"
49
- class="rounded-lg p-1 transition-colors hover:bg-gray-100 dark:hover:bg-white/[0.06]"
49
+ class="rounded-md p-1 transition-colors hover:bg-gray-100 dark:hover:bg-white/[0.06]"
50
50
  @click="onBack"
51
51
  >
52
52
  <a-icon-chevron-left class="size-6" />
@@ -58,7 +58,7 @@ function onBack() {
58
58
  </template>
59
59
 
60
60
  <div class="flex flex-col gap-6">
61
- <div class="flex flex-col items-center gap-4 rounded-2xl bg-gray-50 p-6 text-center dark:bg-white/[0.03]">
61
+ <div class="flex flex-col items-center gap-4 rounded-xl bg-gray-50 p-6 text-center dark:bg-white/[0.03]">
62
62
  <a-ill-phone-check class="size-[120px]" />
63
63
  <p class="text-sm font-medium text-gray-600 dark:text-gray-300">
64
64
  {{ t('payment.method.description') }}
@@ -74,7 +74,7 @@ function onBack() {
74
74
  v-for="item in cards"
75
75
  :key="item.id"
76
76
  type="button"
77
- class="flex items-center gap-3 rounded-2xl border p-4 text-left transition-colors"
77
+ class="flex items-center gap-3 rounded-xl border p-4 text-left transition-colors"
78
78
  :class="selected === item.id
79
79
  ? 'border-blue-500 bg-blue-50/60 dark:border-blue-400 dark:bg-blue-950/30'
80
80
  : 'border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-900 dark:hover:bg-gray-800'"
@@ -53,7 +53,7 @@ function handlePayment() {
53
53
  </template>
54
54
 
55
55
  <div class="flex flex-col gap-6">
56
- <div class="flex flex-col items-center gap-4 rounded-2xl bg-gray-50 p-6 text-center dark:bg-white/[0.03]">
56
+ <div class="flex flex-col items-center gap-4 rounded-xl bg-gray-50 p-6 text-center dark:bg-white/[0.03]">
57
57
  <a-ill-bill class="size-[120px]" />
58
58
  <p class="text-sm font-medium text-gray-600 dark:text-gray-300">
59
59
  {{ t('payment.topUp.info') }}
@@ -75,7 +75,7 @@ function handlePayment() {
75
75
  v-for="item in sumArr"
76
76
  :key="item.id"
77
77
  type="button"
78
- class="rounded-xl border px-3 py-2.5 text-sm font-semibold transition-colors"
78
+ class="rounded-lg border px-3 py-2.5 text-sm font-semibold transition-colors"
79
79
  :class="amount === item.value
80
80
  ? 'border-blue-500 bg-blue-50 text-blue-700 dark:border-blue-400 dark:bg-blue-950/40 dark:text-blue-300'
81
81
  : 'border-gray-200 bg-white text-deepblue-900 hover:border-gray-300 hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:hover:bg-gray-800'"
@@ -29,7 +29,7 @@ const blockStyles = [
29
29
  :class="['flex flex-col items-center gap-2 p-2', blockStyles[index]]"
30
30
  >
31
31
  <div
32
- class="size-10 p-2 rounded-lg"
32
+ class="size-10 p-2 rounded-md"
33
33
  :class="[
34
34
  'bg-deepblue-900/5 dark:bg-gray-200/5',
35
35
  {'!bg-blue-700 text-white dark:!bg-blue-500 ': isActiveService(service.to)}
@@ -10,9 +10,9 @@ const { t } = useI18n()
10
10
  <nuxt-link
11
11
  :to="url"
12
12
  target="_blank"
13
- class="flex cursor-pointer items-center justify-center gap-1 rounded-md bg-blue-700/10 px-3 py-2 text-blue-700 transition-colors duration-150 hover:bg-blue-700/15 dark:bg-blue-400/10 dark:text-blue-300 dark:hover:bg-blue-400/20"
13
+ class="flex cursor-pointer items-center justify-center gap-1 rounded-sm bg-blue-700/10 px-3 py-2 text-blue-700 transition-colors duration-150 hover:bg-blue-700/15 dark:bg-blue-400/10 dark:text-blue-300 dark:hover:bg-blue-400/20"
14
14
  >
15
- <span class="body-400">{{ t('header.oldVersion') }}</span>
15
+ <span class="text-body-md">{{ t('header.oldVersion') }}</span>
16
16
  <a-icon-arrow-bottom-left-on-square class="rotate-180" />
17
17
  </nuxt-link>
18
18
  </template>
@@ -58,7 +58,7 @@
58
58
  </template>
59
59
 
60
60
  <script setup lang="ts">
61
- import { twMerge } from 'tailwind-merge'
61
+ import { twMerge } from '#adata-ui/utils/twMerge'
62
62
 
63
63
 
64
64
  defineOptions({ name: 'ACheckbox' })