@mtn-ui-z/utils 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # @mtn-ui-z/utils
2
+
3
+ MTN UI 工具函数包,基于 VueUse 构建。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ pnpm add @mtn-ui-z/utils @vueuse/core
9
+ ```
10
+
11
+ ## 目录结构
12
+
13
+ ```
14
+ packages/utils/src/
15
+ ├── common.ts # 通用工具函数
16
+ ├── function.ts # 函数工具(防抖、节流)
17
+ ├── state.ts # 状态管理工具
18
+ ├── dom.ts # DOM 操作工具
19
+ ├── interaction.ts # 交互工具(鼠标、滚动等)
20
+ ├── media.ts # 媒体查询工具
21
+ ├── types.ts # 类型定义
22
+ └── index.ts # 主入口(重新导出所有内容)
23
+ ```
24
+
25
+ ## 功能分类
26
+
27
+ ### 通用工具 (`common.ts`)
28
+
29
+ - `classNames` - 格式化类名
30
+
31
+ ### 函数工具 (`function.ts`)
32
+
33
+ - `useDebounceFn` - 防抖函数
34
+ - `useThrottleFn` - 节流函数
35
+
36
+ ### 状态管理 (`state.ts`)
37
+
38
+ 本包重新导出了 VueUse 的状态管理函数,包括:
39
+
40
+ - `useToggle` - 切换布尔值
41
+ - `useCounter` - 计数器
42
+ - `useLocalStorage` - 本地存储
43
+ - `useSessionStorage` - 会话存储
44
+
45
+ ### DOM 操作 (`dom.ts`)
46
+
47
+ - `onClickOutside` - 点击外部区域
48
+ - `useEventListener` - 事件监听
49
+ - `useElementSize` - 元素尺寸
50
+ - `useResizeObserver` - 尺寸观察
51
+ - `useFocus` - 焦点管理
52
+ - `useHover` - 悬停状态
53
+ - `useClipboard` - 剪贴板操作
54
+
55
+ ### 交互工具 (`interaction.ts`)
56
+
57
+ - `useMouse` - 鼠标位置
58
+ - `useScroll` - 滚动位置
59
+ - `useWindowSize` - 窗口尺寸
60
+
61
+ ### 媒体查询 (`media.ts`)
62
+
63
+ - `useMediaQuery` - 媒体查询
64
+ - `usePreferredDark` - 系统暗色偏好
65
+ - `useDark` - 暗色模式
66
+ - `useColorMode` - 颜色模式
67
+
68
+ ## 使用方式
69
+
70
+ ### 全量导入(推荐)
71
+
72
+ ```typescript
73
+ import { classNames, useDebounceFn, useToggle } from '@mtn-ui-z/utils'
74
+ ```
75
+
76
+ ### 按分类导入
77
+
78
+ ```typescript
79
+ // 通用工具
80
+ import { classNames } from '@mtn-ui-z/utils/common'
81
+
82
+ // 函数工具
83
+ import { useDebounceFn, useThrottleFn } from '@mtn-ui-z/utils/function'
84
+
85
+ // 状态管理
86
+ import { useToggle, useCounter } from '@mtn-ui-z/utils/state'
87
+
88
+ // DOM 操作
89
+ import { onClickOutside, useElementSize } from '@mtn-ui-z/utils/dom'
90
+
91
+ // 交互工具
92
+ import { useMouse, useScroll } from '@mtn-ui-z/utils/interaction'
93
+
94
+ // 媒体查询
95
+ import { useDark, useColorMode } from '@mtn-ui-z/utils/media'
96
+ ```
97
+
98
+ ### 主题与密度 (`theme.ts`)
99
+
100
+ 与 `@mtn-ui-z/theme` 的 CSS 变量、`data-theme`、`data-mtn-density` 对齐,并同步 Ant Design Vue `ConfigProvider` 的 `theme.token`:
101
+
102
+ - `initTheme` — 尽早调用;可从 `localStorage` 恢复亮/暗与密度
103
+ - `setThemePrimary` / `setThemeColors` / `setThemeMode` / `toggleThemeMode`
104
+ - `setDensityMode` / `toggleDensityMode` — 紧凑与舒适
105
+ - `antThemeConfigRef`、`themeModeRef`、`densityModeRef` — 供模板与 `ConfigProvider` 绑定
106
+
107
+ 接入顺序与层叠约定见 `@mtn-ui-z/theme` README 与文档站「自定义主题」。
108
+
109
+ ## 使用示例
110
+
111
+ ### 防抖和节流
112
+
113
+ ```typescript
114
+ import { useDebounceFn, useThrottleFn } from '@mtn-ui-z/utils'
115
+
116
+ // 防抖
117
+ const debouncedSearch = useDebounceFn((query: string) => {
118
+ console.log('Search:', query)
119
+ }, 300)
120
+
121
+ // 节流
122
+ const throttledScroll = useThrottleFn(() => {
123
+ console.log('Scrolled')
124
+ }, 100)
125
+ ```
126
+
127
+ ### 状态管理
128
+
129
+ ```typescript
130
+ import { useToggle, useCounter, useLocalStorage } from '@mtn-ui-z/utils'
131
+
132
+ // 切换状态
133
+ const [isOpen, toggle] = useToggle(false)
134
+
135
+ // 计数器
136
+ const { count, inc, dec, reset } = useCounter(0)
137
+
138
+ // 本地存储
139
+ const stored = useLocalStorage('key', 'default-value')
140
+ ```
141
+
142
+ ### DOM 操作
143
+
144
+ ```typescript
145
+ import { onClickOutside, useElementSize } from '@mtn-ui-z/utils'
146
+ import { ref } from 'vue'
147
+
148
+ const target = ref<HTMLElement>()
149
+
150
+ // 点击外部区域
151
+ onClickOutside(target, () => {
152
+ console.log('Clicked outside')
153
+ })
154
+
155
+ // 元素尺寸
156
+ const { width, height } = useElementSize(target)
157
+ ```
158
+
159
+ ## 更多文档
160
+
161
+ 查看 [VueUse 官方文档](https://vueuse.org/) 了解更多功能。
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@mtn-ui-z/utils",
3
+ "version": "0.0.1",
4
+ "description": "MTN UI Utils",
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "types": "./src/index.d.ts",
8
+ "files": [
9
+ "src"
10
+ ],
11
+ "peerDependencies": {
12
+ "vue": "^3.5.0",
13
+ "@vueuse/core": "^11.0.0"
14
+ },
15
+ "dependencies": {
16
+ "@vueuse/core": "^11.0.0",
17
+ "axios": "^1.7.0",
18
+ "dayjs": "^1.11.10"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ }
23
+ }
@@ -0,0 +1,3 @@
1
+ export function classNames(
2
+ ...classes: (string | undefined | null | false)[]
3
+ ): string
package/src/common.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 通用工具函数
3
+ */
4
+
5
+ /**
6
+ * 格式化类名
7
+ * 工具函数,用于合并多个类名
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * classNames('foo', 'bar', false, 'baz') // => 'foo bar baz'
12
+ * ```
13
+ */
14
+ export function classNames(...classes: (string | undefined | null | false)[]): string {
15
+ return classes.filter(Boolean).join(' ')
16
+ }
package/src/date.ts ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 日期格式化工具
3
+ */
4
+ import dayjs from 'dayjs'
5
+
6
+ /**
7
+ * 格式化日期(YYYY-MM-DD)
8
+ */
9
+ export function formatDate(value: unknown): string {
10
+ if (!value) return ''
11
+ const date = dayjs(value as string | number | Date)
12
+ if (!date.isValid()) return String(value)
13
+ return date.format('YYYY-MM-DD')
14
+ }
15
+
16
+ /**
17
+ * 格式化日期时间(YYYY-MM-DD HH:mm:ss)
18
+ */
19
+ export function formatDateTime(value: unknown): string {
20
+ if (!value) return ''
21
+ const date = dayjs(value as string | number | Date)
22
+ if (!date.isValid()) return String(value)
23
+ return date.format('YYYY-MM-DD HH:mm:ss')
24
+ }
25
+
26
+ /**
27
+ * 格式化年月(YYYY-MM)
28
+ */
29
+ export function formatYearMonth(value: unknown): string {
30
+ if (!value) return ''
31
+ const date = dayjs(value as string | number | Date)
32
+ if (!date.isValid()) return String(value)
33
+ return date.format('YYYY-MM')
34
+ }
package/src/dict.ts ADDED
@@ -0,0 +1,193 @@
1
+ /**
2
+ * 数据字典:通过接口获取,与 DictSelect 约定一致的字典项结构
3
+ */
4
+ import { ref, type Ref, inject, type InjectionKey } from 'vue'
5
+ import { request } from './request'
6
+ import type { Result } from './request-types'
7
+ import { getStorage, setStorage } from './storage'
8
+
9
+ /** 字典项结构(与 @mtn-ui-z/components DictSelect 一致) */
10
+ export interface DictItem {
11
+ dictLabel: string
12
+ dictValue: string
13
+ /** 颜色(如状态、标签场景下的展示色),可选 */
14
+ dictColor?: string
15
+ [key: string]: unknown
16
+ }
17
+
18
+ /** 请求字典的接口:传入多个 dictKey,返回各 key 对应的字典项数组(一个接口) */
19
+ export type FetchDictFn = (dictKeys: string[]) => Promise<Record<string, DictItem[]>>
20
+
21
+ const MOCK_MAP: Record<string, DictItem[]> = {
22
+ order_status: [
23
+ { dictLabel: '待支付', dictValue: '10' },
24
+ { dictLabel: '已支付', dictValue: '20' },
25
+ { dictLabel: '已取消', dictValue: '30' },
26
+ ],
27
+ pay_type: [
28
+ { dictLabel: '微信', dictValue: 'wx' },
29
+ { dictLabel: '支付宝', dictValue: 'alipay' },
30
+ ],
31
+ }
32
+
33
+ const DEFAULT_LIST: DictItem[] = [
34
+ { dictLabel: '选项一', dictValue: '1' },
35
+ { dictLabel: '选项二', dictValue: '2' },
36
+ ]
37
+
38
+ /** 默认假数据:一次传入多个 key,返回 key -> 字典项数组(暂无接口时使用) */
39
+ function defaultMockFetch(dictKeys: string[]): Promise<Record<string, DictItem[]>> {
40
+ const res: Record<string, DictItem[]> = {}
41
+ dictKeys.forEach(key => {
42
+ res[key] = MOCK_MAP[key] ?? DEFAULT_LIST
43
+ })
44
+ return Promise.resolve(res)
45
+ }
46
+
47
+ /** localStorage 的 key 前缀,与 DictSelect 的 storageKeyPrefix 一致时可直接用 dictType 读缓存 */
48
+ export const DEFAULT_DICT_STORAGE_PREFIX = 'dict_'
49
+
50
+ /** 字典全局配置(可在 App 初始化时 provide,useDict 会 inject 读取) */
51
+ export interface DictGlobalConfig {
52
+ /** 字典接口地址,传入则通过 request 请求该 URL(params: { keys }),响应需为 Result<Record<string, DictItem[]>> */
53
+ dictApiUrl?: string
54
+ /** 请求完成后是否写入 localStorage,默认 true */
55
+ storeInStorage?: boolean
56
+ /** localStorage key 前缀,默认 dict_ */
57
+ storageKeyPrefix?: string
58
+ }
59
+
60
+ /** 注入 key(用于 provide/inject) */
61
+ export const DICT_CONFIG_KEY: InjectionKey<DictGlobalConfig> = Symbol('dictConfig')
62
+
63
+ export interface UseDictOptions {
64
+ /** 字典接口地址,传入则通过 request 请求该 URL(params: { keys }),响应需为 Result<Record<string, DictItem[]>> */
65
+ dictApiUrl?: string
66
+ /** 自定义请求方法,优先级高于 dictApiUrl;不传且无 dictApiUrl 时用内置假数据 */
67
+ fetchDict?: FetchDictFn
68
+ /** 请求完成后是否写入 localStorage,默认 true;按「一个字典一个 key」存储(key = storageKeyPrefix + dictKey) */
69
+ storeInStorage?: boolean
70
+ /** localStorage key 前缀,默认 dict_,单条 key 如 dict_order_status */
71
+ storageKeyPrefix?: string
72
+ }
73
+
74
+ /**
75
+ * 按字典 key 列表调用一次接口获取多组字典,返回 key -> 字典项数组 的响应式对象。
76
+ * 用法:useDict(['order_status', 'pay_type']),返回的 ref 中 result.value.order_status 即为该 key 的 DictItem[]。
77
+ * 暂无接口时使用内置假数据;有接口后传入 fetchDict(dictKeys) 即可(接口入参为多个 key,出参为 Record<string, DictItem[]>)。
78
+ */
79
+ function fetchByRequest(dictApiUrl: string, keys: string[]): Promise<Record<string, DictItem[]>> {
80
+ return request
81
+ .post<Result<Record<string, DictItem[]>>>(dictApiUrl, { dict_code: keys })
82
+ .then(res => normalizeDictMap(res.data))
83
+ }
84
+
85
+ function normalizeDictItem(item: DictItem): DictItem {
86
+ return {
87
+ ...item,
88
+ dictLabel: String(item.dictLabel ?? item.dict_label ?? ''),
89
+ dictValue: String(item.dictValue ?? item.dict_value ?? ''),
90
+ dictColor:
91
+ typeof item.dictColor === 'string'
92
+ ? item.dictColor
93
+ : typeof item.dict_color === 'string'
94
+ ? item.dict_color
95
+ : undefined
96
+ }
97
+ }
98
+
99
+ function normalizeDictMap(data: Record<string, DictItem[]>): Record<string, DictItem[]> {
100
+ const normalized: Record<string, DictItem[]> = {}
101
+ Object.entries(data ?? {}).forEach(([dictKey, list]) => {
102
+ normalized[dictKey] = Array.isArray(list) ? list.map(item => normalizeDictItem(item)) : []
103
+ })
104
+ return normalized
105
+ }
106
+
107
+ /** 正在请求中的 promise(避免同一 key 并发重复请求) */
108
+ const pendingRequests = new Map<string, Promise<Record<string, DictItem[]>>>()
109
+
110
+ export function useDict(
111
+ keys: string[],
112
+ options: UseDictOptions = {}
113
+ ): Ref<Record<string, DictItem[]>> {
114
+ const result = ref<Record<string, DictItem[]>>({}) as Ref<Record<string, DictItem[]>>
115
+
116
+ // 读取全局配置(App 级别 provide 的),局部 options 优先级更高
117
+ const globalConfig = inject(DICT_CONFIG_KEY, {})
118
+ const dictApiUrl = options.dictApiUrl ?? globalConfig.dictApiUrl
119
+ const storeInStorage = options.storeInStorage ?? globalConfig.storeInStorage ?? true
120
+ const prefix =
121
+ options.storageKeyPrefix ?? globalConfig.storageKeyPrefix ?? DEFAULT_DICT_STORAGE_PREFIX
122
+
123
+ // 根据配置决定请求方式:局部 fetchDict > 全局 dictApiUrl > 内置 mock
124
+ const fetchDict =
125
+ options.fetchDict ??
126
+ (dictApiUrl ? (dictKeys: string[]) => fetchByRequest(dictApiUrl, dictKeys) : defaultMockFetch)
127
+
128
+ // 优先从 localStorage 读取已有缓存,减少不必要的请求
129
+ const cachedResult: Record<string, DictItem[]> = {}
130
+ const missingKeys: string[] = []
131
+
132
+ for (const key of keys) {
133
+ const cached = getStorage<DictItem[]>(prefix + key)
134
+ if (cached !== undefined && cached.length > 0) {
135
+ cachedResult[key] = cached.map(item => normalizeDictItem(item))
136
+ } else {
137
+ missingKeys.push(key)
138
+ }
139
+ }
140
+
141
+ // 已有缓存的处理
142
+ if (Object.keys(cachedResult).length > 0) {
143
+ result.value = cachedResult
144
+ }
145
+
146
+ // 全部命中缓存,无需请求
147
+ if (missingKeys.length === 0) {
148
+ return result
149
+ }
150
+
151
+ // 构造新请求,并缓存 promise 引用(按 sorted keys 做去重)
152
+ const pendingKey = missingKeys.sort().join(',')
153
+ const existingPending = pendingRequests.get(pendingKey)
154
+
155
+ if (existingPending) {
156
+ existingPending
157
+ .then(data => {
158
+ const normalizedData = normalizeDictMap(data)
159
+ if (storeInStorage) {
160
+ Object.entries(normalizedData).forEach(([dictKey, list]) => {
161
+ setStorage(prefix + dictKey, list)
162
+ })
163
+ }
164
+ result.value = { ...result.value, ...normalizedData }
165
+ })
166
+ .catch(() => {
167
+ result.value = { ...result.value, ...Object.fromEntries(missingKeys.map(k => [k, []])) }
168
+ })
169
+ return result
170
+ }
171
+
172
+ const reqPromise = fetchDict(missingKeys)
173
+ pendingRequests.set(pendingKey, reqPromise)
174
+
175
+ reqPromise
176
+ .then(data => {
177
+ const normalizedData = normalizeDictMap(data)
178
+ result.value = { ...result.value, ...normalizedData }
179
+ if (storeInStorage) {
180
+ Object.entries(normalizedData).forEach(([dictKey, list]) => {
181
+ setStorage(prefix + dictKey, list)
182
+ })
183
+ }
184
+ })
185
+ .catch(() => {
186
+ result.value = { ...result.value, ...Object.fromEntries(missingKeys.map(k => [k, []])) }
187
+ })
188
+ .finally(() => {
189
+ pendingRequests.delete(pendingKey)
190
+ })
191
+
192
+ return result
193
+ }
package/src/dom.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export {
2
+ onClickOutside,
3
+ useEventListener,
4
+ useElementSize,
5
+ useResizeObserver,
6
+ useFocus,
7
+ useClipboard
8
+ } from '@vueuse/core'
package/src/dom.ts ADDED
@@ -0,0 +1,20 @@
1
+ /*
2
+ * @Author: liaokt
3
+ * @Description:
4
+ * @Date: 2026-01-21 10:19:31
5
+ * @LastEditors: liaokt
6
+ * @LastEditTime: 2026-01-26 16:09:27
7
+ */
8
+ /**
9
+ * DOM 操作工具
10
+ * 与 DOM 元素交互相关的工具函数
11
+ */
12
+
13
+ export {
14
+ onClickOutside,
15
+ useEventListener,
16
+ useElementSize,
17
+ useResizeObserver,
18
+ useFocus,
19
+ useClipboard
20
+ } from '@vueuse/core'
@@ -0,0 +1 @@
1
+ export { useDebounceFn, useThrottleFn } from '@vueuse/core'
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 函数工具
3
+ * 防抖、节流等函数处理工具
4
+ */
5
+
6
+ export {
7
+ useDebounceFn,
8
+ useThrottleFn
9
+ } from '@vueuse/core'
package/src/index.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @mtn-ui-z/utils 类型声明入口
3
+ * 供 package.json "types" 指向,避免部分环境下 TS 无法解析 node_modules 内 .ts
4
+ */
5
+ export * from './common'
6
+ export * from './function'
7
+ export * from './state'
8
+ export * from './storage'
9
+ export * from './dom'
10
+ export * from './interaction'
11
+ export * from './media'
12
+ export * from './permission'
13
+ export * from './theme'
14
+ export * from './dict'
15
+ export * from './request-types'
16
+ export {
17
+ createRequest,
18
+ request,
19
+ axiosInstance,
20
+ type CreateRequestOptions
21
+ } from './request'
22
+
23
+ // 表格状态管理
24
+ export * from './useTable'
25
+
26
+ // Modal 命令式调用
27
+ export * from './useModal'
28
+
29
+ // Modal 注册表
30
+ export * from './modalRegistry'
31
+
32
+ // 日期格式化
33
+ export * from './date'
34
+
35
+ // 类型定义
36
+ export * from './types'
package/src/index.ts ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * MTN UI Utils
3
+ *
4
+ * 基于 VueUse 的工具函数集合
5
+ *
6
+ * @module @mtn-ui-z/utils
7
+ */
8
+
9
+ // 通用工具
10
+ export * from './common'
11
+
12
+ // 函数工具
13
+ export * from './function'
14
+
15
+ // 状态管理
16
+ export * from './state'
17
+
18
+ // 本地/会话存储
19
+ export * from './storage'
20
+
21
+ // DOM 操作
22
+ export * from './dom'
23
+
24
+ // 交互工具
25
+ export * from './interaction'
26
+
27
+ // 媒体查询
28
+ export * from './media'
29
+
30
+ // 权限管理
31
+ export * from './permission'
32
+
33
+ // 主题色(运行时)
34
+ export * from './theme'
35
+
36
+ // 数据字典
37
+ export * from './dict'
38
+
39
+ // 请求与 API 类型
40
+ export * from './request-types'
41
+ export {
42
+ createRequest,
43
+ request,
44
+ axiosInstance,
45
+ type CreateRequestOptions
46
+ } from './request'
47
+
48
+ // 表格状态管理
49
+ export * from './useTable'
50
+
51
+ // Modal 命令式调用
52
+ export * from './useModal'
53
+
54
+ // Modal 注册表
55
+ export * from './modalRegistry'
56
+
57
+ // 日期格式化
58
+ export * from './date'
59
+
60
+ // 类型定义
61
+ export * from './types'
@@ -0,0 +1 @@
1
+ export { useMouse, useScroll, useWindowSize } from '@vueuse/core'
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 交互工具
3
+ * 鼠标、滚动、窗口等交互相关的工具函数
4
+ */
5
+
6
+ export {
7
+ useMouse,
8
+ useScroll,
9
+ useWindowSize
10
+ } from '@vueuse/core'
package/src/media.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export {
2
+ useMediaQuery,
3
+ usePreferredDark,
4
+ useDark,
5
+ useColorMode
6
+ } from '@vueuse/core'
package/src/media.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 媒体查询工具
3
+ * 媒体查询、主题、颜色模式相关的工具函数
4
+ */
5
+
6
+ export {
7
+ useMediaQuery,
8
+ usePreferredDark,
9
+ useDark,
10
+ useColorMode
11
+ } from '@vueuse/core'
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Modal 注册表
3
+ * 存储已注册的 Modal 组件定义,供 MxModalProvider 渲染使用
4
+ */
5
+ import type { Component } from 'vue'
6
+
7
+ /** Modal 组件注册项 */
8
+ interface ModalRegistryItem {
9
+ component: Component
10
+ }
11
+
12
+ const registry = new Map<string, ModalRegistryItem>()
13
+
14
+ export const ModalRegistry = {
15
+ /**
16
+ * 注册一个 Modal 组件
17
+ * @param id 唯一标识
18
+ * @param component Vue 组件
19
+ */
20
+ register(id: string, component: Component) {
21
+ registry.set(id, { component })
22
+ },
23
+
24
+ /**
25
+ * 注销一个 Modal 组件
26
+ */
27
+ unregister(id: string) {
28
+ registry.delete(id)
29
+ },
30
+
31
+ /**
32
+ * 根据 id 获取已注册的组件
33
+ */
34
+ get(id: string): Component | undefined {
35
+ return registry.get(id)?.component
36
+ }
37
+ }
@@ -0,0 +1,27 @@
1
+ import type { InjectionKey, Ref, MaybeRefOrGetter, ComputedRef } from 'vue'
2
+
3
+ export type PermissionChecker = (permission: string | string[]) => boolean
4
+ export type PermissionAction = 'hide' | 'disable'
5
+
6
+ export const defaultPermissionChecker: PermissionChecker
7
+ export const PERMISSION_CHECKER_KEY: InjectionKey<Ref<PermissionChecker>>
8
+ export const USER_PERMISSIONS_KEY: InjectionKey<Ref<string[]>>
9
+
10
+ export function createPermissionChecker(permissions: Ref<string[]>): PermissionChecker
11
+ export function hasPermission(
12
+ userPermissions: string[],
13
+ requiredPermission: string | string[]
14
+ ): boolean
15
+
16
+ export interface UsePermissionOptions {
17
+ permission?: MaybeRefOrGetter<string | string[] | undefined>
18
+ permissionAction?: MaybeRefOrGetter<PermissionAction | undefined>
19
+ }
20
+
21
+ export interface UsePermissionReturn {
22
+ hasPermission: ComputedRef<boolean>
23
+ shouldHide: ComputedRef<boolean>
24
+ shouldDisable: ComputedRef<boolean>
25
+ }
26
+
27
+ export function usePermission(options: UsePermissionOptions): UsePermissionReturn