hyperscript-rxjs 1.3.14 → 1.3.15

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 (279) hide show
  1. package/package.json +13 -22
  2. package/src/array/advance.d.ts +9 -0
  3. package/src/array/advance.js +13 -0
  4. package/src/array/advance.test.js +12 -0
  5. package/src/array/arrayInsert.d.ts +8 -0
  6. package/src/array/arrayInsert.js +13 -0
  7. package/src/array/arrayInsert.test.js +13 -0
  8. package/src/array/arrayRemove.d.ts +7 -0
  9. package/src/array/arrayRemove.js +15 -0
  10. package/src/array/arrayRemove.test.js +13 -0
  11. package/src/array/findLastIndex.d.ts +14 -0
  12. package/src/array/findLastIndex.js +20 -0
  13. package/src/array/findLastIndex.test.js +41 -0
  14. package/src/array/index.d.ts +9 -0
  15. package/src/array/index.js +9 -0
  16. package/src/array/isRange.d.ts +7 -0
  17. package/src/array/isRange.js +15 -0
  18. package/src/array/isRange.test.js +6 -0
  19. package/src/array/rangeArray.d.ts +7 -0
  20. package/src/array/rangeArray.js +10 -0
  21. package/src/array/rangeArray.test.js +11 -0
  22. package/src/array/unwrapArgs.d.ts +10 -0
  23. package/src/array/unwrapArgs.js +15 -0
  24. package/src/array/unwrapArgs.test.js +33 -0
  25. package/src/array/zipArray.d.ts +11 -0
  26. package/src/array/zipArray.js +24 -0
  27. package/src/array/zipArray.test.js +16 -0
  28. package/src/comparers/Comparer.d.ts +101 -0
  29. package/src/comparers/Comparer.js +149 -0
  30. package/src/comparers/comparers.d.ts +21 -0
  31. package/src/comparers/comparers.js +10 -0
  32. package/src/comparers/differenceSet.d.ts +20 -0
  33. package/src/comparers/differenceSet.js +35 -0
  34. package/src/comparers/differenceSet.test.js +11 -0
  35. package/src/comparers/distinctArray.d.ts +13 -0
  36. package/src/comparers/distinctArray.js +30 -0
  37. package/src/comparers/distinctArray.test.js +10 -0
  38. package/src/comparers/findIndexInSet.d.ts +20 -0
  39. package/src/comparers/findIndexInSet.js +27 -0
  40. package/src/comparers/findIndexInSet.test.js +8 -0
  41. package/src/comparers/groupArrayBy.d.ts +19 -0
  42. package/src/comparers/groupArrayBy.js +29 -0
  43. package/src/comparers/groupArrayBy.test.js +38 -0
  44. package/src/comparers/groupSortedEntries.d.ts +17 -0
  45. package/src/comparers/groupSortedEntries.js +38 -0
  46. package/src/comparers/groupSortedEntries.test.js +46 -0
  47. package/src/comparers/index.d.ts +14 -0
  48. package/src/comparers/index.js +14 -0
  49. package/src/comparers/intersectSet.d.ts +19 -0
  50. package/src/comparers/intersectSet.js +35 -0
  51. package/src/comparers/intersectSet.test.js +14 -0
  52. package/src/comparers/isEqualset.d.ts +22 -0
  53. package/src/comparers/isEqualset.js +33 -0
  54. package/src/comparers/isEqualset.test.js +22 -0
  55. package/src/comparers/isSubset.d.ts +21 -0
  56. package/src/comparers/isSubset.js +33 -0
  57. package/src/comparers/isSubset.test.js +21 -0
  58. package/src/comparers/isSuperset.d.ts +21 -0
  59. package/src/comparers/isSuperset.js +13 -0
  60. package/src/comparers/isSuperset.test.js +21 -0
  61. package/src/comparers/sortedArrayToSet.d.ts +20 -0
  62. package/src/comparers/sortedArrayToSet.js +35 -0
  63. package/src/comparers/sortedArrayToSet.test.js +11 -0
  64. package/src/comparers/unionSet.d.ts +21 -0
  65. package/src/comparers/unionSet.js +34 -0
  66. package/src/comparers/unionSet.test.js +11 -0
  67. package/src/comparison/compareDate.d.ts +8 -0
  68. package/src/comparison/compareDate.js +11 -0
  69. package/src/comparison/compareEntries.d.ts +13 -0
  70. package/src/comparison/compareEntries.js +13 -0
  71. package/src/comparison/compareKey.d.ts +11 -0
  72. package/src/comparison/compareKey.js +25 -0
  73. package/src/comparison/compareKey.test.js +21 -0
  74. package/src/comparison/compareKeyPath.d.ts +15 -0
  75. package/src/comparison/compareKeyPath.js +33 -0
  76. package/src/comparison/compareKeyPath.test.js +28 -0
  77. package/src/comparison/compareNumber.d.ts +11 -0
  78. package/src/comparison/compareNumber.js +27 -0
  79. package/src/comparison/compareNumber.test.js +21 -0
  80. package/src/comparison/defaultCompare.d.ts +8 -0
  81. package/src/comparison/defaultCompare.js +12 -0
  82. package/src/comparison/defaultCompare.test.js +24 -0
  83. package/src/comparison/index.d.ts +7 -0
  84. package/src/comparison/index.js +7 -0
  85. package/src/comparison/infinity.test.js +122 -0
  86. package/src/comparison/typeof.test.js +64 -0
  87. package/src/comparison/types.d.ts +5 -0
  88. package/src/comparison/types.js +11 -0
  89. package/src/deep/Deep.d.ts +58 -0
  90. package/src/deep/Deep.js +267 -0
  91. package/src/deep/Deep.test.js +130 -0
  92. package/src/deep/deepCombineLatest.test.js +36 -0
  93. package/src/deep/deepMerge.test.js +34 -0
  94. package/src/deep/differenceDeep.test.js +31 -0
  95. package/src/deep/freshValueDeep.test.js +17 -0
  96. package/src/deep/index.d.ts +1 -0
  97. package/src/deep/index.js +2 -0
  98. package/src/deep/intersectDeep.test.js +25 -0
  99. package/src/deep/intersectEntries.d.ts +13 -0
  100. package/src/deep/intersectEntries.js +37 -0
  101. package/src/deep/intersectEntries.test.js +20 -0
  102. package/src/deep/objectToDeep.test.js +31 -0
  103. package/src/deep/replaceValueDeep.test.js +21 -0
  104. package/src/deep/unionDeep.test.js +30 -0
  105. package/src/deep/zipValueDeep.test.js +21 -0
  106. package/src/deep-rxjs/ObservableArray.d.ts +55 -0
  107. package/src/deep-rxjs/ObservableArray.js +94 -0
  108. package/src/deep-rxjs/ObservableArray.test.js +117 -0
  109. package/src/deep-rxjs/index.d.ts +2 -0
  110. package/src/deep-rxjs/index.js +2 -0
  111. package/src/deep-rxjs/isRxType.d.ts +9 -0
  112. package/src/deep-rxjs/isRxType.js +15 -0
  113. package/src/deep-rxjs/isRxType.test.js +43 -0
  114. package/src/hyperscript-rxjs/HyperscriptExtensions.d.ts +20 -0
  115. package/src/hyperscript-rxjs/checkbox.d.ts +13 -0
  116. package/src/hyperscript-rxjs/checkbox.js +47 -0
  117. package/src/hyperscript-rxjs/checkbox.test.js +68 -0
  118. package/src/hyperscript-rxjs/choice.d.ts +13 -0
  119. package/src/hyperscript-rxjs/choice.js +24 -0
  120. package/src/hyperscript-rxjs/choice.test.js +108 -0
  121. package/src/hyperscript-rxjs/collapse.d.ts +14 -0
  122. package/src/hyperscript-rxjs/collapse.js +32 -0
  123. package/src/hyperscript-rxjs/collapse.test.js +67 -0
  124. package/src/hyperscript-rxjs/displays/blockLevelFamily.d.ts +5 -0
  125. package/src/hyperscript-rxjs/displays/blockLevelFamily.js +51 -0
  126. package/src/hyperscript-rxjs/displays/getDisplay.d.ts +7 -0
  127. package/src/hyperscript-rxjs/displays/getDisplay.js +51 -0
  128. package/src/hyperscript-rxjs/displays/getDisplay.test.js +56 -0
  129. package/src/hyperscript-rxjs/displays/index.d.ts +3 -0
  130. package/src/hyperscript-rxjs/displays/index.js +3 -0
  131. package/src/hyperscript-rxjs/displays/inlineFamily.d.ts +5 -0
  132. package/src/hyperscript-rxjs/displays/inlineFamily.js +73 -0
  133. package/src/hyperscript-rxjs/flip.d.ts +15 -0
  134. package/src/hyperscript-rxjs/flip.js +29 -0
  135. package/src/hyperscript-rxjs/flip.test.js +85 -0
  136. package/src/hyperscript-rxjs/fragment.d.ts +10 -0
  137. package/src/hyperscript-rxjs/fragment.js +22 -0
  138. package/src/hyperscript-rxjs/fragment.test.js +70 -0
  139. package/src/hyperscript-rxjs/hyperscript.d.ts +15 -0
  140. package/src/hyperscript-rxjs/hyperscript.js +170 -0
  141. package/src/hyperscript-rxjs/hyperscript.test.js +75 -0
  142. package/src/hyperscript-rxjs/index.d.ts +19 -0
  143. package/src/hyperscript-rxjs/index.js +19 -0
  144. package/src/hyperscript-rxjs/multiselect.d.ts +18 -0
  145. package/src/hyperscript-rxjs/multiselect.js +41 -0
  146. package/src/hyperscript-rxjs/multiselect.test.js +121 -0
  147. package/src/hyperscript-rxjs/numberbox.d.ts +14 -0
  148. package/src/hyperscript-rxjs/numberbox.js +73 -0
  149. package/src/hyperscript-rxjs/numberbox.test.js +84 -0
  150. package/src/hyperscript-rxjs/radio.d.ts +15 -0
  151. package/src/hyperscript-rxjs/radio.js +53 -0
  152. package/src/hyperscript-rxjs/radio.test.js +59 -0
  153. package/src/hyperscript-rxjs/select.d.ts +28 -0
  154. package/src/hyperscript-rxjs/select.js +88 -0
  155. package/src/hyperscript-rxjs/select.test.js +101 -0
  156. package/src/hyperscript-rxjs/tabControls/bindTabIndex.d.ts +12 -0
  157. package/src/hyperscript-rxjs/tabControls/bindTabIndex.js +59 -0
  158. package/src/hyperscript-rxjs/tabControls/index.d.ts +8 -0
  159. package/src/hyperscript-rxjs/tabControls/index.js +10 -0
  160. package/src/hyperscript-rxjs/tabControls/tabControl.d.ts +19 -0
  161. package/src/hyperscript-rxjs/tabControls/tabControl.js +40 -0
  162. package/src/hyperscript-rxjs/tabControls/tabControl.test.js +98 -0
  163. package/src/hyperscript-rxjs/tabControls/tabNavItem.d.ts +9 -0
  164. package/src/hyperscript-rxjs/tabControls/tabNavItem.js +30 -0
  165. package/src/hyperscript-rxjs/tabControls/tabPanel.d.ts +9 -0
  166. package/src/hyperscript-rxjs/tabControls/tabPanel.js +21 -0
  167. package/src/hyperscript-rxjs/tabControls/tabRoot.d.ts +7 -0
  168. package/src/hyperscript-rxjs/tabControls/tabRoot.js +26 -0
  169. package/src/hyperscript-rxjs/tags.d.ts +193 -0
  170. package/src/hyperscript-rxjs/tags.js +751 -0
  171. package/src/hyperscript-rxjs/tags.test.js +75 -0
  172. package/src/hyperscript-rxjs/textNode.d.ts +11 -0
  173. package/src/hyperscript-rxjs/textNode.js +51 -0
  174. package/src/hyperscript-rxjs/textNode.test.js +56 -0
  175. package/src/hyperscript-rxjs/textarea.d.ts +17 -0
  176. package/src/hyperscript-rxjs/textarea.js +45 -0
  177. package/src/hyperscript-rxjs/textarea.test.js +52 -0
  178. package/src/hyperscript-rxjs/textbox.d.ts +15 -0
  179. package/src/hyperscript-rxjs/textbox.js +42 -0
  180. package/src/hyperscript-rxjs/textbox.test.js +52 -0
  181. package/src/index.d.ts +19 -0
  182. package/src/index.js +19 -0
  183. package/src/nodes/attachSubscriptionToNode.d.ts +13 -0
  184. package/src/nodes/attachSubscriptionToNode.js +25 -0
  185. package/src/nodes/attachSubscriptionToNode.test.js +73 -0
  186. package/src/nodes/index.d.ts +6 -0
  187. package/src/nodes/index.js +6 -0
  188. package/src/nodes/normalizeChildNodes.d.ts +9 -0
  189. package/src/nodes/normalizeChildNodes.js +15 -0
  190. package/src/nodes/normalizeChildNodes.test.js +55 -0
  191. package/src/nodes/parseHyperscriptArgs.d.ts +10 -0
  192. package/src/nodes/parseHyperscriptArgs.js +57 -0
  193. package/src/nodes/parseHyperscriptArgs.test.js +85 -0
  194. package/src/nodes/pipeEvent.d.ts +15 -0
  195. package/src/nodes/pipeEvent.js +49 -0
  196. package/src/nodes/pipeEvent.test.js +97 -0
  197. package/src/nodes/subscribeEvent.d.ts +15 -0
  198. package/src/nodes/subscribeEvent.js +56 -0
  199. package/src/nodes/subscribeEvent.test.js +88 -0
  200. package/src/object/index.d.ts +10 -0
  201. package/src/object/index.js +11 -0
  202. package/src/object/intersectObject.d.ts +12 -0
  203. package/src/object/intersectObject.js +23 -0
  204. package/src/object/intersectObject.test.js +69 -0
  205. package/src/object/isEmptyObject.d.ts +7 -0
  206. package/src/object/isEmptyObject.js +13 -0
  207. package/src/object/isEmptyObject.test.js +33 -0
  208. package/src/object/isPlainObject.d.ts +11 -0
  209. package/src/object/isPlainObject.js +18 -0
  210. package/src/object/nestedCombineLatest.d.ts +11 -0
  211. package/src/object/nestedCombineLatest.js +18 -0
  212. package/src/object/nestedCombineLatest.test.js +25 -0
  213. package/src/object/nestedMerge.d.ts +11 -0
  214. package/src/object/nestedMerge.js +11 -0
  215. package/src/object/nestedMerge.test.js +61 -0
  216. package/src/object/pickBehaviorSubject.d.ts +13 -0
  217. package/src/object/pickBehaviorSubject.js +81 -0
  218. package/src/object/pickBehaviorSubject.test.js +88 -0
  219. package/src/object/pluckProperty.d.ts +13 -0
  220. package/src/object/pluckProperty.js +24 -0
  221. package/src/object/pluckProperty.test.js +37 -0
  222. package/src/object/restore.d.ts +12 -0
  223. package/src/object/restore.js +69 -0
  224. package/src/object/restore.test.js +124 -0
  225. package/src/object/splitObjectByObservable.d.ts +12 -0
  226. package/src/object/splitObjectByObservable.js +41 -0
  227. package/src/object/splitObjectByObservable.test.js +78 -0
  228. package/src/props/getNestedProperty.d.ts +12 -0
  229. package/src/props/getNestedProperty.js +31 -0
  230. package/src/props/getNestedProperty.test.js +72 -0
  231. package/src/props/index.d.ts +7 -0
  232. package/src/props/index.js +7 -0
  233. package/src/props/parsePropName.d.ts +13 -0
  234. package/src/props/parsePropName.js +45 -0
  235. package/src/props/parsePropName.test.js +67 -0
  236. package/src/props/setProp.d.ts +16 -0
  237. package/src/props/setProp.js +42 -0
  238. package/src/props/setProp.test.js +59 -0
  239. package/src/props/setProps.d.ts +14 -0
  240. package/src/props/setProps.js +47 -0
  241. package/src/props/setProps.test.js +97 -0
  242. package/src/props/subscribeProp.d.ts +16 -0
  243. package/src/props/subscribeProp.js +47 -0
  244. package/src/props/subscribeProp.test.js +81 -0
  245. package/src/ramda/compose.d.ts +10 -0
  246. package/src/ramda/compose.js +36 -0
  247. package/src/ramda/compose.test.js +73 -0
  248. package/src/ramda/cond.d.ts +12 -0
  249. package/src/ramda/cond.js +29 -0
  250. package/src/ramda/cond.test.js +88 -0
  251. package/src/ramda/fold.d.ts +13 -0
  252. package/src/ramda/fold.js +20 -0
  253. package/src/ramda/fold.test.js +51 -0
  254. package/src/ramda/index.d.ts +6 -0
  255. package/src/ramda/index.js +6 -0
  256. package/src/ramda/pipe.d.ts +13 -0
  257. package/src/ramda/pipe.js +27 -0
  258. package/src/ramda/pipe.test.js +77 -0
  259. package/src/ramda/unfold.d.ts +11 -0
  260. package/src/ramda/unfold.js +20 -0
  261. package/src/ramda/unfold.test.js +29 -0
  262. package/src/unquoted-json/ajax.test.js +1074 -0
  263. package/src/unquoted-json/index.d.ts +13 -0
  264. package/src/unquoted-json/index.js +12 -0
  265. package/src/unquoted-json/queryStringify.d.ts +8 -0
  266. package/src/unquoted-json/queryStringify.js +70 -0
  267. package/src/unquoted-json/queryStringify.test.js +110 -0
  268. package/src/unquoted-json/stringifyKey.d.ts +7 -0
  269. package/src/unquoted-json/stringifyKey.js +16 -0
  270. package/src/unquoted-json/stringifyKey.test.js +51 -0
  271. package/src/unquoted-json/stringifyStringValue.d.ts +7 -0
  272. package/src/unquoted-json/stringifyStringValue.js +17 -0
  273. package/src/unquoted-json/stringifyStringValue.test.js +52 -0
  274. package/src/unquoted-json/unquotedJsonStringify.d.ts +7 -0
  275. package/src/unquoted-json/unquotedJsonStringify.js +39 -0
  276. package/src/unquoted-json/unquotedJsonStringify.test.js +52 -0
  277. package/dist/hyperscript-rxjs.d.ts +0 -1412
  278. package/dist/hyperscript-rxjs.js +0 -1
  279. package/dist/tsdoc-metadata.json +0 -11
@@ -0,0 +1,124 @@
1
+ import { BehaviorSubject } from 'rxjs'
2
+ import { ObservableArray } from '../deep-rxjs/ObservableArray'
3
+ import { pickBehaviorSubject } from './pickBehaviorSubject'
4
+ import { restore } from './restore'
5
+
6
+ test('BehaviorSubject happy', done => {
7
+ let source = new BehaviorSubject(0)
8
+ restore(source, 1)
9
+ expect(source.value).toEqual(1)
10
+ done()
11
+ })
12
+
13
+ test('array happy', done => {
14
+ let source = [
15
+ new BehaviorSubject(0),
16
+ new BehaviorSubject(0),
17
+ ]
18
+ restore(source, [1, 2])
19
+ let y = pickBehaviorSubject(source)
20
+ expect(y).toEqual([1, 2])
21
+ done()
22
+ })
23
+
24
+ test('array less', done => {
25
+ let source = [
26
+ new BehaviorSubject(0),
27
+ new BehaviorSubject(0),
28
+ ]
29
+ restore(source, [1])
30
+ let y = pickBehaviorSubject(source)
31
+ expect(y).toEqual([1, 0])
32
+ done()
33
+ })
34
+
35
+ test('nested happy', done => {
36
+ let model = {
37
+ title: new BehaviorSubject('compiler'),
38
+ keywords: [
39
+ new BehaviorSubject('lex'),
40
+ new BehaviorSubject('yacc'),
41
+ ]
42
+ }
43
+ let src = {
44
+ title: 'lang',
45
+ keywords: [
46
+ 'js',
47
+ 'fs',
48
+ ]
49
+ }
50
+ restore(model, src)
51
+
52
+ expect(model.title.value).toEqual(src.title)
53
+ expect(model.keywords[0].value).toEqual(src.keywords[0])
54
+ expect(model.keywords[1].value).toEqual(src.keywords[1])
55
+ done()
56
+ })
57
+
58
+
59
+ test('array too much', done => {
60
+ let source = [
61
+ new BehaviorSubject(0),
62
+ new BehaviorSubject(0),
63
+ ]
64
+ restore(source, [1, 2, 3])
65
+ let y = pickBehaviorSubject(source)
66
+ expect(y).toEqual([1, 2])
67
+ done()
68
+ })
69
+
70
+ test('object ignore member', done => {
71
+ let source = {
72
+ a: new BehaviorSubject(0),
73
+ b: 0
74
+ }
75
+ restore(source, { a: 1, b: 1 })
76
+ let y = pickBehaviorSubject(source)
77
+ expect(y).toEqual({ a: 1 })
78
+ done()
79
+ })
80
+
81
+ test('observable array happy', done => {
82
+ let source = new ObservableArray()
83
+
84
+ source.insertBefore(new BehaviorSubject(0))
85
+ source.insertBefore(new BehaviorSubject(0))
86
+ source.insertBefore(new BehaviorSubject(0))
87
+
88
+ restore(source, [1, 2, 3])
89
+ let y = pickBehaviorSubject(source)
90
+ expect(y).toEqual([1, 2, 3])
91
+ done()
92
+ })
93
+
94
+ test('observable array cut off', done => {
95
+ let source = new ObservableArray()
96
+
97
+ source.insertBefore(new BehaviorSubject(0))
98
+ source.insertBefore(new BehaviorSubject(0))
99
+ source.insertBefore(new BehaviorSubject(0))
100
+ source.insertBefore(new BehaviorSubject(0))
101
+
102
+ restore(source, [1, 2, 3])
103
+ let y = pickBehaviorSubject(source)
104
+ expect(y).toEqual([1, 2, 3])
105
+ done()
106
+ })
107
+
108
+ test('observable array complement', done => {
109
+ let model = new ObservableArray(()=>new BehaviorSubject(0))
110
+
111
+ let src = [1, 2, 3]
112
+ restore(model, src)
113
+
114
+ expect(model[0].value).toEqual(src[0])
115
+ expect(model[1].value).toEqual(src[1])
116
+ expect(model[2].value).toEqual(src[2])
117
+ done()
118
+ })
119
+
120
+
121
+
122
+
123
+
124
+
@@ -0,0 +1,12 @@
1
+ import { Observable } from 'rxjs';
2
+
3
+ /**
4
+ * 将对象属性按类型分为两部分:可观察对象(Observable)与普通值(非 Observable)。
5
+ *
6
+ * @param obj - 要分割的对象,其属性值可能是 Observable 或普通值。
7
+ * @returns 一个数组,第一个对象包含所有 Observable 属性,第二个对象包含所有非 Observable 属性。
8
+ * @throws 如果参数不是一个非空对象会抛出错误。
9
+ */
10
+ export function splitObjectByObservable(
11
+ obj: Record<string, any>
12
+ ): [Record<string, Observable<any>>, Record<string, any>];
@@ -0,0 +1,41 @@
1
+ import { isObservable, Observable } from 'rxjs';
2
+
3
+ /**
4
+ * 将对象属性按类型分为两部分:可观察对象(Observable)与普通值(非 Observable)。
5
+ *
6
+ * @param {Record<string,any>} obj - 要分割的对象,其属性值可能是 Observable 或普通值。
7
+ * @returns {[Record<string, Observable<any>>, Record<string, any>]} - 返回一个数组,第一个对象包含所有 Observable 属性,第二个对象包含所有非 Observable 属性。
8
+ * @throws {Error} 如果参数不是一个非空对象。
9
+ */
10
+ export function splitObjectByObservable(obj) {
11
+ // 参数检查,确保输入是一个非空对象
12
+ if (typeof obj !== 'object' || Array.isArray(obj) || obj === null) {
13
+ throw new Error('参数 "obj" 必须是一个非空对象。');
14
+ }
15
+
16
+ /**
17
+ * @type {Record<string, Observable<any>>}
18
+ */
19
+ let observables = {}; // 存储 Observable 属性
20
+
21
+ /**
22
+ * @type {Record<string, any>}
23
+ */
24
+ let scalars = {}; // 存储非 Observable 属性
25
+
26
+ // 遍历对象的所有属性
27
+ for (const key in obj) {
28
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
29
+ let value = obj[key];
30
+
31
+ // 根据值的类型分类
32
+ if (isObservable(value)) {
33
+ observables[key] = value; // 如果是 Observable,存入 observables
34
+ } else {
35
+ scalars[key] = value; // 否则存入 scalars
36
+ }
37
+ }
38
+ }
39
+ //可观察对象(Observable)与普通值(非 Observable)
40
+ return [observables, scalars];
41
+ }
@@ -0,0 +1,78 @@
1
+ import { of } from 'rxjs';
2
+ import { splitObjectByObservable } from './splitObjectByObservable';
3
+
4
+ describe('splitObjectByObservable', () => {
5
+ test('should split object into observables and scalars', () => {
6
+ const obj = {
7
+ a: of(1), // Observable
8
+ b: 42, // Scalar
9
+ c: 'hello', // Scalar
10
+ d: of('world'), // Observable
11
+ };
12
+
13
+ const [observables, scalars] = splitObjectByObservable(obj);
14
+
15
+ // 验证 Observable 部分
16
+ expect(observables).toEqual({
17
+ a: obj.a,
18
+ d: obj.d,
19
+ });
20
+
21
+ // 验证 Scalar 部分
22
+ expect(scalars).toEqual({
23
+ b: 42,
24
+ c: 'hello',
25
+ });
26
+ });
27
+
28
+ test('should handle an object with only observables', () => {
29
+ const obj = {
30
+ a: of(1),
31
+ b: of(2),
32
+ };
33
+
34
+ const [observables, scalars] = splitObjectByObservable(obj);
35
+
36
+ // 验证 Observable 部分
37
+ expect(observables).toEqual(obj);
38
+
39
+ // 验证 Scalar 部分为空
40
+ expect(scalars).toEqual({});
41
+ });
42
+
43
+ test('should handle an object with only scalars', () => {
44
+ const obj = {
45
+ a: 42,
46
+ b: 'hello',
47
+ };
48
+
49
+ const [observables, scalars] = splitObjectByObservable(obj);
50
+
51
+ // 验证 Observable 部分为空
52
+ expect(observables).toEqual({});
53
+
54
+ // 验证 Scalar 部分
55
+ expect(scalars).toEqual(obj);
56
+ });
57
+
58
+ test('should return empty objects for an empty input object', () => {
59
+ const obj = {};
60
+
61
+ const [observables, scalars] = splitObjectByObservable(obj);
62
+
63
+ // 验证 Observable 部分为空
64
+ expect(observables).toEqual({});
65
+
66
+ // 验证 Scalar 部分为空
67
+ expect(scalars).toEqual({});
68
+ });
69
+
70
+ test('should throw an error if input is not an object', () => {
71
+ let errorMessage = '参数 "obj" 必须是一个非空对象。';
72
+ expect(() => splitObjectByObservable(null)).toThrow(errorMessage);
73
+ expect(() => splitObjectByObservable(undefined)).toThrow(errorMessage);
74
+ expect(() => splitObjectByObservable(42)).toThrow(errorMessage);
75
+ expect(() => splitObjectByObservable('string')).toThrow(errorMessage);
76
+ expect(() => splitObjectByObservable([])).toThrow(errorMessage);
77
+ });
78
+ });
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 根据属性路径数组读取对象的嵌套属性值。
3
+ *
4
+ * @param obj - 要读取属性的对象。
5
+ * @param keyPath - 属性路径数组,例如 ['a', 'b'] 表示 obj.a.b。
6
+ * @returns 返回目标属性的值,如果路径为空数组,则返回对象本身。
7
+ * @throws 如果路径中的某一级属性不存在或输入无效会抛出错误。
8
+ */
9
+ export function getNestedProperty(
10
+ obj: Record<string | number, any>,
11
+ keyPath: (string | number)[]
12
+ ): any;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * 根据属性路径数组读取对象的嵌套属性值。
3
+ * @param {Record<string | number, any>} obj - 要读取属性的对象。
4
+ * @param {(string | number)[]} keyPath - 属性路径数组,例如 ['a', 'b'] 表示 obj.a.b。
5
+ * @returns {any} - 返回目标属性的值,如果路径为空数组,则返回对象本身。
6
+ * @throws {Error} 如果路径中的某一级属性不存在或输入无效。
7
+ */
8
+ export function getNestedProperty(obj, keyPath) {
9
+ if (!Array.isArray(keyPath)) {
10
+ throw new Error('The "pathArray" parameter must be an array.');
11
+ }
12
+
13
+ if (!obj || typeof obj !== 'object') {
14
+ throw new Error('The "obj" parameter must be a non-null object.');
15
+ }
16
+
17
+ return keyPath.reduce((currentObj, key) => {
18
+ if (currentObj === null || currentObj === undefined) {
19
+ throw new Error(`Cannot read property "${key}" of null or undefined.`);
20
+ }
21
+
22
+ if (typeof key === 'string' && typeof currentObj === 'object' && key in currentObj) {
23
+ return /** @type {Record<string, any>} */ (currentObj)[key];
24
+ } else if (typeof key === 'number' && Array.isArray(currentObj) && key >= 0 && key < currentObj.length) {
25
+ return currentObj[key];
26
+ } else {
27
+ throw new Error(`Property "${key}" does not exist on the object.`);
28
+ }
29
+
30
+ }, obj);
31
+ }
@@ -0,0 +1,72 @@
1
+ import { getNestedProperty } from './getNestedProperty';
2
+
3
+ describe('getNestedProperty', () => {
4
+ test('should return the object itself if pathArray is empty', () => {
5
+ const obj = { a: 1 };
6
+ expect(getNestedProperty(obj, [])).toBe(obj);
7
+ });
8
+
9
+ test('should return a simple property value', () => {
10
+ const obj = { a: 1 };
11
+ expect(getNestedProperty(obj, ['a'])).toBe(1);
12
+ });
13
+
14
+ test('should return a nested property value', () => {
15
+ const obj = { a: { b: { c: 42 } } };
16
+ expect(getNestedProperty(obj, ['a', 'b', 'c'])).toBe(42);
17
+ });
18
+
19
+ test('should throw an error if a property in the path does not exist', () => {
20
+ const obj = { a: { b: { c: 42 } } };
21
+ expect(() => getNestedProperty(obj, ['a', 'x'])).toThrow(
22
+ 'Property "x" does not exist on the object.'
23
+ );
24
+ expect(() => getNestedProperty(obj, ['a', 'b', 'd'])).toThrow(
25
+ 'Property "d" does not exist on the object.'
26
+ );
27
+ });
28
+
29
+ test('should throw an error if the pathArray is not an array', () => {
30
+ const obj = { a: 1 };
31
+ expect(() => getNestedProperty(obj, null)).toThrow(
32
+ 'The "pathArray" parameter must be an array.'
33
+ );
34
+ expect(() => getNestedProperty(obj, 'a')).toThrow(
35
+ 'The "pathArray" parameter must be an array.'
36
+ );
37
+ });
38
+
39
+ test('should throw an error if the obj parameter is not an object', () => {
40
+ expect(() => getNestedProperty(null, ['a'])).toThrow(
41
+ 'The "obj" parameter must be a non-null object.'
42
+ );
43
+ expect(() => getNestedProperty(undefined, ['a'])).toThrow(
44
+ 'The "obj" parameter must be a non-null object.'
45
+ );
46
+ expect(() => getNestedProperty(42, ['a'])).toThrow(
47
+ 'The "obj" parameter must be a non-null object.'
48
+ );
49
+ });
50
+
51
+ test('should handle deeply nested properties', () => {
52
+ const obj = { a: { b: { c: { d: 'value' } } } };
53
+ expect(getNestedProperty(obj, ['a', 'b', 'c', 'd'])).toBe('value');
54
+ });
55
+
56
+ test('should handle properties with special characters', () => {
57
+ const obj = { 'data-value': { 'inner.prop': 'test' } };
58
+ expect(getNestedProperty(obj, ['data-value', 'inner.prop'])).toBe('test');
59
+ });
60
+
61
+ test('should handle arrays as part of the path', () => {
62
+ const obj = { a: [{ b: 42 }] };
63
+ expect(getNestedProperty(obj, ['a', 0, 'b'])).toBe(42);
64
+ });
65
+
66
+ test('should throw an error if accessing an array index that does not exist', () => {
67
+ const obj = { a: [{ b: 42 }] };
68
+ expect(() => getNestedProperty(obj, ['a', 1, 'b'])).toThrow(
69
+ 'Property "1" does not exist on the object.'
70
+ );
71
+ });
72
+ });
@@ -0,0 +1,7 @@
1
+ export * from './getNestedProperty';
2
+ export * from './parsePropName';
3
+ export * from './setProp';
4
+ export * from './setProps';
5
+ export * from './subscribeProp';
6
+
7
+
@@ -0,0 +1,7 @@
1
+ export * from './getNestedProperty';
2
+ export * from './parsePropName';
3
+ export * from './setProp';
4
+ export * from './setProps';
5
+ export * from './subscribeProp';
6
+
7
+
@@ -0,0 +1,13 @@
1
+
2
+ /**
3
+ * 解析嵌套的 DOM 属性路径,并返回目标对象和属性名。
4
+ *
5
+ * @param props - 属性路径字符串,支持嵌套属性(如 "style.color")。
6
+ * @param obj - 起始对象,通常是一个 DOM 元素。
7
+ * @returns [目标对象, 属性名],如 [obj.style, "color"]。
8
+ * @throws 如果路径中的某一级属性不存在或输入无效会抛出错误。
9
+ */
10
+ export function parsePropName(
11
+ props: string,
12
+ obj: Record<string, any>
13
+ ): [Record<string, any>, string];
@@ -0,0 +1,45 @@
1
+ import { getNestedProperty } from './getNestedProperty';
2
+
3
+ /**
4
+ * 解析嵌套的 DOM 属性路径,并返回目标对象和属性名。
5
+ *
6
+ * @param {string} props - 属性路径,是 DOM API 的属性,不需要引号包裹,支持嵌套属性(如 "style.color")。
7
+ * @param {Record<string, any>} obj - 起始对象,通常是一个 DOM 元素。
8
+ * @returns {[Record<string, any>, string]} - 返回一个数组,表示叶节点,其中第一个元素是目标对象,第二个元素是属性名。(如 [obj.style, "color"])。
9
+ * @throws {Error} 如果路径中的某一级属性不存在或输入无效。
10
+ */
11
+ export function parsePropName(props, obj) {
12
+ if (typeof props !== 'string') {
13
+ throw new Error('The "prop" parameter must be a string.');
14
+ }
15
+
16
+ /**
17
+ * @param {any} target
18
+ * @param {string} prop
19
+ * @returns {[any, string]}
20
+ */
21
+ function getTargetAndProp(target, prop) {
22
+ if (!target || typeof target !== 'object') {
23
+ throw new Error('The "obj" parameter must be a non-null object.');
24
+ }
25
+
26
+ if (!(prop in target)) {
27
+ throw new Error(`Property "${prop}" does not exist on the target object.`);
28
+ }
29
+
30
+ return [target, prop];
31
+ }
32
+
33
+ if (props.includes('.')) {
34
+ const pathArray = props.split('.')
35
+ const prop = pathArray.pop()
36
+ if(!prop){
37
+ throw new Error('The "prop" parameter must be a non-empty string.');
38
+ }
39
+ const target = getNestedProperty(obj, pathArray)
40
+ return getTargetAndProp(target, prop)
41
+
42
+ } else {
43
+ return getTargetAndProp(obj, props)
44
+ }
45
+ }
@@ -0,0 +1,67 @@
1
+ import { parsePropName } from './parsePropName';
2
+
3
+ describe('parsePropName', () => {
4
+ test('should parse a simple property', () => {
5
+ const obj = { id: 'test' };
6
+ const [target, prop] = parsePropName('id', obj);
7
+ expect(target).toBe(obj);
8
+ expect(prop).toBe('id');
9
+ });
10
+
11
+ test('should parse a nested property', () => {
12
+ const obj = { style: { color: 'red' } };
13
+ const [target, prop] = parsePropName('style.color', obj);
14
+ expect(target).toBe(obj.style);
15
+ expect(prop).toBe('color');
16
+ });
17
+
18
+ test('should throw an error if the property does not exist in a simple path', () => {
19
+ const obj = { id: 'test' };
20
+ expect(() => parsePropName('name', obj)).toThrow(
21
+ 'Property "name" does not exist on the target object.'
22
+ );
23
+ });
24
+
25
+ test('should throw an error if the property does not exist in a nested path', () => {
26
+ const obj = { style: { color: 'red' } };
27
+ expect(() => parsePropName('style.background', obj)).toThrow(
28
+ 'Property "background" does not exist on the target object.'
29
+ );
30
+ });
31
+
32
+ test('should throw an error if the prop parameter is not a string', () => {
33
+ const obj = { id: 'test' };
34
+ expect(() => parsePropName(null, obj)).toThrow(
35
+ 'The "prop" parameter must be a string.'
36
+ );
37
+ expect(() => parsePropName(123, obj)).toThrow(
38
+ 'The "prop" parameter must be a string.'
39
+ );
40
+ });
41
+
42
+ test('should throw an error if the obj parameter is not an object', () => {
43
+ expect(() => parsePropName('id', null)).toThrow(
44
+ 'The "obj" parameter must be a non-null object.'
45
+ );
46
+ expect(() => parsePropName('id', undefined)).toThrow(
47
+ 'The "obj" parameter must be a non-null object.'
48
+ );
49
+ expect(() => parsePropName('id', 123)).toThrow(
50
+ 'The "obj" parameter must be a non-null object.'
51
+ );
52
+ });
53
+
54
+ test('should handle deeply nested properties', () => {
55
+ const obj = { a: { b: { c: { d: 'value' } } } };
56
+ const [target, prop] = parsePropName('a.b.c.d', obj);
57
+ expect(target).toBe(obj.a.b.c);
58
+ expect(prop).toBe('d');
59
+ });
60
+
61
+ test('should throw an error if a deeply nested property does not exist', () => {
62
+ const obj = { a: { b: { c: {} } } };
63
+ expect(() => parsePropName('a.b.c.d', obj)).toThrow(
64
+ 'Property "d" does not exist on the target object.'
65
+ );
66
+ });
67
+ });
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 设置一个元素对象的任意嵌套路径属性的值。
3
+ * 如果是 CSS 类名,值为真则添加类名,值为假则移除类名。
4
+ * 如果是普通属性或嵌套属性则设置该属性值。
5
+ *
6
+ * @param root - 要设置属性的 DOM 元素。
7
+ * @param key - 属性名称,支持普通属性、嵌套属性(如 "style.color")或以 "." 开头的类名(如 ".active")。
8
+ * @param value - 要设置的属性值。如果是布尔值,用于控制类名的添加或移除。
9
+ * @returns 返回元素本身,支持链式调用。
10
+ * @throws 如果参数无效或设置失败会抛出错误。
11
+ */
12
+ export function setProp(
13
+ root: HTMLElement,
14
+ key: string,
15
+ value: any
16
+ ): HTMLElement;
@@ -0,0 +1,42 @@
1
+ import { parsePropName } from './parsePropName';
2
+
3
+ /**
4
+ *
5
+ * 设置一个元素对象的任意嵌套路径属性的值,如果是CSS类名,值为真则添加类名,值为假则移除类名。如果是普通属性或嵌套属性则设置改属性值。
6
+ *
7
+ * @param {HTMLElement} root - 要设置属性的 DOM 元素。
8
+ * @param {string} key - 属性名称,支持普通属性、嵌套属性(如 "style.color")或以 "." 开头的类名(如 ".active")。
9
+ * @param {*} value - 要设置的属性值。如果是布尔值,用于控制类名的添加或移除。
10
+ * @returns {HTMLElement} - 返回元素本身,支持链式调用。
11
+ * @throws {Error} 如果参数无效或设置失败。
12
+ *
13
+ */
14
+ export function setProp(root, key, value) {
15
+ if (!(root instanceof HTMLElement)) {
16
+ throw new Error('The "element" parameter must be a valid DOM element.');
17
+ }
18
+ if (typeof key !== 'string') {
19
+ throw new Error('The "key" parameter must be a string.');
20
+ }
21
+
22
+ // CSS 类名操作
23
+ if (key.charAt(0) === '.') {
24
+ const className = key.substring(1);
25
+
26
+ if (className.length === 0) {
27
+ throw new Error('The class name cannot be empty.');
28
+ }
29
+
30
+ if (value) {
31
+ root.classList.add(className); // 添加类名
32
+ } else {
33
+ root.classList.remove(className); // 移除类名
34
+ }
35
+ } else {
36
+ // 普通属性或嵌套属性设置
37
+ const [target, prop] = parsePropName(key, root); // 解析属性路径
38
+ target[prop] = value; // 设置属性值
39
+ }
40
+
41
+ return root; // 返回元素本身,支持链式调用
42
+ }
@@ -0,0 +1,59 @@
1
+ import { setProp } from './setProp';
2
+
3
+ describe('setProp', () => {
4
+ let div;
5
+
6
+ beforeEach(() => {
7
+ div = document.createElement('div');
8
+ });
9
+
10
+ test('should add a CSS class when value is true', () => {
11
+ setProp(div, '.active', true);
12
+ expect(div.classList.contains('active')).toBe(true);
13
+ });
14
+
15
+ test('should remove a CSS class when value is false', () => {
16
+ div.classList.add('active');
17
+ setProp(div, '.active', false);
18
+ expect(div.classList.contains('active')).toBe(false);
19
+ });
20
+
21
+ test('should throw an error if the class name is empty', () => {
22
+ expect(() => setProp(div, '.', true)).toThrow('The class name cannot be empty.');
23
+ });
24
+
25
+ test('should set a simple property', () => {
26
+ setProp(div, 'id', 'myDiv');
27
+ expect(div.id).toBe('myDiv');
28
+ });
29
+
30
+ test('should set a nested property', () => {
31
+ setProp(div, 'style.color', 'red');
32
+ expect(div.style.color).toBe('red');
33
+ });
34
+
35
+ test('should throw an error if the key is not a string', () => {
36
+ expect(() => setProp(div, null, 'value')).toThrow('The "key" parameter must be a string.');
37
+ expect(() => setProp(div, 123, 'value')).toThrow('The "key" parameter must be a string.');
38
+ });
39
+
40
+ test('should throw an error if the element is not a valid DOM element', () => {
41
+ expect(() => setProp(null, 'id', 'myDiv')).toThrow(
42
+ 'The "element" parameter must be a valid DOM element.'
43
+ );
44
+ expect(() => setProp({}, 'id', 'myDiv')).toThrow(
45
+ 'The "element" parameter must be a valid DOM element.'
46
+ );
47
+ });
48
+
49
+ test('should throw an error if setting a nested property fails', () => {
50
+ expect(() => setProp(div, 'nonexistent.property', 'value')).toThrow(
51
+ 'Property "nonexistent" does not exist on the object.'
52
+ );
53
+ });
54
+
55
+ test('should support chainable calls', () => {
56
+ const result = setProp(div, 'id', 'myDiv');
57
+ expect(result).toBe(div);
58
+ });
59
+ });
@@ -0,0 +1,14 @@
1
+ import { Observable } from 'rxjs';
2
+
3
+ /**
4
+ * 为 DOM 元素设置属性,包括静态属性和动态属性(Observable)。
5
+ *
6
+ * @param element - 要设置属性的 DOM 元素。
7
+ * @param props - 包含属性键值对的对象,其中值可以是普通值或 Observable。
8
+ * @returns 返回元素本身,支持链式调用。
9
+ * @throws 如果参数无效或设置属性失败会抛出错误。
10
+ */
11
+ export function setProps(
12
+ element: HTMLElement,
13
+ props: Record<string, any | Observable<any>>
14
+ ): HTMLElement;