gnim 1.3.7 → 1.4.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.
Binary file
package/dist/jsx/state.ts CHANGED
@@ -104,21 +104,63 @@ export function createState<T>(init: T): State<T> {
104
104
  return [new Accessor(() => currentValue, subscribe), set as Setter<T>]
105
105
  }
106
106
 
107
- /**
108
- * Create an `Accessor` which is computed from a list of `Accessor`s.
109
- *
110
- * ```ts Example
111
- * let a: Accessor<number>
112
- * let b: Accessor<string>
113
- * const c: Accessor<[number, string]> = createComputed([a, b])
114
- * const d: Accessor<string> = createComputed([a, b], (a: number, b: string) => `${a} ${b}`)
115
- * ```
116
- *
117
- * @param deps List of `Accessors`.
118
- * @param transform An optional transform function.
119
- * @returns The computed `Accessor`.
120
- */
121
- export function createComputed<
107
+ const empty = Symbol("empty computed value")
108
+
109
+ function createComputedProducer<T>(fn: (track: <V>(signal: Accessor<V>) => V) => T): Accessor<T> {
110
+ const subscribers = new Set<SubscribeCallback>()
111
+ let value: typeof empty | T
112
+ let prevDeps = new Map<Accessor, DisposeFunction>()
113
+
114
+ const effect = () => {
115
+ const deps = new Set<Accessor>()
116
+ value = fn((v) => (deps.add(v), v.get()))
117
+
118
+ const newDeps = new Map<Accessor, DisposeFunction>()
119
+
120
+ for (const [dep, unsub] of prevDeps) {
121
+ if (!deps.has(dep)) {
122
+ unsub()
123
+ } else {
124
+ newDeps.set(dep, unsub)
125
+ }
126
+ }
127
+
128
+ for (const dep of deps) {
129
+ if (!newDeps.has(dep)) {
130
+ newDeps.set(dep, dep.subscribe(effect))
131
+ }
132
+ }
133
+
134
+ prevDeps = newDeps
135
+ Array.from(subscribers).forEach((cb) => cb())
136
+ }
137
+
138
+ const subscribe: SubscribeFunction = (callback) => {
139
+ if (subscribers.size === 0) {
140
+ effect()
141
+ }
142
+
143
+ subscribers.add(callback)
144
+
145
+ return () => {
146
+ subscribers.delete(callback)
147
+ if (subscribers.size === 0) {
148
+ value = empty
149
+ for (const [, unsub] of prevDeps) {
150
+ unsub()
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ const get = (): T => {
157
+ return value === empty ? fn((v) => v.get()) : value
158
+ }
159
+
160
+ return new Accessor(get, subscribe)
161
+ }
162
+
163
+ function createComputedArgs<
122
164
  const Deps extends Array<Accessor<any>>,
123
165
  Args extends { [K in keyof Deps]: Accessed<Deps[K]> },
124
166
  V = Args,
@@ -167,6 +209,56 @@ export function createComputed<
167
209
  return new Accessor(get, subscribe)
168
210
  }
169
211
 
212
+ /**
213
+ * Create an `Accessor` from a producer function that tracks its dependencies.
214
+ *
215
+ * ```ts Example
216
+ * let a: Accessor<number>
217
+ * let b: Accessor<number>
218
+ * const c: Accessor<number> = createComputed((get) => get(a) + get(b))
219
+ * ```
220
+ *
221
+ * @experimental
222
+ * @param producer The producer function which let's you track dependencies
223
+ * @returns The computed `Accessor`.
224
+ */
225
+ export function createComputed<T>(
226
+ producer: (track: <V>(signal: Accessor<V>) => V) => T,
227
+ ): Accessor<T>
228
+
229
+ /**
230
+ * Create an `Accessor` which is computed from a list of given `Accessor`s.
231
+ *
232
+ * ```ts Example
233
+ * let a: Accessor<number>
234
+ * let b: Accessor<string>
235
+ * const c: Accessor<[number, string]> = createComputed([a, b])
236
+ * const d: Accessor<string> = createComputed([a, b], (a: number, b: string) => `${a} ${b}`)
237
+ * ```
238
+ *
239
+ * @param deps List of `Accessors`.
240
+ * @param transform An optional transform function.
241
+ * @returns The computed `Accessor`.
242
+ */
243
+ export function createComputed<
244
+ const Deps extends Array<Accessor<any>>,
245
+ Args extends { [K in keyof Deps]: Accessed<Deps[K]> },
246
+ T = Args,
247
+ >(deps: Deps, transform?: (...args: Args) => T): Accessor<T>
248
+
249
+ export function createComputed(
250
+ ...args:
251
+ | [producer: (track: <V>(signal: Accessor<V>) => V) => unknown]
252
+ | [deps: Array<Accessor>, transform?: (...args: unknown[]) => unknown]
253
+ ) {
254
+ const [depsOrProducer, transform] = args
255
+ if (typeof depsOrProducer === "function") {
256
+ return createComputedProducer(depsOrProducer)
257
+ } else {
258
+ return createComputedArgs(depsOrProducer, transform)
259
+ }
260
+ }
261
+
170
262
  /**
171
263
  * Create an `Accessor` on a `GObject.Object`'s `property`.
172
264
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnim",
3
- "version": "1.3.7",
3
+ "version": "1.4.0",
4
4
  "type": "module",
5
5
  "author": "Aylur",
6
6
  "license": "MIT",