gi-component 0.0.44 → 0.0.45

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 (36) hide show
  1. package/dist/components/descriptions/src/descriptions.vue.d.ts +1 -1
  2. package/dist/components/drawer/src/drawer.vue.d.ts +1 -1
  3. package/dist/components/flex/src/flex.vue.d.ts +2 -2
  4. package/dist/components/flex/src/type.d.ts +2 -2
  5. package/dist/components/nav-tabs/index.d.ts +4 -0
  6. package/dist/components/nav-tabs/src/nav-tabs.vue.d.ts +49 -0
  7. package/dist/components/nav-tabs/src/type.d.ts +12 -0
  8. package/dist/components/plus-tabs/index.d.ts +8 -0
  9. package/dist/components/plus-tabs/src/context.d.ts +26 -0
  10. package/dist/components/plus-tabs/src/plus-tab-pane.vue.d.ts +39 -0
  11. package/dist/components/plus-tabs/src/plus-tabs.vue.d.ts +78 -0
  12. package/dist/components/plus-tabs/src/type.d.ts +5 -0
  13. package/dist/components/tab/index.d.ts +2 -0
  14. package/dist/components/tab/src/context.d.ts +10 -0
  15. package/dist/components/tab/src/tab-item.vue.d.ts +26 -0
  16. package/dist/components/tab/src/tab.vue.d.ts +44 -0
  17. package/dist/components/tab/src/type.d.ts +21 -0
  18. package/dist/components/tab/src/use-nav-tabs.d.ts +2 -0
  19. package/dist/components/tab/src/use-tabs.d.ts +13 -0
  20. package/dist/components/tabs/src/tabs.vue.d.ts +2 -2
  21. package/dist/gi.css +1 -1
  22. package/dist/hooks/index.d.ts +1 -0
  23. package/dist/hooks/useNavTabs.d.ts +22 -0
  24. package/dist/index.d.ts +3 -3
  25. package/dist/index.es.js +263 -2023
  26. package/dist/index.es.js.map +1 -1
  27. package/dist/index.umd.js +1 -1
  28. package/dist/index.umd.js.map +1 -1
  29. package/package.json +1 -1
  30. package/packages/components/nav-tabs/index.ts +5 -0
  31. package/packages/components/nav-tabs/src/nav-tabs.vue +164 -0
  32. package/packages/components/nav-tabs/src/type.ts +13 -0
  33. package/packages/components.d.ts +34 -33
  34. package/packages/hooks/index.ts +1 -0
  35. package/packages/hooks/useNavTabs.ts +275 -0
  36. package/packages/index.ts +4 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gi-component",
3
3
  "type": "module",
4
- "version": "0.0.44",
4
+ "version": "0.0.45",
5
5
  "description": "Vue3中基于Element Plus二次封装基础组件库",
6
6
  "author": "lin",
7
7
  "license": "MIT",
@@ -0,0 +1,5 @@
1
+ import NavTabs from './src/nav-tabs.vue'
2
+
3
+ export type NavTabsInstance = InstanceType<typeof NavTabs>
4
+ export * from './src/type'
5
+ export default NavTabs
@@ -0,0 +1,164 @@
1
+ <template>
2
+ <div ref="rootRef" :class="[b('nav-tabs'), { [b('nav-tabs--custom')]: props.custom }]">
3
+ <div v-if="slots['left-extra']" :class="b('nav-tabs__left')">
4
+ <slot name="left-extra" />
5
+ </div>
6
+ <div ref="scrollRef" :class="b('nav-tabs__scroll')">
7
+ <div v-for="item in props.data" :key="item.value" :class="[
8
+ b('nav-tabs-item'),
9
+ props.custom
10
+ ? b('nav-tabs-item--custom')
11
+ : {
12
+ [b('nav-tabs-item--active')]: model === item.value,
13
+ [b('nav-tabs-item--disabled')]: item.disabled,
14
+ },
15
+ ]" :data-value="item.value" @click="handleItemClick(item)">
16
+ <slot :item="item" :active="model === item.value" :disabled="!!item.disabled">
17
+ {{ item.label }}
18
+ </slot>
19
+ </div>
20
+ </div>
21
+ <div v-if="slots['right-extra']" :class="b('nav-tabs__right')">
22
+ <slot name="right-extra" />
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import type { NavTabItem, NavTabsProps } from './type.ts'
29
+ import { ref, useSlots } from 'vue'
30
+ import { useBemClass, useNavTabs } from '../../../hooks'
31
+
32
+ const model = defineModel<string | number>()
33
+
34
+ const props = withDefaults(defineProps<NavTabsProps>(), {
35
+ data: () => [],
36
+ wheelSpeed: 1,
37
+ custom: false
38
+ })
39
+
40
+ const emits = defineEmits<{
41
+ (e: 'change', value: string | number): void
42
+ }>()
43
+
44
+ defineSlots<{
45
+ 'default': (props: {
46
+ item: NavTabItem
47
+ active: boolean
48
+ disabled: boolean
49
+ }) => void
50
+ 'left-extra': () => void
51
+ 'right-extra': () => void
52
+ }>()
53
+
54
+ const slots = useSlots()
55
+ const { b } = useBemClass()
56
+
57
+ const rootRef = ref<HTMLElement | null>(null)
58
+ const scrollRef = ref<HTMLElement | null>(null)
59
+
60
+ const tabItemClassName = b('nav-tabs-item')
61
+
62
+ useNavTabs({
63
+ tabEl: rootRef,
64
+ tabScrollEl: scrollRef,
65
+ tabItemClassName,
66
+ activeValue: model,
67
+ wheelSpeed: props.wheelSpeed
68
+ })
69
+
70
+ function handleItemClick(item: NavTabItem) {
71
+ if (item.disabled) {
72
+ return
73
+ }
74
+ model.value = item.value
75
+ emits('change', item.value)
76
+ }
77
+ </script>
78
+
79
+ <style lang="scss" scoped>
80
+ @use '../../../styles/var.scss' as a;
81
+
82
+ .#{a.$prefix}-nav-tabs {
83
+ display: flex;
84
+ align-items: center;
85
+ width: 100%;
86
+ height: 40px;
87
+ box-sizing: border-box;
88
+
89
+ &__left {
90
+ flex-shrink: 0;
91
+ margin-right: 10px;
92
+ }
93
+
94
+ &__right {
95
+ flex-shrink: 0;
96
+ margin-left: 10px;
97
+ }
98
+
99
+ &__scroll {
100
+ flex: 1;
101
+ display: flex;
102
+ overflow-x: auto;
103
+ overflow-y: hidden;
104
+ scrollbar-width: none;
105
+ height: 100%;
106
+
107
+ &::-webkit-scrollbar {
108
+ display: none;
109
+ }
110
+ }
111
+
112
+ &:not(.#{a.$prefix}-nav-tabs--custom) {
113
+ .#{a.$prefix}-nav-tabs-item {
114
+ padding: 0 16px;
115
+ color: var(--el-text-color-regular);
116
+ position: relative;
117
+ font-size: 14px;
118
+ }
119
+
120
+ .#{a.$prefix}-nav-tabs-item--active {
121
+ color: var(--el-color-primary);
122
+ font-weight: 500;
123
+
124
+ &::after {
125
+ content: '';
126
+ position: absolute;
127
+ left: 16px;
128
+ right: 16px;
129
+ bottom: 0;
130
+ height: 2px;
131
+ background: var(--el-color-primary);
132
+ }
133
+ }
134
+
135
+ .#{a.$prefix}-nav-tabs-item--disabled {
136
+ color: var(--el-text-color-disabled);
137
+ cursor: not-allowed;
138
+ }
139
+ }
140
+ }
141
+
142
+ .#{a.$prefix}-nav-tabs--custom {
143
+ .#{a.$prefix}-nav-tabs__scroll {
144
+ gap: 8px;
145
+ }
146
+
147
+ .#{a.$prefix}-nav-tabs-item {
148
+ padding: 0;
149
+ height: auto;
150
+ line-height: inherit;
151
+ }
152
+ }
153
+
154
+ .#{a.$prefix}-nav-tabs-item {
155
+ flex-shrink: 0;
156
+ cursor: pointer;
157
+ user-select: none;
158
+ height: 100%;
159
+ display: flex;
160
+ justify-content: center;
161
+ align-items: center;
162
+ position: relative;
163
+ }
164
+ </style>
@@ -0,0 +1,13 @@
1
+ export type NavTabItem = {
2
+ label: string
3
+ value: string | number
4
+ disabled?: boolean
5
+ [key: string]: unknown
6
+ }
7
+
8
+ export interface NavTabsProps {
9
+ data?: NavTabItem[]
10
+ wheelSpeed?: number
11
+ /** 自定义项样式:无 padding,不应用 --active / --disabled 修饰类 */
12
+ custom?: boolean
13
+ }
@@ -1,33 +1,34 @@
1
- /* eslint-disable */
2
- // @ts-nocheck
3
- // Generated by unplugin-vue-components
4
- // Read more: https://github.com/vuejs/core/pull/3399
5
- // biome-ignore lint: disable
6
- export {}
7
-
8
- /* prettier-ignore */
9
- declare module 'vue' {
10
- export interface GlobalComponents {
11
- GiButton: typeof import('./components/button/src/button.vue')['default']
12
- GiCard: typeof import('./components/card/src/card.vue')['default']
13
- GiDescriptions: typeof import('./components/descriptions/src/descriptions.vue')['default']
14
- GiDialog: typeof import('./components/dialog/src/dialog.vue')['default']
15
- GiDialogContent: typeof import('./components/dialog/src/dialog-content.vue')['default']
16
- GiDot: typeof import('./components/dot/src/dot.vue')['default']
17
- GiDrawer: typeof import('./components/drawer/src/drawer.vue')['default']
18
- GiEditTable: typeof import('./components/edit-table/src/edit-table.vue')['default']
19
- GiFlex: typeof import('./components/flex/src/flex.vue')['default']
20
- GiForm: typeof import('./components/form/src/form.vue')['default']
21
- GiGrid: typeof import('./components/grid/src/grid.vue')['default']
22
- GiGridItem: typeof import('./components/grid/src/grid-item.vue')['default']
23
- GiInputGroup: typeof import('./components/input-group/src/input-group.vue')['default']
24
- GiInputSearch: typeof import('./components/input-search/src/input-search.vue')['default']
25
- GiPageLayout: typeof import('./components/page-layout/src/page-layout.vue')['default']
26
- GiSplitButton: typeof import('./components/page-layout/src/split-button.vue')['default']
27
- GiTable: typeof import('./components/table/src/table.vue')['default']
28
- GiTableColumn: typeof import('./components/table/src/TableColumn.vue')['default']
29
- GiTabs: typeof import('./components/tabs/src/tabs.vue')['default']
30
- GiTag: typeof import('./components/tag/src/tag.vue')['default']
31
- GiTreeTransfer: typeof import('./components/tree-transfer/src/tree-transfer.vue')['default']
32
- }
33
- }
1
+ /* eslint-disable */
2
+ // @ts-nocheck
3
+ // Generated by unplugin-vue-components
4
+ // Read more: https://github.com/vuejs/core/pull/3399
5
+ // biome-ignore lint: disable
6
+ export {}
7
+
8
+ /* prettier-ignore */
9
+ declare module 'vue' {
10
+ export interface GlobalComponents {
11
+ GiButton: typeof import('./components/button/src/button.vue')['default']
12
+ GiCard: typeof import('./components/card/src/card.vue')['default']
13
+ GiDescriptions: typeof import('./components/descriptions/src/descriptions.vue')['default']
14
+ GiDialog: typeof import('./components/dialog/src/dialog.vue')['default']
15
+ GiDialogContent: typeof import('./components/dialog/src/dialog-content.vue')['default']
16
+ GiDot: typeof import('./components/dot/src/dot.vue')['default']
17
+ GiDrawer: typeof import('./components/drawer/src/drawer.vue')['default']
18
+ GiEditTable: typeof import('./components/edit-table/src/edit-table.vue')['default']
19
+ GiFlex: typeof import('./components/flex/src/flex.vue')['default']
20
+ GiForm: typeof import('./components/form/src/form.vue')['default']
21
+ GiGrid: typeof import('./components/grid/src/grid.vue')['default']
22
+ GiGridItem: typeof import('./components/grid/src/grid-item.vue')['default']
23
+ GiInputGroup: typeof import('./components/input-group/src/input-group.vue')['default']
24
+ GiInputSearch: typeof import('./components/input-search/src/input-search.vue')['default']
25
+ GiNavTabs: typeof import('./components/nav-tabs/src/nav-tabs.vue')['default']
26
+ GiPageLayout: typeof import('./components/page-layout/src/page-layout.vue')['default']
27
+ GiSplitButton: typeof import('./components/page-layout/src/split-button.vue')['default']
28
+ GiTable: typeof import('./components/table/src/table.vue')['default']
29
+ GiTableColumn: typeof import('./components/table/src/TableColumn.vue')['default']
30
+ GiTabs: typeof import('./components/tabs/src/tabs.vue')['default']
31
+ GiTag: typeof import('./components/tag/src/tag.vue')['default']
32
+ GiTreeTransfer: typeof import('./components/tree-transfer/src/tree-transfer.vue')['default']
33
+ }
34
+ }
@@ -1 +1,2 @@
1
1
  export * from './useBemClass'
2
+ export * from './useNavTabs'
@@ -0,0 +1,275 @@
1
+ import type { MaybeRefOrGetter } from 'vue'
2
+ import {
3
+ getCurrentInstance,
4
+ nextTick,
5
+ onMounted,
6
+ onUnmounted,
7
+ toRef,
8
+ toValue,
9
+ watch
10
+ } from 'vue'
11
+
12
+ export interface UseNavTabsOptions {
13
+ /** 根容器:选择器(.tab)或 HTMLElement / Ref */
14
+ tabEl: MaybeRefOrGetter<string | HTMLElement | null>
15
+ /** 滚动容器:类名 tab__scroll 或 .tab__scroll 或 HTMLElement */
16
+ tabScrollEl: MaybeRefOrGetter<string | HTMLElement | null>
17
+ /** tab 项 class,如 tab-item */
18
+ tabItemClassName: string
19
+ /** 当前选中值;变化时自动居中(推荐传入) */
20
+ activeValue?: MaybeRefOrGetter<string | number | undefined>
21
+ /** 滚轮换算系数,默认 1 */
22
+ wheelSpeed?: number
23
+ }
24
+
25
+ export interface UseNavTabsReturn {
26
+ /** 滚动到当前选中项并居中 */
27
+ scrollToActive: (behavior?: ScrollBehavior) => void
28
+ /** 获取解析后的滚动容器 */
29
+ getScrollEl: () => HTMLElement | null
30
+ }
31
+
32
+ function normalizeSelector(value: string): string {
33
+ if (value.startsWith('.') || value.startsWith('#')) {
34
+ return value
35
+ }
36
+ return `.${value}`
37
+ }
38
+
39
+ function resolveElement(
40
+ target: string | HTMLElement | null | undefined,
41
+ root?: HTMLElement | Document | null
42
+ ): HTMLElement | null {
43
+ if (!target) {
44
+ return null
45
+ }
46
+ if (typeof target !== 'string') {
47
+ return target
48
+ }
49
+ const scope = root ?? document
50
+ return scope.querySelector(normalizeSelector(target))
51
+ }
52
+
53
+ /** 滚轮平滑插值系数,越大跟手越快 */
54
+ const WHEEL_SCROLL_LERP = 0.4
55
+ const WHEEL_LINE_HEIGHT = 16
56
+
57
+ function getWheelPixelDelta(event: WheelEvent, scrollEl: HTMLElement): number {
58
+ let delta = Math.abs(event.deltaX) > Math.abs(event.deltaY)
59
+ ? event.deltaX
60
+ : event.deltaY
61
+
62
+ if (event.deltaMode === WheelEvent.DOM_DELTA_LINE) {
63
+ delta *= WHEEL_LINE_HEIGHT
64
+ } else if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
65
+ delta *= scrollEl.clientWidth
66
+ }
67
+
68
+ return delta
69
+ }
70
+
71
+ function clampScrollLeft(scrollEl: HTMLElement, left: number): number {
72
+ const maxScroll = Math.max(0, scrollEl.scrollWidth - scrollEl.clientWidth)
73
+ return Math.max(0, Math.min(left, maxScroll))
74
+ }
75
+
76
+ function scrollItemToCenter(
77
+ scrollEl: HTMLElement,
78
+ activeEl: HTMLElement,
79
+ behavior: ScrollBehavior = 'smooth'
80
+ ) {
81
+ const maxScroll = scrollEl.scrollWidth - scrollEl.clientWidth
82
+ if (maxScroll <= 0) {
83
+ return
84
+ }
85
+
86
+ // 使用视口坐标计算,兼容 flex gap / margin 等间距,避免 offsetLeft 偏差
87
+ const scrollRect = scrollEl.getBoundingClientRect()
88
+ const activeRect = activeEl.getBoundingClientRect()
89
+ const activeLeftInContent = activeRect.left - scrollRect.left + scrollEl.scrollLeft
90
+ const target = activeLeftInContent - (scrollEl.clientWidth - activeRect.width) / 2
91
+
92
+ scrollEl.scrollTo({
93
+ left: Math.max(0, Math.min(target, maxScroll)),
94
+ behavior
95
+ })
96
+ }
97
+
98
+ export function useNavTabs(options: UseNavTabsOptions): UseNavTabsReturn {
99
+ const {
100
+ tabEl,
101
+ tabScrollEl,
102
+ tabItemClassName,
103
+ activeValue,
104
+ wheelSpeed = 1
105
+ } = options
106
+
107
+ const activeClassName = `${tabItemClassName}--active`
108
+ const itemSelector = normalizeSelector(tabItemClassName)
109
+
110
+ let rootEl: HTMLElement | null = null
111
+ let scrollEl: HTMLElement | null = null
112
+ let resizeObserver: ResizeObserver | null = null
113
+ let wheelRafId: number | null = null
114
+ let wheelTargetScrollLeft = 0
115
+
116
+ const cancelWheelAnimation = () => {
117
+ if (wheelRafId !== null) {
118
+ cancelAnimationFrame(wheelRafId)
119
+ wheelRafId = null
120
+ }
121
+ }
122
+
123
+ const runWheelAnimation = () => {
124
+ if (!scrollEl) {
125
+ cancelWheelAnimation()
126
+ return
127
+ }
128
+
129
+ const current = scrollEl.scrollLeft
130
+ const diff = wheelTargetScrollLeft - current
131
+
132
+ if (Math.abs(diff) < 0.5) {
133
+ scrollEl.scrollLeft = wheelTargetScrollLeft
134
+ cancelWheelAnimation()
135
+ return
136
+ }
137
+
138
+ scrollEl.scrollLeft = current + diff * WHEEL_SCROLL_LERP
139
+ wheelRafId = requestAnimationFrame(runWheelAnimation)
140
+ }
141
+
142
+ const resolveElements = () => {
143
+ const instanceRoot = getCurrentInstance()?.proxy?.$el as HTMLElement | undefined
144
+ const fallbackRoot = instanceRoot instanceof HTMLElement ? instanceRoot : document
145
+
146
+ rootEl = resolveElement(toValue(tabEl), fallbackRoot)
147
+ scrollEl = resolveElement(toValue(tabScrollEl), rootEl ?? fallbackRoot)
148
+
149
+ return Boolean(rootEl && scrollEl)
150
+ }
151
+
152
+ const findActiveItem = (): HTMLElement | null => {
153
+ if (!scrollEl) {
154
+ return null
155
+ }
156
+
157
+ const activeByClass = scrollEl.querySelector(normalizeSelector(activeClassName))
158
+ if (activeByClass instanceof HTMLElement) {
159
+ return activeByClass
160
+ }
161
+
162
+ const value = activeValue !== undefined ? toValue(activeValue) : undefined
163
+ if (value === undefined) {
164
+ return null
165
+ }
166
+
167
+ const items = scrollEl.querySelectorAll<HTMLElement>(itemSelector)
168
+ const matched = Array.from(items).find((item) => item.dataset.value === String(value))
169
+ return matched ?? null
170
+ }
171
+
172
+ const scrollToActive = (behavior: ScrollBehavior = 'smooth') => {
173
+ if (!scrollEl) {
174
+ return
175
+ }
176
+ cancelWheelAnimation()
177
+ const activeItem = findActiveItem()
178
+ if (activeItem) {
179
+ scrollItemToCenter(scrollEl, activeItem, behavior)
180
+ }
181
+ }
182
+
183
+ const handleWheel = (event: WheelEvent) => {
184
+ if (!scrollEl) {
185
+ return
186
+ }
187
+
188
+ const delta = getWheelPixelDelta(event, scrollEl)
189
+ if (delta === 0) {
190
+ return
191
+ }
192
+
193
+ event.preventDefault()
194
+
195
+ if (wheelRafId === null) {
196
+ wheelTargetScrollLeft = scrollEl.scrollLeft
197
+ }
198
+
199
+ wheelTargetScrollLeft = clampScrollLeft(
200
+ scrollEl,
201
+ wheelTargetScrollLeft + delta * wheelSpeed
202
+ )
203
+
204
+ if (wheelRafId === null) {
205
+ wheelRafId = requestAnimationFrame(runWheelAnimation)
206
+ }
207
+ }
208
+
209
+ const bindWheel = () => {
210
+ scrollEl?.addEventListener('wheel', handleWheel, { passive: false })
211
+ }
212
+
213
+ const unbindWheel = () => {
214
+ scrollEl?.removeEventListener('wheel', handleWheel)
215
+ cancelWheelAnimation()
216
+ }
217
+
218
+ const bindResizeObserver = () => {
219
+ if (!scrollEl || typeof ResizeObserver === 'undefined') {
220
+ return
221
+ }
222
+
223
+ resizeObserver = new ResizeObserver(() => {
224
+ scrollToActive('auto')
225
+ })
226
+ resizeObserver.observe(scrollEl)
227
+ }
228
+
229
+ const unbindResizeObserver = () => {
230
+ resizeObserver?.disconnect()
231
+ resizeObserver = null
232
+ }
233
+
234
+ const setup = async () => {
235
+ await nextTick()
236
+ if (!resolveElements()) {
237
+ return
238
+ }
239
+ bindWheel()
240
+ bindResizeObserver()
241
+ scrollToActive('auto')
242
+ }
243
+
244
+ onMounted(() => {
245
+ setup()
246
+ })
247
+
248
+ watch(
249
+ () => [toValue(tabEl), toValue(tabScrollEl)] as const,
250
+ () => {
251
+ unbindWheel()
252
+ unbindResizeObserver()
253
+ setup()
254
+ }
255
+ )
256
+
257
+ if (activeValue !== undefined) {
258
+ watch(toRef(activeValue), () => {
259
+ nextTick(() => scrollToActive())
260
+ })
261
+ }
262
+
263
+ onUnmounted(() => {
264
+ unbindWheel()
265
+ unbindResizeObserver()
266
+ cancelWheelAnimation()
267
+ rootEl = null
268
+ scrollEl = null
269
+ })
270
+
271
+ return {
272
+ scrollToActive,
273
+ getScrollEl: () => scrollEl
274
+ }
275
+ }
package/packages/index.ts CHANGED
@@ -13,6 +13,7 @@ import GridItem from './components/grid/src/grid-item.vue'
13
13
  import Grid from './components/grid/src/grid.vue'
14
14
  import InputGroup from './components/input-group'
15
15
  import InputSearch from './components/input-search'
16
+ import NavTabs from './components/nav-tabs'
16
17
  import PageLayout from './components/page-layout'
17
18
  import Table from './components/table'
18
19
  import Tabs from './components/tabs'
@@ -28,6 +29,7 @@ export * from './components/dialog'
28
29
  export * from './components/drawer'
29
30
  export * from './components/edit-table'
30
31
  export * from './components/form'
32
+ export * from './components/nav-tabs'
31
33
  export * from './components/table'
32
34
  export * from './components/tabs'
33
35
  export * from './components/tag'
@@ -43,6 +45,7 @@ const components = {
43
45
  Tabs,
44
46
  InputGroup,
45
47
  InputSearch,
48
+ NavTabs,
46
49
  Flex,
47
50
  Grid,
48
51
  GridItem,
@@ -64,6 +67,7 @@ export const GiDot: typeof Dot = Dot
64
67
  export const GiTabs: typeof Tabs = Tabs
65
68
  export const GiInputGroup: typeof InputGroup = InputGroup
66
69
  export const GiInputSearch: typeof InputSearch = InputSearch
70
+ export const GiNavTabs: typeof NavTabs = NavTabs
67
71
  export const GiFlex: typeof Flex = Flex
68
72
  export const GiGrid: typeof Grid = Grid
69
73
  export const GiGridItem: typeof GridItem = GridItem