@gtkx/react 1.4.0 → 1.5.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.
- package/README.md +1 -1
- package/dist/adw/element-behaviors.js +19 -107
- package/dist/adw/element-behaviors.js.map +1 -1
- package/dist/element-behaviors.js +21 -116
- package/dist/element-behaviors.js.map +1 -1
- package/dist/reconciler/behaviors.d.ts +19 -3
- package/dist/reconciler/behaviors.d.ts.map +1 -1
- package/dist/reconciler/behaviors.js +42 -17
- package/dist/reconciler/behaviors.js.map +1 -1
- package/package.json +5 -5
- package/src/adw/element-behaviors.ts +22 -162
- package/src/element-behaviors.ts +27 -167
- package/src/reconciler/behaviors.ts +81 -32
|
@@ -35,8 +35,24 @@ type ListEntry = { item: unknown; handle: unknown };
|
|
|
35
35
|
type ListState = { snapshot: unknown[]; entries: ListEntry[] };
|
|
36
36
|
type DeferredState = { desired: unknown; isPresent: boolean; isScheduled: boolean; disconnect: (() => void) | null };
|
|
37
37
|
type CanApply<P extends GObject.Object, V> = (object: P, value: V) => boolean;
|
|
38
|
+
|
|
39
|
+
type DeferredOps<P extends GObject.Object, V> = {
|
|
40
|
+
canApply?: CanApply<P, V> | undefined;
|
|
41
|
+
parse?: ((value: unknown) => V | undefined) | undefined;
|
|
42
|
+
read: (object: P) => unknown;
|
|
43
|
+
write: (object: P, value: V) => void;
|
|
44
|
+
signal?: string | undefined;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type DeferredHooks<P extends GObject.Object, V> = Omit<DeferredOps<P, V>, "read" | "write"> & {
|
|
48
|
+
read?: ((object: P) => unknown) | undefined;
|
|
49
|
+
write?: ((object: P, value: V) => void) | undefined;
|
|
50
|
+
};
|
|
51
|
+
|
|
38
52
|
type ChildSetter = GObject.Object & { setChild: (child: Gtk.Widget | null) => void };
|
|
39
53
|
type ContentSetter<C extends Gtk.Widget> = GObject.Object & { setContent: (content: C | null) => void };
|
|
54
|
+
type MatchingKey<P, F> = keyof P & string & { [K in keyof P]: P[K] extends F ? K : never }[keyof P];
|
|
55
|
+
type MethodKey<P, A> = MatchingKey<P, (argument: A) => unknown>;
|
|
40
56
|
|
|
41
57
|
type BoxLike = GObject.Object & {
|
|
42
58
|
remove: (child: Gtk.Widget) => void;
|
|
@@ -172,29 +188,31 @@ const list = <P extends GObject.Object, I, H = void>(
|
|
|
172
188
|
};
|
|
173
189
|
|
|
174
190
|
const settleDeferred = <P extends GObject.Object, V>(
|
|
175
|
-
object:
|
|
191
|
+
object: P,
|
|
176
192
|
state: DeferredState,
|
|
177
193
|
prop: string,
|
|
178
|
-
|
|
194
|
+
ops: DeferredOps<P, V>,
|
|
179
195
|
): void => {
|
|
180
|
-
if (!state.isPresent || Object.is(
|
|
196
|
+
if (!state.isPresent || Object.is(ops.read(object), state.desired)) {
|
|
181
197
|
return;
|
|
182
198
|
}
|
|
183
199
|
|
|
184
|
-
|
|
200
|
+
const desired = state.desired as V;
|
|
201
|
+
|
|
202
|
+
if (ops.canApply !== undefined && !ops.canApply(object, desired)) {
|
|
185
203
|
return;
|
|
186
204
|
}
|
|
187
205
|
|
|
188
206
|
applyWrite(prop, () => {
|
|
189
|
-
|
|
207
|
+
ops.write(object, desired);
|
|
190
208
|
});
|
|
191
209
|
};
|
|
192
210
|
|
|
193
211
|
const scheduleSettle = <P extends GObject.Object, V>(
|
|
194
|
-
object:
|
|
212
|
+
object: P,
|
|
195
213
|
state: DeferredState,
|
|
196
214
|
prop: string,
|
|
197
|
-
|
|
215
|
+
ops: DeferredOps<P, V>,
|
|
198
216
|
): void => {
|
|
199
217
|
if (state.isScheduled) {
|
|
200
218
|
return;
|
|
@@ -206,25 +224,25 @@ const scheduleSettle = <P extends GObject.Object, V>(
|
|
|
206
224
|
state.isScheduled = false;
|
|
207
225
|
|
|
208
226
|
if (state.disconnect !== null) {
|
|
209
|
-
settleDeferred(object, state, prop,
|
|
227
|
+
settleDeferred(object, state, prop, ops);
|
|
210
228
|
}
|
|
211
229
|
});
|
|
212
230
|
};
|
|
213
231
|
|
|
214
232
|
const watchDrift = <P extends GObject.Object, V>(
|
|
215
|
-
object:
|
|
233
|
+
object: P,
|
|
216
234
|
state: DeferredState,
|
|
217
235
|
prop: string,
|
|
218
|
-
|
|
236
|
+
ops: DeferredOps<P, V>,
|
|
219
237
|
): void => {
|
|
220
238
|
if (state.disconnect !== null) {
|
|
221
239
|
return;
|
|
222
240
|
}
|
|
223
241
|
|
|
224
|
-
const signal = `notify::${getPropertyName(object, prop) ?? unsanitizeIdentifier(kebabCase(prop))}`;
|
|
242
|
+
const signal = ops.signal ?? `notify::${getPropertyName(object, prop) ?? unsanitizeIdentifier(kebabCase(prop))}`;
|
|
225
243
|
|
|
226
244
|
const handler = (): undefined => {
|
|
227
|
-
scheduleSettle(object, state, prop,
|
|
245
|
+
scheduleSettle(object, state, prop, ops);
|
|
228
246
|
};
|
|
229
247
|
|
|
230
248
|
object.on(signal, handler);
|
|
@@ -234,23 +252,20 @@ const watchDrift = <P extends GObject.Object, V>(
|
|
|
234
252
|
};
|
|
235
253
|
};
|
|
236
254
|
|
|
237
|
-
const
|
|
238
|
-
prop: string,
|
|
239
|
-
canApply?: CanApply<P, V>,
|
|
240
|
-
): ElementBehavior<P> => ({
|
|
255
|
+
const deferredBehavior = <P extends GObject.Object, V>(prop: string, ops: DeferredOps<P, V>): ElementBehavior<P> => ({
|
|
241
256
|
deferred: [prop],
|
|
242
257
|
initialize: (): DeferredState => ({ desired: undefined, isPresent: false, isScheduled: false, disconnect: null }),
|
|
243
258
|
update: (_object, _prev, next, context) => {
|
|
244
259
|
const state = context as DeferredState;
|
|
245
|
-
state.desired = next[prop];
|
|
246
|
-
state.isPresent =
|
|
260
|
+
state.desired = ops.parse === undefined ? next[prop] : ops.parse(next[prop]);
|
|
261
|
+
state.isPresent = state.desired !== undefined;
|
|
247
262
|
|
|
248
263
|
return [prop];
|
|
249
264
|
},
|
|
250
265
|
flush: (object, context) => {
|
|
251
266
|
const state = context as DeferredState;
|
|
252
|
-
settleDeferred(object, state, prop,
|
|
253
|
-
watchDrift(object, state, prop,
|
|
267
|
+
settleDeferred(object, state, prop, ops);
|
|
268
|
+
watchDrift(object, state, prop, ops);
|
|
254
269
|
},
|
|
255
270
|
teardown: (_object, context) => {
|
|
256
271
|
const state = context as DeferredState;
|
|
@@ -259,6 +274,18 @@ const deferred = <P extends GObject.Object, V>(
|
|
|
259
274
|
},
|
|
260
275
|
});
|
|
261
276
|
|
|
277
|
+
const deferredWith = <P extends GObject.Object, V>(prop: string, hooks: DeferredHooks<P, V>): ElementBehavior<P> =>
|
|
278
|
+
deferredBehavior<P, V>(prop, {
|
|
279
|
+
...hooks,
|
|
280
|
+
read: hooks.read ?? ((object) => Reflect.get(object, prop)),
|
|
281
|
+
write: hooks.write ?? ((object, value) => {
|
|
282
|
+
Reflect.set(object, prop, value);
|
|
283
|
+
}),
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const deferred = <P extends GObject.Object, V>(prop: string, canApply?: CanApply<P, V>): ElementBehavior<P> =>
|
|
287
|
+
deferredWith<P, V>(prop, { canApply });
|
|
288
|
+
|
|
262
289
|
const controlledText = (prop: string): ElementBehavior =>
|
|
263
290
|
value(prop, (object, next) => {
|
|
264
291
|
if (!hasSameText(object, prop, next)) {
|
|
@@ -301,12 +328,39 @@ const boxSlot = <P extends BoxLike>(): ElementBehavior<P> =>
|
|
|
301
328
|
},
|
|
302
329
|
});
|
|
303
330
|
|
|
304
|
-
const
|
|
331
|
+
const callMethod = <P extends GObject.Object, A>(parent: P, method: MethodKey<P, A>, argument: A): unknown =>
|
|
332
|
+
(parent[method] as (argument: A) => unknown)(argument);
|
|
333
|
+
|
|
334
|
+
const methodSlot = <P extends GObject.Object, C extends GObject.Object>(
|
|
335
|
+
slotName: string,
|
|
336
|
+
childType: string,
|
|
337
|
+
add: MethodKey<P, C>,
|
|
338
|
+
remove?: MethodKey<P, C>,
|
|
339
|
+
): ElementBehavior => {
|
|
340
|
+
const hooks: SlotHooks<P, C> = { attach: (parent, child) => callMethod(parent, add, child) };
|
|
341
|
+
|
|
342
|
+
if (remove !== undefined) {
|
|
343
|
+
hooks.detach = (parent, child) => {
|
|
344
|
+
callMethod(parent, remove, child);
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return slot<P, C>(slotName, childType, hooks);
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const setterSlot = <P extends GObject.Object, C extends GObject.Object>(
|
|
305
352
|
slotName: string,
|
|
306
353
|
childType: string,
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
354
|
+
setter: MethodKey<P, C | null>,
|
|
355
|
+
): ElementBehavior =>
|
|
356
|
+
slot<P, C>(slotName, childType, {
|
|
357
|
+
attach: (parent, child) => {
|
|
358
|
+
callMethod<P, C | null>(parent, setter, child);
|
|
359
|
+
},
|
|
360
|
+
detach: (parent) => {
|
|
361
|
+
callMethod<P, C | null>(parent, setter, null);
|
|
362
|
+
},
|
|
363
|
+
});
|
|
310
364
|
|
|
311
365
|
const indexedSlot = <P extends IndexedChildHost<C>, C extends GObject.Object>(
|
|
312
366
|
slotName: string,
|
|
@@ -325,12 +379,6 @@ const indexedSlot = <P extends IndexedChildHost<C>, C extends GObject.Object>(
|
|
|
325
379
|
},
|
|
326
380
|
});
|
|
327
381
|
|
|
328
|
-
const adoptedChildrenSlot = <P extends GObject.Object, C extends GObject.Object>(
|
|
329
|
-
childType: string,
|
|
330
|
-
add: (parent: P, item: C) => unknown,
|
|
331
|
-
remove: (parent: P, item: C) => void,
|
|
332
|
-
): ElementBehavior => addRemoveSlot<C, P>("children", childType, add, remove);
|
|
333
|
-
|
|
334
382
|
const wrappedRow = <W extends Gtk.Widget>(
|
|
335
383
|
Wrapper: new (props: Props) => W,
|
|
336
384
|
setChild: (wrapper: W, inner: Gtk.Widget) => void,
|
|
@@ -394,12 +442,13 @@ export {
|
|
|
394
442
|
value,
|
|
395
443
|
list,
|
|
396
444
|
deferred,
|
|
445
|
+
deferredWith,
|
|
397
446
|
controlledText,
|
|
398
447
|
childSetterSlot,
|
|
399
448
|
contentSetterSlot,
|
|
400
449
|
boxSlot,
|
|
401
|
-
|
|
402
|
-
|
|
450
|
+
methodSlot,
|
|
451
|
+
setterSlot,
|
|
403
452
|
indexedSlot,
|
|
404
453
|
wrappingIndexedSlot,
|
|
405
454
|
};
|