grainjs 1.0.1 → 1.1.0

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 (146) hide show
  1. package/README.md +23 -26
  2. package/dist/cjs/index.js +28 -17
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/lib/PriorityQueue.d.ts +2 -2
  5. package/dist/cjs/lib/PriorityQueue.js +1 -0
  6. package/dist/cjs/lib/PriorityQueue.js.map +1 -1
  7. package/dist/cjs/lib/_computed_queue.js +4 -3
  8. package/dist/cjs/lib/_computed_queue.js.map +1 -1
  9. package/dist/cjs/lib/binding.d.ts +11 -4
  10. package/dist/cjs/lib/binding.js +6 -5
  11. package/dist/cjs/lib/binding.js.map +1 -1
  12. package/dist/cjs/lib/browserGlobals.d.ts +4 -1
  13. package/dist/cjs/lib/browserGlobals.js +2 -0
  14. package/dist/cjs/lib/browserGlobals.js.map +1 -1
  15. package/dist/cjs/lib/computed.d.ts +49 -28
  16. package/dist/cjs/lib/computed.js +38 -51
  17. package/dist/cjs/lib/computed.js.map +1 -1
  18. package/dist/cjs/lib/dispose.d.ts +109 -96
  19. package/dist/cjs/lib/dispose.js +106 -79
  20. package/dist/cjs/lib/dispose.js.map +1 -1
  21. package/dist/cjs/lib/dom.d.ts +40 -18
  22. package/dist/cjs/lib/dom.js +63 -29
  23. package/dist/cjs/lib/dom.js.map +1 -1
  24. package/dist/cjs/lib/domComponent.d.ts +56 -51
  25. package/dist/cjs/lib/domComponent.js +46 -44
  26. package/dist/cjs/lib/domComponent.js.map +1 -1
  27. package/dist/cjs/lib/domComputed.d.ts +50 -20
  28. package/dist/cjs/lib/domComputed.js +37 -7
  29. package/dist/cjs/lib/domComputed.js.map +1 -1
  30. package/dist/cjs/lib/domDispose.d.ts +27 -12
  31. package/dist/cjs/lib/domDispose.js +27 -11
  32. package/dist/cjs/lib/domDispose.js.map +1 -1
  33. package/dist/cjs/lib/domForEach.d.ts +5 -4
  34. package/dist/cjs/lib/domForEach.js +41 -41
  35. package/dist/cjs/lib/domForEach.js.map +1 -1
  36. package/dist/cjs/lib/domImpl.d.ts +33 -10
  37. package/dist/cjs/lib/domImpl.js +29 -9
  38. package/dist/cjs/lib/domImpl.js.map +1 -1
  39. package/dist/cjs/lib/domMethods.d.ts +93 -47
  40. package/dist/cjs/lib/domMethods.js +91 -47
  41. package/dist/cjs/lib/domMethods.js.map +1 -1
  42. package/dist/cjs/lib/domevent.d.ts +87 -62
  43. package/dist/cjs/lib/domevent.js +85 -59
  44. package/dist/cjs/lib/domevent.js.map +1 -1
  45. package/dist/cjs/lib/emit.d.ts +62 -32
  46. package/dist/cjs/lib/emit.js +68 -53
  47. package/dist/cjs/lib/emit.js.map +1 -1
  48. package/dist/cjs/lib/kowrap.d.ts +6 -3
  49. package/dist/cjs/lib/kowrap.js +7 -3
  50. package/dist/cjs/lib/kowrap.js.map +1 -1
  51. package/dist/cjs/lib/obsArray.d.ts +91 -53
  52. package/dist/cjs/lib/obsArray.js +87 -54
  53. package/dist/cjs/lib/obsArray.js.map +1 -1
  54. package/dist/cjs/lib/observable.d.ts +25 -15
  55. package/dist/cjs/lib/observable.js +31 -19
  56. package/dist/cjs/lib/observable.js.map +1 -1
  57. package/dist/cjs/lib/pureComputed.d.ts +12 -15
  58. package/dist/cjs/lib/pureComputed.js +16 -18
  59. package/dist/cjs/lib/pureComputed.js.map +1 -1
  60. package/dist/cjs/lib/styled.d.ts +78 -61
  61. package/dist/cjs/lib/styled.js +27 -79
  62. package/dist/cjs/lib/styled.js.map +1 -1
  63. package/dist/cjs/lib/subscribe.d.ts +41 -37
  64. package/dist/cjs/lib/subscribe.js +31 -39
  65. package/dist/cjs/lib/subscribe.js.map +1 -1
  66. package/dist/cjs/lib/util.js +2 -0
  67. package/dist/cjs/lib/util.js.map +1 -1
  68. package/dist/cjs/lib/widgets/input.d.ts +3 -1
  69. package/dist/cjs/lib/widgets/input.js +7 -4
  70. package/dist/cjs/lib/widgets/input.js.map +1 -1
  71. package/dist/cjs/lib/widgets/select.d.ts +4 -2
  72. package/dist/cjs/lib/widgets/select.js +8 -5
  73. package/dist/cjs/lib/widgets/select.js.map +1 -1
  74. package/dist/esm/lib/_computed_queue.js +3 -3
  75. package/dist/esm/lib/_computed_queue.js.map +1 -1
  76. package/dist/esm/lib/binding.js +2 -2
  77. package/dist/esm/lib/binding.js.map +1 -1
  78. package/dist/esm/lib/browserGlobals.js +1 -0
  79. package/dist/esm/lib/browserGlobals.js.map +1 -1
  80. package/dist/esm/lib/computed.js +36 -50
  81. package/dist/esm/lib/computed.js.map +1 -1
  82. package/dist/esm/lib/dispose.js +104 -78
  83. package/dist/esm/lib/dispose.js.map +1 -1
  84. package/dist/esm/lib/dom.js +40 -18
  85. package/dist/esm/lib/dom.js.map +1 -1
  86. package/dist/esm/lib/domComponent.js +45 -44
  87. package/dist/esm/lib/domComponent.js.map +1 -1
  88. package/dist/esm/lib/domComputed.js +32 -5
  89. package/dist/esm/lib/domComputed.js.map +1 -1
  90. package/dist/esm/lib/domDispose.js +26 -11
  91. package/dist/esm/lib/domDispose.js.map +1 -1
  92. package/dist/esm/lib/domForEach.js +40 -41
  93. package/dist/esm/lib/domForEach.js.map +1 -1
  94. package/dist/esm/lib/domImpl.js +26 -7
  95. package/dist/esm/lib/domImpl.js.map +1 -1
  96. package/dist/esm/lib/domMethods.js +77 -35
  97. package/dist/esm/lib/domMethods.js.map +1 -1
  98. package/dist/esm/lib/domevent.js +84 -59
  99. package/dist/esm/lib/domevent.js.map +1 -1
  100. package/dist/esm/lib/emit.js +67 -53
  101. package/dist/esm/lib/emit.js.map +1 -1
  102. package/dist/esm/lib/kowrap.js +5 -2
  103. package/dist/esm/lib/kowrap.js.map +1 -1
  104. package/dist/esm/lib/obsArray.js +82 -50
  105. package/dist/esm/lib/obsArray.js.map +1 -1
  106. package/dist/esm/lib/observable.js +26 -15
  107. package/dist/esm/lib/observable.js.map +1 -1
  108. package/dist/esm/lib/pureComputed.js +15 -18
  109. package/dist/esm/lib/pureComputed.js.map +1 -1
  110. package/dist/esm/lib/styled.js +24 -77
  111. package/dist/esm/lib/styled.js.map +1 -1
  112. package/dist/esm/lib/subscribe.js +27 -36
  113. package/dist/esm/lib/subscribe.js.map +1 -1
  114. package/dist/esm/lib/util.js +1 -0
  115. package/dist/esm/lib/util.js.map +1 -1
  116. package/dist/esm/lib/widgets/input.js +3 -1
  117. package/dist/esm/lib/widgets/input.js.map +1 -1
  118. package/dist/esm/lib/widgets/select.js +3 -1
  119. package/dist/esm/lib/widgets/select.js.map +1 -1
  120. package/dist/grain-full.debug.js +2138 -3052
  121. package/dist/grain-full.debug.js.map +7 -0
  122. package/dist/grain-full.min.js +6 -2
  123. package/dist/grain-full.min.js.map +7 -1
  124. package/lib/binding.ts +9 -2
  125. package/lib/browserGlobals.ts +3 -1
  126. package/lib/computed.ts +56 -56
  127. package/lib/dispose.ts +110 -85
  128. package/lib/dom.ts +41 -20
  129. package/lib/domComponent.ts +68 -70
  130. package/lib/domComputed.ts +66 -21
  131. package/lib/domDispose.ts +28 -11
  132. package/lib/domForEach.ts +13 -12
  133. package/lib/domImpl.ts +30 -7
  134. package/lib/domMethods.ts +101 -46
  135. package/lib/domevent.ts +86 -61
  136. package/lib/emit.ts +64 -50
  137. package/lib/kowrap.ts +5 -2
  138. package/lib/obsArray.ts +89 -54
  139. package/lib/observable.ts +26 -15
  140. package/lib/pureComputed.ts +16 -22
  141. package/lib/styled.ts +85 -71
  142. package/lib/subscribe.ts +41 -45
  143. package/lib/util.ts +1 -0
  144. package/lib/widgets/input.ts +3 -1
  145. package/lib/widgets/select.ts +3 -1
  146. package/package.json +48 -38
package/lib/styled.ts CHANGED
@@ -1,87 +1,85 @@
1
+ // Use the browser globals in a way that allows replacing them with mocks in tests.
2
+ import {G} from './browserGlobals';
3
+ import {dom, IDomArgs, TagElem, TagName} from './domImpl';
4
+ import {cls, clsPrefix} from './domMethods';
5
+
6
+ // The value returned by styled() matches the input (first argument), and also implements IClsName
7
+ // interface.
8
+ export interface IClsName {
9
+ className: string; // Name of the generated class.
10
+ cls: typeof cls; // Helper like dom.cls(), but which prefixes classes by className.
11
+ }
12
+
13
+ export type DomCreateFunc<R, Args extends IDomArgs<R> = IDomArgs<R>> = (...args: Args) => R;
14
+
1
15
  /**
2
16
  * In-code styling for DOM components, inspired by Reacts Styled Components.
3
17
  *
4
18
  * Usage:
5
- * const title = styled('h1', `
6
- * font-size: 1.5em;
7
- * text-align: center;
8
- * color: palevioletred;
9
- * `);
10
- *
11
- * const wrapper = styled('section', `
12
- * padding: 4em;
13
- * background: papayawhip;
14
- * `);
15
- *
16
- * wrapper(title('Hello world'))
17
- *
18
- * This generates class names for title and wrapper, adds the styles to the document on first use,
19
- * and the result is equivalent to:
20
- *
21
- * dom(`section.${wrapper.className}`, dom(`h1.${title.className}`, 'Hello world'));
22
- *
23
- * Calls to styled() should happen at the top level, at import time, in order to register all
19
+ * ```ts
20
+ * const cssTitle = styled('h1', `
21
+ * font-size: 1.5em;
22
+ * text-align: center;
23
+ * color: palevioletred;
24
+ * `);
25
+ *
26
+ * const cssWrapper = styled('section', `
27
+ * padding: 4em;
28
+ * background: papayawhip;
29
+ * `);
30
+ *
31
+ * cssWrapper(cssTitle('Hello world'))
32
+ * ```
33
+ *
34
+ * This generates class names for `cssTitle` and `cssWrapper`, adds the styles to the document on
35
+ * first use, and the result is equivalent to:
36
+ * ```ts
37
+ * dom(`section.${cssWrapper.className}`, dom(`h1.${cssTitle.className}`, 'Hello world'));
38
+ * ```
39
+ *
40
+ * What `styled(tag)` returns is a function that takes the same arguments `...args` as
41
+ * `dom(tag, ...args)`. In particular, you may call it with all the arguments that
42
+ * [`dom()`](#dom) takes: content, DOM methods, event handlers, etc.
43
+ *
44
+ * Calls to `styled()` should happen at the top level, at import time, in order to register all
24
45
  * styles upfront. Actual work happens the first time a style is needed to create an element.
25
- * Calling styled() elsewhere than at top level is wasteful and bad for performance.
26
- *
27
- * You may create a style that modifies an existing styled() or other component, e.g.
46
+ * Calling `styled()` elsewhere than at top level is wasteful and bad for performance.
28
47
  *
29
- * const title2 = styled(title, `font-size: 1rem; color: red;`);
48
+ * You may create a style that modifies an existing `styled()` or other component, e.g.
49
+ * ```ts
50
+ * const cssTitle2 = styled(cssTitle, `font-size: 1rem; color: red;`);
51
+ * ```
30
52
  *
31
- * Calling title2('Foo') becomes equivalent to dom(`h1.${title.className}.${title2.className}`).
53
+ * Now calling `cssTitle2('Foo')` becomes equivalent to
54
+ * `dom('h1', {className: cssTitle.className + ' ' + cssTitle2.className})`.
32
55
  *
33
56
  * Styles may incorporate other related styles by nesting them under the main one as follows:
34
- *
35
- * const myButton = styled('button', `
36
- * border-radius: 0.5rem;
37
- * border: 1px solid grey;
38
- * font-size: 1rem;
39
- *
40
- * &:active {
41
- * background: lightblue;
42
- * }
43
- * &-small {
44
- * font-size: 0.6rem;
45
- * }
46
- * `);
57
+ * ```ts
58
+ * const myButton = styled('button', `
59
+ * border-radius: 0.5rem;
60
+ * border: 1px solid grey;
61
+ * font-size: 1rem;
62
+ *
63
+ * &:active {
64
+ * background: lightblue;
65
+ * }
66
+ * &-small {
67
+ * font-size: 0.6rem;
68
+ * }
69
+ * `);
70
+ * ```
47
71
  *
48
72
  * In nested styles, ampersand (&) gets replaced with the generated .className of the main element.
49
73
  *
50
- * The resulting styled component provides a .cls() helper to simplify using prefixed classes. It
51
- * behaves as dom.cls(), but prefixes the class names with the generated className of the main
74
+ * The resulting styled component provides a `.cls()` helper to simplify using prefixed classes. It
75
+ * behaves as `dom.cls()`, but prefixes the class names with the generated className of the main
52
76
  * element. E.g. for the example above,
77
+ * ```ts
78
+ * myButton(myButton.cls('-small'), 'Test')
79
+ * ```
53
80
  *
54
- * myButton(myButton.cls('-small'), 'Test')
55
- *
56
- * creates a button with both the myButton style above, and the style specified under "&-small".
57
- *
58
- * Animations with @keyframes may be created with a unique name by using the keyframes() helper:
59
- *
60
- * const rotate360 = keyframes(`
61
- * from { transform: rotate(0deg); }
62
- * to { transform: rotate(360deg); }
63
- * `);
64
- *
65
- * const Rotate = styled('div', `
66
- * display: inline-block;
67
- * animation: ${rotate360} 2s linear infinite;
68
- * `);
81
+ * creates a button with both the `myButton` style above, and the style specified under "&-small".
69
82
  */
70
-
71
- // Use the browser globals in a way that allows replacing them with mocks in tests.
72
- import {G} from './browserGlobals';
73
- import {dom, IDomArgs, TagElem, TagName} from './domImpl';
74
- import {cls, clsPrefix} from './domMethods';
75
-
76
- // The value returned by styled() matches the input (first argument), and also implements IClsName
77
- // interface.
78
- export interface IClsName {
79
- className: string; // Name of the generated class.
80
- cls: typeof cls; // Helper like dom.cls(), but which prefixes classes by className.
81
- }
82
-
83
- export type DomCreateFunc<R, Args extends IDomArgs<R> = IDomArgs<R>> = (...args: Args) => R;
84
-
85
83
  // See module documentation for details.
86
84
  export function styled<Tag extends TagName>(tag: Tag, styles: string): DomCreateFunc<TagElem<Tag>> & IClsName;
87
85
  export function styled<Args extends any[], R extends Element>(
@@ -102,8 +100,24 @@ export function styled(creator: any, styles: string): IClsName {
102
100
  });
103
101
  }
104
102
 
105
- // Keyframes produces simply a string with the generated name. Note that these does not support
106
- // nesting or ampersand (&) handling, since these would be difficult and are entirely unneeded.
103
+ /**
104
+ * Animations with `@keyframes` may be created with a unique name by using the keyframes() helper:
105
+ * ```ts
106
+ * const rotate360 = keyframes(`
107
+ * from { transform: rotate(0deg); }
108
+ * to { transform: rotate(360deg); }
109
+ * `);
110
+ *
111
+ * const Rotate = styled('div', `
112
+ * display: inline-block;
113
+ * animation: ${rotate360} 2s linear infinite;
114
+ * `);
115
+ * ```
116
+ *
117
+ * This function returns simply a string with the generated name. Note that keyframes do not
118
+ * support nesting or ampersand (&) handling, like `styled()` does, since these would be difficult
119
+ * and are entirely unneeded.
120
+ */
107
121
  export function keyframes(styles: string): string {
108
122
  return (new KeyframePiece(styles)).className;
109
123
  }
package/lib/subscribe.ts CHANGED
@@ -1,23 +1,3 @@
1
- /**
2
- * subscribe.js implements subscriptions to several observables at once.
3
- *
4
- * E.g. if we have some existing observables (which may be instances of `computed`),
5
- * we can subscribe to them explicitly:
6
- * let obs1 = observable(5), obs2 = observable(12);
7
- * subscribe(obs1, obs2, (use, v1, v2) => console.log(v1, v2));
8
- *
9
- * or implicitly by using `use(obs)` function, which allows dynamic subscriptions:
10
- * subscribe(use => console.log(use(obs1), use(obs2)));
11
- *
12
- * In either case, if obs1 or obs2 is changed, the callbacks will get called automatically.
13
- *
14
- * Creating a subscription allows any number of dependencies to be specified explicitly, and their
15
- * values will be passed to the callback(). These may be combined with automatic dependencies
16
- * detected using use(). Note that constructor dependencies have less overhead.
17
- *
18
- * subscribe(...deps, ((use, ...depValues) => READ_CALLBACK));
19
- */
20
-
21
1
  import {DepItem} from './_computed_queue';
22
2
  import {IDisposableOwner} from './dispose';
23
3
  import {Listener} from './emit';
@@ -25,6 +5,7 @@ import {fromKo, IKnockoutReadObservable} from './kowrap';
25
5
  import {BaseObservable as Obs} from './observable';
26
6
 
27
7
  export interface ISubscribableObs {
8
+ /** @internal */
28
9
  _getDepItem(): DepItem|null;
29
10
  addListener(callback: (val: any, prev: any) => void, optContext?: object): Listener;
30
11
  get(): any;
@@ -52,6 +33,31 @@ interface IListenerWithInUse extends Listener {
52
33
  // Constant empty array, which we use to avoid allocating new read-only empty arrays.
53
34
  const emptyArray: ReadonlyArray<any> = [];
54
35
 
36
+ /**
37
+ * `Subscription` allows subscribing to several observables at once. It's the foundation for a
38
+ * `Computed`, but may also be used directly.
39
+ *
40
+ * E.g. if we have some existing observables (which may be instances of `Computed`),
41
+ * we can subscribe to them explicitly:
42
+ * ```ts
43
+ * const obs1 = observable(5), obs2 = observable(12);
44
+ * subscribe(obs1, obs2, (use, v1, v2) => console.log(v1, v2));
45
+ * ```
46
+ *
47
+ * or implicitly by using `use(obs)` function, which allows dynamic subscriptions:
48
+ * ```ts
49
+ * subscribe(use => console.log(use(obs1), use(obs2)));
50
+ * ```
51
+ *
52
+ * In either case, if `obs1` or `obs2` is changed, the callbacks will get called automatically.
53
+ *
54
+ * Creating a subscription allows any number of dependencies to be specified explicitly, and their
55
+ * values will be passed to the `callback`. These may be combined with automatic dependencies
56
+ * detected using `use()`. Note that constructor dependencies have less overhead.
57
+ * ```ts
58
+ * subscribe(...deps, ((use, ...depValues) => READ_CALLBACK));
59
+ * ```
60
+ */
55
61
  export class Subscription {
56
62
  private readonly _depItem: DepItem;
57
63
  private readonly _dependencies: ReadonlyArray<ISubscribableObs>;
@@ -60,11 +66,9 @@ export class Subscription {
60
66
  private _callback: (use: UseCB, ...args: any[]) => void;
61
67
  private _useFunc: UseCB;
62
68
 
63
- /**
64
- * Internal constructor for a Subscription. You should use subscribe() function instead.
65
- * The last owner argument is used by computed() to make itself available as the .owner property
66
- * of the 'use' function that gets passed to the callback.
67
- */
69
+ // Internal constructor for a Subscription. You should use subscribe() function instead.
70
+ // The last owner argument is used by computed() to make itself available as the .owner property
71
+ // of the 'use' function that gets passed to the callback.
68
72
  constructor(callback: (use: UseCB, ...args: any[]) => void, dependencies: ReadonlyArray<ISubscribable>, owner?: any) {
69
73
  this._depItem = new DepItem(this._evaluate, this);
70
74
  this._dependencies = dependencies.length > 0 ? dependencies : emptyArray;
@@ -90,14 +94,14 @@ export class Subscription {
90
94
 
91
95
  /**
92
96
  * For use by computed(): returns this subscription's hook into the _computed_queue.
97
+ * @internal
93
98
  */
94
99
  public _getDepItem(): DepItem { return this._depItem; }
95
100
 
96
101
  /**
97
- * @private
98
102
  * Gets called when the callback calls `use(obs)` for an observable. It creates a
99
103
  * subscription to `obs` if one doesn't yet exist.
100
- * @param {Observable} obs: The observable being used as a dependency.
104
+ * @param obs - The observable being used as a dependency.
101
105
  */
102
106
  private _useDependency(_obs: ISubscribable) {
103
107
  const obs = ('_getDepItem' in _obs) ? _obs : fromKo(_obs);
@@ -112,7 +116,6 @@ export class Subscription {
112
116
  }
113
117
 
114
118
  /**
115
- * @private
116
119
  * Calls the callback() with appropriate args, and updates subscriptions when it is done.
117
120
  * I.e. adds dynamic subscriptions created via `use(obs)`, and disposes those no longer used.
118
121
  */
@@ -140,10 +143,9 @@ export class Subscription {
140
143
  }
141
144
 
142
145
  /**
143
- * @private
144
146
  * Subscribes this computed to another observable that it depends on.
145
- * @param {Observable} obs: The observable to subscribe to.
146
- * @returns {Listener} Listener object.
147
+ * @param obs - The observable to subscribe to.
148
+ * @returns Listener object.
147
149
  */
148
150
  private _subscribeTo(_obs: ISubscribable) {
149
151
  const obs = ('_getDepItem' in _obs) ? _obs : fromKo(_obs);
@@ -151,7 +153,6 @@ export class Subscription {
151
153
  }
152
154
 
153
155
  /**
154
- * @private
155
156
  * Adds this item to the recompute queue.
156
157
  */
157
158
  private _enqueue() {
@@ -160,9 +161,14 @@ export class Subscription {
160
161
  }
161
162
 
162
163
  /**
163
- * This is the type-checking interface for subscribe(), which allows TypeScript to do helpful
164
- * type-checking when using it. We can only support a fixed number of argumnets (explicit
165
- * dependencies), but 5 should almost always be enough.
164
+ * Creates a new Subscription.
165
+ * @param observables - The initial params, of which there may be zero or more, are
166
+ * observables on which this computed depends. When any of them change, the `callback`
167
+ * will be called with the values of these observables as arguments.
168
+ * @param callback - will be called with arguments `(use, ...values)`, i.e. the
169
+ * `use` function and values for all of the `...observables` that precede this argument.
170
+ * This callback is called immediately, and whenever any dependency changes.
171
+ * @returns The new `Subscription` which may be disposed to unsubscribe.
166
172
  */
167
173
  export function subscribe(cb: (use: UseCB) => void): Subscription;
168
174
 
@@ -186,16 +192,6 @@ export function subscribe<A, B, C, D, E>(
186
192
  a: Obs<A>, b: Obs<B>, c: Obs<C>, d: Obs<D>, e: Obs<E>,
187
193
  cb: (use: UseCB, a: A, b: B, c: C, d: D, e: E) => void): Subscription;
188
194
 
189
- /**
190
- * Creates a new Subscription.
191
- * @param {Observable} ...observables: The initial params, of which there may be zero or more, are
192
- * observables on which this computed depends. When any of them change, the callback()
193
- * will be called with the values of these observables as arguments.
194
- * @param {Function} callback: will be called with arguments (use, ...values), i.e. the
195
- * `use` function and values for all of the ...observables that precede this argument.
196
- * This callback is called immediately, and whenever any dependency changes.
197
- * @returns {Subscription} The new subscription which may be disposed to unsubscribe.
198
- */
199
195
  export function subscribe(...args: any[]): Subscription {
200
196
  const cb = args.pop();
201
197
  // The cast helps ensure that Observable is compatible with ISubscribable abstraction that we use.
package/lib/util.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint-disable prefer-spread */
1
2
 
2
3
  /**
3
4
  * Returns f such that f() calls func(...boundArgs), i.e. optimizes `() => func(...boundArgs)`.
@@ -19,13 +19,15 @@ export interface IInputOptions {
19
19
  * number, tel.
20
20
  *
21
21
  * Note that every change to the observable will affect the input element, but not every change to
22
- * the input element will affect the observable. Specifically, unless {onInput: true} is set, the
22
+ * the input element will affect the observable. Specifically, unless `{onInput: true}` is set, the
23
23
  * visible content may differ from the observable until the element loses focus or Enter is hit.
24
24
  *
25
25
  * Example usage:
26
+ * ```
26
27
  * input(obs, {}, {type: 'text', placeholder: 'Your name...'});
27
28
  * input(obs, {isValid: isValidObs}, {type: 'email', placeholder: 'Your email...'});
28
29
  * input(obs, {onInput: true}, {type: 'text'});
30
+ * ```
29
31
  */
30
32
  export function input(
31
33
  obs: Observable<string>, options: IInputOptions, ...args: IDomArgs<HTMLInputElement>
@@ -24,7 +24,7 @@ function getOptionValue<T>(option: IOption<T>): T {
24
24
  /**
25
25
  * Creates a select dropdown widget. The observable `obs` reflects the value of the selected
26
26
  * option, and `optionArray` is an array (regular or observable) of option values and labels.
27
- * These may be either strings, or {label, value, disabled} objects.
27
+ * These may be either strings, or `{label, value, disabled}` objects.
28
28
  *
29
29
  * The type of value may be any type at all; it is opaque to this widget.
30
30
  *
@@ -32,6 +32,7 @@ function getOptionValue<T>(option: IOption<T>): T {
32
32
  * label that the select box will show, blank by default.
33
33
  *
34
34
  * Usage:
35
+ * ```
35
36
  * const fruit = observable("apple");
36
37
  * select(fruit, ["apple", "banana", "mango"]);
37
38
  *
@@ -42,6 +43,7 @@ function getOptionValue<T>(option: IOption<T>): T {
42
43
  * {value: 21, label: "Eve"},
43
44
  * ]);
44
45
  * select(employee, employees, {defLabel: "Select employee:"});
46
+ * ```
45
47
  */
46
48
  export function select<T>(obs: Observable<T>, optionArray: MaybeObsArray<IOption<T>>,
47
49
  options: {defLabel?: string} = {}) {
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "grainjs",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "JS library from Grist Labs",
5
5
  "main": "dist/cjs/index",
6
6
  "module": "dist/esm/index",
7
- "types": "dist/cjs/index",
7
+ "types": "dist/cjs/index.d.ts",
8
8
  "scripts": {
9
9
  "build": "bash build.sh",
10
10
  "watch": "tsc -w",
@@ -16,8 +16,12 @@
16
16
  "test-browser-headless": "MOCHA_WEBDRIVER_ARGS='--no-sandbox --disable-gpu' MOCHA_WEBDRIVER_HEADLESS=1 mocha 'test/browser/*.{js,ts}'",
17
17
  "test-browser": "mocha 'test/browser/*.{js,ts}'",
18
18
  "test-browser-debug": "mocha --bail --no-exit 'test/browser/*.{js,ts}'",
19
- "test-types": "dtslint --onlyTestTsNext --expectOnly test/types",
20
- "prepack": "npm run build && npm test"
19
+ "test-types": "tsd --files 'test/types/**/*.ts'",
20
+ "prepack": "npm run build && npm test",
21
+ "docs:dev": "vitepress dev docs",
22
+ "docs:build": "vitepress build docs",
23
+ "docs:build-api": "tsc -p tsconfig/tsconfig.es2015.cjs.json && api-extractor run --local --verbose && node scripts/generate-api-md.js",
24
+ "docs:preview": "vitepress preview docs"
21
25
  },
22
26
  "keywords": [
23
27
  "grist",
@@ -44,6 +48,11 @@
44
48
  },
45
49
  "homepage": "https://github.com/gristlabs/grainjs#readme",
46
50
  "nyc": {
51
+ "reporter": [
52
+ "html",
53
+ "text",
54
+ "lcov"
55
+ ],
47
56
  "extension": [
48
57
  ".ts"
49
58
  ],
@@ -55,41 +64,42 @@
55
64
  "owner": "gristlabs",
56
65
  "repo": "grainjs"
57
66
  },
58
- "dependencies": {},
59
67
  "devDependencies": {
60
- "@types/chai": "^4.1.2",
61
- "@types/chai-as-promised": "^7.1.0",
62
- "@types/jsdom": "^12.2.0",
63
- "@types/lodash": "^4.14.100",
64
- "@types/mocha": "^5.2.5",
65
- "@types/node": "^11.13.8",
66
- "@types/selenium-webdriver": "^4.0.0",
67
- "@types/sinon": "^7.0.11",
68
- "@types/webpack-dev-server": "^3.1.5",
69
- "browserify": "^16.2.3",
70
- "chai": "^4.1.0",
71
- "chai-as-promised": "^7.1.1",
72
- "chromedriver": "^74.0.0",
73
- "create-react-app": "^3.0.0",
74
- "dtslint": "^0.7.1",
75
- "fastpriorityqueue": "^0.6.1",
76
- "geckodriver": "^1.11.0",
77
- "jsdom": "15.0.0",
78
- "knockout": "^3.5.0",
79
- "lodash": "^4.17.15",
80
- "mocha": "^6.1.4",
81
- "mocha-webdriver": "^0.1.13",
82
- "nyc": "^14.0.0",
83
- "selenium-webdriver": "^4.0.0-alpha.1",
84
- "sinon": "^7.1.0",
85
- "ts-loader": "^5.2.2",
86
- "ts-node": "^8.1.0",
87
- "tslint": "^5.11.0",
88
- "typescript": "~3.4.5",
89
- "typescript-tslint-plugin": "^0.3.1",
68
+ "@microsoft/api-extractor": "^7.55.1",
69
+ "@types/chai": "^4.2.18",
70
+ "@types/chai-as-promised": "^7.1.4",
71
+ "@types/jsdom": "^16.2.11",
72
+ "@types/lodash": "^4.14.170",
73
+ "@types/mocha": "^8.2.2",
74
+ "@types/node": "^22",
75
+ "@types/selenium-webdriver": "^4.0.13",
76
+ "@types/sinon": "^21.0.0",
77
+ "chai": "^6.2.1",
78
+ "chai-as-promised": "^8.0.2",
79
+ "esbuild": "^0.27.2",
80
+ "eslint": "^9.39.2",
81
+ "fastpriorityqueue": "^0.7.5",
82
+ "jsdom": "27.3.0",
83
+ "knockout": "^3.5.1",
84
+ "lodash": "^4.17.21",
85
+ "markdown-it-multimd-table": "^4.2.3",
86
+ "mocha": "^11.7.5",
87
+ "mocha-webdriver": "^0.3.4",
88
+ "nyc": "^17.1.0",
89
+ "selenium-webdriver": "^4.38.0",
90
+ "sinon": "^21.0.0",
91
+ "ts-loader": "^9.2.3",
92
+ "ts-node": "^10.9.2",
93
+ "tsd": "^0.27.0",
94
+ "typescript": "^4",
95
+ "typescript-eslint": "^8.50.0",
96
+ "typescript-tslint-plugin": "^1.0.1",
90
97
  "uglify-es": "^3.2.0",
91
- "webpack": "^4.15.1",
92
- "webpack-cli": "^3.0.8",
93
- "webpack-dev-server": "^3.3.1"
98
+ "vitepress": "^1.6.4",
99
+ "webpack": "^5.104.0",
100
+ "webpack-dev-server": "^5.2.2"
101
+ },
102
+ "overrides": {
103
+ "esbuild": "^0.27.2"
94
104
  }
95
105
  }