v-dict 2.0.3 → 2.0.4

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 CHANGED
@@ -5,7 +5,12 @@
5
5
  * @Description:
6
6
  -->
7
7
 
8
- # Vue3 Dict Manager
8
+ # Vue3 & React Dict Manager
9
+
10
+ ## 目录
11
+
12
+ - [Vue](#vue)
13
+ - [React](#react)
9
14
 
10
15
  ## Installation
11
16
 
@@ -13,7 +18,7 @@
13
18
  npm i v-dict
14
19
  ```
15
20
 
16
- ## Examples
21
+ ## Vue
17
22
 
18
23
  ### dict.ts
19
24
 
@@ -147,3 +152,85 @@ onMounted(async () => {
147
152
  })
148
153
  </script>
149
154
  ```
155
+
156
+ ## React
157
+
158
+ ### dict.ts
159
+
160
+ ```ts
161
+ import { createDictManager, defineDictData } from 'v-dict/react'
162
+
163
+ export const dm = createDictManager({
164
+ fetch: (code) =>
165
+ Promise.resolve([
166
+ { label: 'xx', value: 'xx' },
167
+ { label: 'xx', value: 'xx' }
168
+ ]),
169
+ extra: ({ map }) => {
170
+ return {
171
+ getLabel: (value: string) => map[value]?.label
172
+ }
173
+ }
174
+ })
175
+
176
+ export const useStatusDict = dm.defineDict('STATUS', {
177
+ data: defineDictData({
178
+ ENABLED: {
179
+ label: 'Enabled',
180
+ color: 'green'
181
+ },
182
+ DISABLED: {
183
+ label: 'Disabled',
184
+ color: 'red'
185
+ }
186
+ })
187
+ })
188
+
189
+ export const useRemoteStatusDict = dm.defineDict('REMOTE_STATUS', {
190
+ remote: true,
191
+ fetch: (code) =>
192
+ Promise.resolve([
193
+ { label: 'Enabled', value: 'ENABLED', color: 'green' },
194
+ { label: 'Disabled', value: 'DISABLED', color: 'red' }
195
+ ]),
196
+ extra: ({ map }) => {
197
+ return {
198
+ getItemDetail: (value: string) => map[value]
199
+ }
200
+ }
201
+ })
202
+
203
+ // clear one dict
204
+ // dm.clear('REMOTE_STATUS')
205
+
206
+ // clear all dicts
207
+ // dm.clear()
208
+ ```
209
+
210
+ ### xx.tsx
211
+
212
+ ```tsx
213
+ import { useEffect } from 'react'
214
+ import { useRemoteStatusDict } from './dict'
215
+
216
+ export default function Demo() {
217
+ const statusDict = useRemoteStatusDict({
218
+ // same as above
219
+ clone: false,
220
+ // same as above
221
+ immediate: true,
222
+ // same as above
223
+ refresh: false
224
+ })
225
+
226
+ return (
227
+ <div>
228
+ <div>{E.ENABLED}</div>
229
+ <div>{map[E.ENABLED]?.label}</div>
230
+ <div>{statusDict.getLabel(E.ENABLED)}</div>
231
+ <div>{statusDict.getItem(E.DISABLED)?.color}</div>
232
+ <div>{list.length}</div>
233
+ </div>
234
+ )
235
+ }
236
+ ```
@@ -0,0 +1,8 @@
1
+ export type Resolve<T> = (value: T | PromiseLike<T>) => void;
2
+ export type Reject = (reason?: any) => void;
3
+ export type CreatePromiseReturn<T> = Promise<T> & {
4
+ resolve: Resolve<T>;
5
+ reject: Reject;
6
+ isPending: boolean;
7
+ };
8
+ export declare function createPromise<T = any>(executor?: (resolve: Resolve<T>, reject: Reject) => void): CreatePromiseReturn<T>;
@@ -0,0 +1 @@
1
+ export * from './vue';
@@ -143,10 +143,11 @@ function createDictManager(createDictManagerOptions = {}) {
143
143
  const listenersMap = /* @__PURE__ */ Object.create(null);
144
144
  function emitChange(code) {
145
145
  var _a;
146
- const listeners = code ? (_a = listenersMap[code]) != null ? _a : [] : Object.values(listenersMap).flat();
147
- for (let listener of listeners) {
148
- listener();
149
- }
146
+ const listeners = code ? (_a = listenersMap[code]) != null ? _a : /* @__PURE__ */ new Set() : Object.values(listenersMap).reduce((acc, set) => {
147
+ set.forEach((listener) => acc.add(listener));
148
+ return acc;
149
+ }, /* @__PURE__ */ new Set());
150
+ listeners.forEach((listener) => listener());
150
151
  }
151
152
  function clear(code) {
152
153
  var _a;
@@ -197,9 +198,10 @@ function createDictManager(createDictManagerOptions = {}) {
197
198
  }
198
199
  function subscribeMap(listener) {
199
200
  var _a;
200
- listenersMap[code] = [...(_a = listenersMap[code]) != null ? _a : [], listener];
201
+ (_a = listenersMap[code]) != null ? _a : listenersMap[code] = /* @__PURE__ */ new Set();
202
+ listenersMap[code].add(listener);
201
203
  return () => {
202
- listenersMap[code] = listenersMap[code].filter((l) => l !== listener);
204
+ listenersMap[code].delete(listener);
203
205
  };
204
206
  }
205
207
  function getMapSnapshot() {
@@ -239,11 +241,12 @@ function createDictManager(createDictManagerOptions = {}) {
239
241
  const loadPromiseRef = react.useRef(
240
242
  !clone ? globalLoadPromise : createPromise()
241
243
  );
242
- const map = react.useSyncExternalStore(subscribeMap, getMapSnapshot);
244
+ const globalMap = react.useSyncExternalStore(subscribeMap, getMapSnapshot);
243
245
  const [clonedMap, setClonedMap] = react.useState(/* @__PURE__ */ new Map());
246
+ const map = !clone ? globalMap : clonedMap;
244
247
  const state = react.useMemo(
245
- () => createStateFromMap(!clone ? map : clonedMap),
246
- [clone, map, clonedMap]
248
+ () => createStateFromMap(map),
249
+ [map]
247
250
  );
248
251
  const load = react.useCallback((options) => {
249
252
  const oldLoadPromise = loadPromiseRef.current;
@@ -0,0 +1,3 @@
1
+ export type * from '../types';
2
+ export * from './react-dict-manager';
3
+ export { defineDictData } from '../util';
@@ -14,10 +14,11 @@ function createDictManager(createDictManagerOptions = {}) {
14
14
  const listenersMap = /* @__PURE__ */ Object.create(null);
15
15
  function emitChange(code) {
16
16
  var _a;
17
- const listeners = code ? (_a = listenersMap[code]) != null ? _a : [] : Object.values(listenersMap).flat();
18
- for (let listener of listeners) {
19
- listener();
20
- }
17
+ const listeners = code ? (_a = listenersMap[code]) != null ? _a : /* @__PURE__ */ new Set() : Object.values(listenersMap).reduce((acc, set) => {
18
+ set.forEach((listener) => acc.add(listener));
19
+ return acc;
20
+ }, /* @__PURE__ */ new Set());
21
+ listeners.forEach((listener) => listener());
21
22
  }
22
23
  function clear(code) {
23
24
  var _a;
@@ -68,9 +69,10 @@ function createDictManager(createDictManagerOptions = {}) {
68
69
  }
69
70
  function subscribeMap(listener) {
70
71
  var _a;
71
- listenersMap[code] = [...(_a = listenersMap[code]) != null ? _a : [], listener];
72
+ (_a = listenersMap[code]) != null ? _a : listenersMap[code] = /* @__PURE__ */ new Set();
73
+ listenersMap[code].add(listener);
72
74
  return () => {
73
- listenersMap[code] = listenersMap[code].filter((l) => l !== listener);
75
+ listenersMap[code].delete(listener);
74
76
  };
75
77
  }
76
78
  function getMapSnapshot() {
@@ -110,11 +112,12 @@ function createDictManager(createDictManagerOptions = {}) {
110
112
  const loadPromiseRef = useRef(
111
113
  !clone ? globalLoadPromise : createPromise()
112
114
  );
113
- const map = useSyncExternalStore(subscribeMap, getMapSnapshot);
115
+ const globalMap = useSyncExternalStore(subscribeMap, getMapSnapshot);
114
116
  const [clonedMap, setClonedMap] = useState(/* @__PURE__ */ new Map());
117
+ const map = !clone ? globalMap : clonedMap;
115
118
  const state = useMemo(
116
- () => createStateFromMap(!clone ? map : clonedMap),
117
- [clone, map, clonedMap]
119
+ () => createStateFromMap(map),
120
+ [map]
118
121
  );
119
122
  const load = useCallback((options) => {
120
123
  const oldLoadPromise = loadPromiseRef.current;
@@ -0,0 +1,6 @@
1
+ import type { CreateDictManagerOptions, DefineDict, DictMap, ExtraGetter, Fetch, Recordable } from '../types';
2
+ export declare function createDictManager<E extends ExtraGetter, F extends Fetch>(createDictManagerOptions?: CreateDictManagerOptions<E, F>): {
3
+ defineDict: DefineDict<E, F>;
4
+ clear: (code?: string) => void;
5
+ maps: Recordable<DictMap>;
6
+ };
@@ -0,0 +1,69 @@
1
+ import type { createPromise } from '../create-promise';
2
+ import type { Merge, MergeValues } from './merge';
3
+ import type { AnyFn, MaybeGetter, MaybePromise, Nil, OptionalRequired, Recordable, Simplify } from './tool';
4
+ export type DictValue = number | string;
5
+ export type DictItem = {
6
+ label: string;
7
+ value: DictValue;
8
+ };
9
+ export type DictItemRecord = DictItem & Recordable;
10
+ export type DictMap = Map<DictValue, DictItemRecord>;
11
+ export type LoadPromise = ReturnType<typeof createPromise<void>>;
12
+ export type Dict<K extends PropertyKey = PropertyKey, I extends Recordable = DictItem, O extends Recordable = Recordable> = {
13
+ list: I[];
14
+ E: {
15
+ [X in K]: X;
16
+ };
17
+ map: {
18
+ [X in K]: I;
19
+ };
20
+ loadPromise: LoadPromise;
21
+ load: (options?: O) => LoadPromise;
22
+ clear: () => void;
23
+ getItem: (value?: I['value'] | Nil) => I | Nil;
24
+ };
25
+ export type Fetch = (code: string, options: Recordable) => MaybePromise<DictItemRecord[]>;
26
+ type FetchOptions<F extends Fetch> = Parameters<F>[1] extends infer T ? T extends Nil ? {} : T : {};
27
+ export type ExtraGetter<D extends Dict<string> = Dict<string>> = (dict: D) => Recordable;
28
+ export interface CreateDictManagerOptions<E extends ExtraGetter, F extends Fetch> {
29
+ fetch?: F;
30
+ extra?: E;
31
+ transformer?: (value: DictValue) => DictValue;
32
+ itemTransformer?: (item: DictItemRecord) => any;
33
+ }
34
+ export type UseDictOptions = {
35
+ clone?: boolean;
36
+ immediate?: boolean;
37
+ refresh?: boolean;
38
+ } & Recordable;
39
+ type Options<F extends Fetch> = FetchOptions<F> & UseDictOptions;
40
+ type CreateDict<D extends Recordable<Recordable>, F extends Fetch> = Dict<keyof D, Simplify<Merge<[DictItem, MergeValues<D>]> extends infer Item ? Item extends never ? DictItem : Item extends Recordable ? OptionalRequired<Item, 'label' | 'value'> : DictItem : DictItem>, Simplify<Options<F>>>;
41
+ type _UseDict<E extends Recordable, D extends Recordable<Recordable>, F extends Fetch> = (options?: Simplify<Options<F>>) => CreateDict<D, F> & E;
42
+ export type UseDict<E extends Recordable, D extends Recordable<Recordable>, F extends Fetch> = _UseDict<E, D, F> & {
43
+ extend: (extendCode: string, extendOptions?: {
44
+ pickValues?: Simplify<keyof D>[];
45
+ omitValues?: Simplify<keyof D>[];
46
+ }) => UseDict<E, D, F>;
47
+ };
48
+ type Data<R extends boolean> = Recordable<(R extends true ? {
49
+ label?: string;
50
+ } : {
51
+ label: string;
52
+ }) & Recordable>;
53
+ export interface DefineDict<ME extends ExtraGetter, MF extends Fetch> {
54
+ <R extends boolean, F extends Fetch, D extends Data<R>, E extends ExtraGetter>(code: string, options?: MaybeGetter<{
55
+ remote?: R;
56
+ fetch?: F;
57
+ data?: D;
58
+ extra?: E;
59
+ transformer?: (value: DictValue) => DictValue;
60
+ itemTransformer?: (item: DictItemRecord) => any;
61
+ }>): UseDict<ReturnType<ME> & ReturnType<E>, D, F extends undefined ? MF : F>;
62
+ }
63
+ export type VDictItem<T extends AnyFn> = ReturnType<T> extends {
64
+ list: Array<infer R>;
65
+ } ? R : never;
66
+ export type VDictUnionValue<T extends AnyFn> = ReturnType<T> extends {
67
+ E: infer R;
68
+ } ? keyof R : never;
69
+ export {};
@@ -0,0 +1,3 @@
1
+ export * from './dict';
2
+ export * from './merge';
3
+ export * from './tool';
@@ -0,0 +1,37 @@
1
+ type TupleUnionKeys<T> = T extends any ? keyof T : never;
2
+ type TupleAllKeys<T extends any[]> = TupleUnionKeys<T[number]>;
3
+ type TupleGetUnionType<T extends any[], K extends PropertyKey> = T extends [
4
+ infer First,
5
+ ...infer Rest
6
+ ] ? (K extends keyof First ? First[K] : undefined) | TupleGetUnionType<Rest, K> : never;
7
+ type Widen<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T;
8
+ type IsRequiredProperty<T, K extends keyof T> = {} extends Pick<T, K> ? false : true;
9
+ type IsAllRequired<T extends any[], K> = T extends [infer First, ...infer Rest] ? (K extends keyof First ? IsRequiredProperty<First, K> : false) extends true ? IsAllRequired<Rest, K> : false : true;
10
+ type TupleRequiredKeys<T extends any[]> = {
11
+ [K in TupleAllKeys<T>]: IsAllRequired<T, K> extends true ? K : never;
12
+ }[TupleAllKeys<T>];
13
+ export type Merge<T extends any[]> = {
14
+ [K in Exclude<TupleAllKeys<T>, TupleRequiredKeys<T>>]?: Widen<TupleGetUnionType<T, K>>;
15
+ } & {
16
+ [K in TupleRequiredKeys<T>]: Widen<TupleGetUnionType<T, K>>;
17
+ } extends infer O ? {
18
+ [P in keyof O]: O[P];
19
+ } : never;
20
+ type UnionKeys<T> = T extends any ? keyof T : never;
21
+ type UnionValueOf<T, K extends PropertyKey> = T extends any ? K extends keyof T ? T[K] : undefined : never;
22
+ type UnionIsAlwaysPresent<T, K extends PropertyKey> = [T] extends [infer U] ? U extends any ? K extends keyof U ? true : false : never : never;
23
+ type UnionRequiredKeys<T> = {
24
+ [K in UnionKeys<T>]: UnionIsAlwaysPresent<T, K> extends true ? K : never;
25
+ }[UnionKeys<T>];
26
+ type UnionOptionalKeys<T> = Exclude<UnionKeys<T>, UnionRequiredKeys<T>>;
27
+ export type MergeUnion<T> = {
28
+ [K in UnionOptionalKeys<T>]?: Widen<UnionValueOf<T, K>>;
29
+ } & {
30
+ [K in UnionRequiredKeys<T>]: Widen<UnionValueOf<T, K>>;
31
+ } extends infer O ? {
32
+ [P in keyof O]: O[P];
33
+ } : never;
34
+ export type MergeValues<T> = MergeUnion<{
35
+ [K in keyof T]: T[K];
36
+ }[keyof T]>;
37
+ export {};
@@ -0,0 +1,11 @@
1
+ export type Recordable<T = any> = Record<string, T>;
2
+ export type Nil = undefined | null;
3
+ export type MaybePromise<T> = T | Promise<T>;
4
+ export type Simplify<T> = {
5
+ [KeyType in keyof T]: T[KeyType];
6
+ } & {};
7
+ export type OptionalRequired<T, K extends keyof T> = Partial<T> & Required<Pick<T, K>>;
8
+ export type Getter<T> = () => T;
9
+ export type MaybeGetter<T> = T | Getter<T>;
10
+ export type AnyFn<Return = any, Args extends unknown[] = any[]> = (...args: Args) => Return;
11
+ export type PlainObject<T = any> = Record<PropertyKey, any>;
package/dist/util.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { AnyFn, DictItemRecord, DictMap, DictValue, Merge, PlainObject, Recordable } from './types';
2
+ export declare const warn: (msg: string) => void;
3
+ export declare function isFunction(fn: unknown): fn is AnyFn;
4
+ export declare function clearObj(obj: Recordable): void;
5
+ export declare function mapToObj(map: DictMap, { obj, itemTransformer }?: {
6
+ obj?: Recordable<DictItemRecord>;
7
+ itemTransformer?: (item: DictItemRecord) => any;
8
+ }): Recordable<DictItemRecord>;
9
+ export declare function mapToList(map: DictMap, { list, itemTransformer }?: {
10
+ list?: DictItemRecord[];
11
+ itemTransformer?: (item: DictItemRecord) => any;
12
+ }): DictItemRecord[];
13
+ type MapOptions = {
14
+ map?: DictMap;
15
+ pickValues?: DictValue[];
16
+ omitValues?: DictValue[];
17
+ transformer?: (value: DictValue) => DictValue;
18
+ };
19
+ export declare function toMap(data: Recordable<DictItemRecord> | DictItemRecord[], { map, pickValues, omitValues, transformer }?: MapOptions): DictMap;
20
+ export declare const defineDictData: <T>(data: T) => T;
21
+ export declare function isPlainObject(obj: any): obj is PlainObject;
22
+ export declare function merge<T extends PlainObject, S extends PlainObject[]>(target: T, ...sources: S): Merge<[T, ...S]>;
23
+ export declare function cloneDeep<T>(value: T): T;
24
+ export {};
@@ -0,0 +1,3 @@
1
+ export type * from '../types';
2
+ export * from './vue-dict-manager';
3
+ export { defineDictData } from '../util';
@@ -0,0 +1,12 @@
1
+ import type { CreateDictManagerOptions, DefineDict, DictValue, ExtraGetter, Fetch } from '../types';
2
+ export declare function createDictManager<E extends ExtraGetter, F extends Fetch>(createDictManagerOptions?: CreateDictManagerOptions<E, F>): {
3
+ defineDict: DefineDict<E, F>;
4
+ clear: (code?: string) => void;
5
+ maps: {
6
+ readonly [x: string]: ReadonlyMap<DictValue, {
7
+ readonly [x: string]: any;
8
+ readonly label: string;
9
+ readonly value: DictValue;
10
+ }>;
11
+ };
12
+ };
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "v-dict",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "type": "module",
5
5
  "description": "Vue3 & React Dict Manager",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/rrryyi/v-dict"
9
9
  },
10
- "main": "dist/index.js",
11
- "module": "dist/index.mjs",
10
+ "main": "dist/index.cjs",
11
+ "module": "dist/index.js",
12
12
  "typings": "dist/index.d.ts",
13
13
  "exports": {
14
14
  ".": {
@@ -39,11 +39,9 @@
39
39
  "vue",
40
40
  "react",
41
41
  "dict",
42
- "dictionary",
43
- "vue3",
44
- "react-dict"
42
+ "dictionary"
45
43
  ],
46
- "author": "",
44
+ "author": "rrryyi",
47
45
  "license": "MIT",
48
46
  "dependencies": {},
49
47
  "peerDependencies": {