@gtkx/react 1.1.0 → 1.2.1

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.
@@ -0,0 +1,4 @@
1
+ import { type RefObject } from "react";
2
+ declare function useLatestRef<T>(value: T): RefObject<T>;
3
+ export { useLatestRef };
4
+ //# sourceMappingURL=use-latest-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-latest-ref.d.ts","sourceRoot":"","sources":["../../src/hooks/use-latest-ref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAA8B,MAAM,OAAO,CAAC;AAEnE,iBAAS,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAQ/C;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { useInsertionEffect, useRef } from "react";
2
+ function useLatestRef(value) {
3
+ const ref = useRef(value);
4
+ useInsertionEffect(() => {
5
+ ref.current = value;
6
+ });
7
+ return ref;
8
+ }
9
+ export { useLatestRef };
10
+ //# sourceMappingURL=use-latest-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-latest-ref.js","sourceRoot":"","sources":["../../src/hooks/use-latest-ref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,kBAAkB,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAEnE,SAAS,YAAY,CAAI,KAAQ;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE1B,kBAAkB,CAAC,GAAG,EAAE;QACpB,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACf,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import { type RefObject, useInsertionEffect, useRef } from \"react\";\n\nfunction useLatestRef<T>(value: T): RefObject<T> {\n const ref = useRef(value);\n\n useInsertionEffect(() => {\n ref.current = value;\n });\n\n return ref;\n}\n\nexport { useLatestRef };\n"]}
@@ -20,13 +20,9 @@ type UseSignalOptions = {
20
20
  /**
21
21
  * Connects a handler to a GObject signal for the lifetime of the component, reconnecting when the object changes.
22
22
  *
23
- * Each emission runs the handler from the latest render, so it does not have to be stable and a
23
+ * Each emission runs the handler from the latest committed render, so it does not have to be stable and a
24
24
  * changing handler never reconnects the signal.
25
25
  *
26
- * On React 19.2 this does not hold inside a component wrapped in `memo` or `forwardRef`, where every emission
27
- * runs the handler captured on the first render. Keep the calling component unwrapped, or read the values the
28
- * handler needs off the GObject itself. React fixes this on the 19.3 line.
29
- *
30
26
  * @param signal The signal name, optionally with a `::detail` suffix.
31
27
  * @param options `isAfter` runs the handler after the default handler; `isImmediate` also invokes it on connect.
32
28
  */
@@ -1 +1 @@
1
- {"version":3,"file":"use-signal.d.ts","sourceRoot":"","sources":["../../src/hooks/use-signal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,KAAK,OAAO,EAAkB,MAAM,sBAAsB,CAAC;AAEpE,0EAA0E;AAC1E,KAAK,OAAO,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AACvE,qFAAqF;AACrF,KAAK,UAAU,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC;AAEzG;;;GAGG;AACH,KAAK,kBAAkB,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1F,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACb,CAAC,SAAS,GAAG,MAAM,KAAK,KAAK,MAAM,EAAE,GACjC,KAAK,SAAS,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GACjB,aAAa,GACjB,aAAa,CAAC;AAExB,qCAAqC;AACrC,KAAK,gBAAgB,GAAG;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,iBAAS,SAAS,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,EACzE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAClB,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EACjC,EAAE,OAAe,EAAE,WAAmB,EAAE,GAAE,gBAAqB,GAChE,IAAI,CAoBN;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"use-signal.d.ts","sourceRoot":"","sources":["../../src/hooks/use-signal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,KAAK,OAAO,EAAkB,MAAM,sBAAsB,CAAC;AAGpE,0EAA0E;AAC1E,KAAK,OAAO,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AACvE,qFAAqF;AACrF,KAAK,UAAU,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC;AAEzG;;;GAGG;AACH,KAAK,kBAAkB,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1F,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACb,CAAC,SAAS,GAAG,MAAM,KAAK,KAAK,MAAM,EAAE,GACjC,KAAK,SAAS,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GACjB,aAAa,GACjB,aAAa,CAAC;AAExB,qCAAqC;AACrC,KAAK,gBAAgB,GAAG;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;;;GAQG;AACH,iBAAS,SAAS,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,EACzE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAClB,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EACjC,EAAE,OAAe,EAAE,WAAmB,EAAE,GAAE,gBAAqB,GAChE,IAAI,CAqBN;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -1,25 +1,23 @@
1
- import { useEffectEvent, useLayoutEffect } from "react";
1
+ import { useLayoutEffect } from "react";
2
2
  import { resolveRefProp } from "../utils/ref-prop.js";
3
+ import { useLatestRef } from "./use-latest-ref.js";
3
4
  /**
4
5
  * Connects a handler to a GObject signal for the lifetime of the component, reconnecting when the object changes.
5
6
  *
6
- * Each emission runs the handler from the latest render, so it does not have to be stable and a
7
+ * Each emission runs the handler from the latest committed render, so it does not have to be stable and a
7
8
  * changing handler never reconnects the signal.
8
9
  *
9
- * On React 19.2 this does not hold inside a component wrapped in `memo` or `forwardRef`, where every emission
10
- * runs the handler captured on the first render. Keep the calling component unwrapped, or read the values the
11
- * handler needs off the GObject itself. React fixes this on the 19.3 line.
12
- *
13
10
  * @param signal The signal name, optionally with a `::detail` suffix.
14
11
  * @param options `isAfter` runs the handler after the default handler; `isImmediate` also invokes it on connect.
15
12
  */
16
13
  function useSignal(object, signal, handler, { isAfter = false, isImmediate = false } = {}) {
17
- const emit = useEffectEvent(handler);
14
+ const handlerRef = useLatestRef(handler);
18
15
  useLayoutEffect(() => {
19
16
  const resolved = resolveRefProp(object);
20
17
  if (!resolved) {
21
18
  return;
22
19
  }
20
+ const emit = (...args) => handlerRef.current(...args);
23
21
  resolved.on(signal, emit, isAfter);
24
22
  if (isImmediate) {
25
23
  emit();
@@ -27,7 +25,7 @@ function useSignal(object, signal, handler, { isAfter = false, isImmediate = fal
27
25
  return () => {
28
26
  resolved.off(signal, emit);
29
27
  };
30
- }, [object, signal, isAfter, isImmediate]);
28
+ }, [handlerRef, object, signal, isAfter, isImmediate]);
31
29
  }
32
30
  export { useSignal };
33
31
  //# sourceMappingURL=use-signal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-signal.js","sourceRoot":"","sources":["../../src/hooks/use-signal.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,EAAgB,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA2BpE;;;;;;;;;;;;GAYG;AACH,SAAS,SAAS,CACd,MAAkB,EAClB,MAAS,EACT,OAAiC,EACjC,EAAE,OAAO,GAAG,KAAK,EAAE,WAAW,GAAG,KAAK,KAAuB,EAAE;IAE/D,MAAM,IAAI,GAAG,cAAc,CAAC,OAAwB,CAAC,CAAC;IAEtD,eAAe,CAAC,GAAG,EAAE;QACjB,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAExC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,OAAO;QACX,CAAC;QAED,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAEnC,IAAI,WAAW,EAAE,CAAC;YACd,IAAI,EAAE,CAAC;QACX,CAAC;QAED,OAAO,GAAG,EAAE;YACR,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport type { SignalHandler } from \"@gtkx/runtime\";\nimport { useEffectEvent, useLayoutEffect } from \"react\";\nimport { type RefProp, resolveRefProp } from \"../utils/ref-prop.js\";\n\n/** The signal map `T` declares, from signal name to handler signature. */\ntype Signals<T extends GObject.Object> = NonNullable<T[\"__signals__\"]>;\n/** Every signal name `T` declares, on its own or narrowed by a `::detail` suffix. */\ntype SignalName<T extends GObject.Object> = keyof Signals<T> | `${keyof Signals<T> & string}::${string}`;\n\n/**\n * The handler signature `T` declares for signal `S`, looked up through any `::detail` suffix and\n * falling back to an untyped `SignalHandler` when the object declares no such signal.\n */\ntype TypedSignalHandler<T extends GObject.Object, S extends string> = S extends keyof Signals<T>\n ? Signals<T>[S]\n : S extends `${infer TBase}::${string}`\n ? TBase extends keyof Signals<T>\n ? Signals<T>[TBase]\n : SignalHandler\n : SignalHandler;\n\n/** Options for {@link useSignal}. */\ntype UseSignalOptions = {\n /** Runs the handler after the object's own default handler rather than before it. */\n isAfter?: boolean;\n /** Invokes the handler once, with no arguments, as soon as the signal is connected. */\n isImmediate?: boolean;\n};\n\n/**\n * Connects a handler to a GObject signal for the lifetime of the component, reconnecting when the object changes.\n *\n * Each emission runs the handler from the latest render, so it does not have to be stable and a\n * changing handler never reconnects the signal.\n *\n * On React 19.2 this does not hold inside a component wrapped in `memo` or `forwardRef`, where every emission\n * runs the handler captured on the first render. Keep the calling component unwrapped, or read the values the\n * handler needs off the GObject itself. React fixes this on the 19.3 line.\n *\n * @param signal The signal name, optionally with a `::detail` suffix.\n * @param options `isAfter` runs the handler after the default handler; `isImmediate` also invokes it on connect.\n */\nfunction useSignal<T extends GObject.Object, S extends SignalName<T> & string>(\n object: RefProp<T>,\n signal: S,\n handler: TypedSignalHandler<T, S>,\n { isAfter = false, isImmediate = false }: UseSignalOptions = {},\n): void {\n const emit = useEffectEvent(handler as SignalHandler);\n\n useLayoutEffect(() => {\n const resolved = resolveRefProp(object);\n\n if (!resolved) {\n return;\n }\n\n resolved.on(signal, emit, isAfter);\n\n if (isImmediate) {\n emit();\n }\n\n return () => {\n resolved.off(signal, emit);\n };\n }, [object, signal, isAfter, isImmediate]);\n}\n\nexport { useSignal };\n"]}
1
+ {"version":3,"file":"use-signal.js","sourceRoot":"","sources":["../../src/hooks/use-signal.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAgB,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AA2BnD;;;;;;;;GAQG;AACH,SAAS,SAAS,CACd,MAAkB,EAClB,MAAS,EACT,OAAiC,EACjC,EAAE,OAAO,GAAG,KAAK,EAAE,WAAW,GAAG,KAAK,KAAuB,EAAE;IAE/D,MAAM,UAAU,GAAG,YAAY,CAAgB,OAAwB,CAAC,CAAC;IAEzE,eAAe,CAAC,GAAG,EAAE;QACjB,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAExC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,OAAO;QACX,CAAC;QAED,MAAM,IAAI,GAAkB,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAEnC,IAAI,WAAW,EAAE,CAAC;YACd,IAAI,EAAE,CAAC;QACX,CAAC;QAED,OAAO,GAAG,EAAE;YACR,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport type { SignalHandler } from \"@gtkx/runtime\";\nimport { useLayoutEffect } from \"react\";\nimport { type RefProp, resolveRefProp } from \"../utils/ref-prop.js\";\nimport { useLatestRef } from \"./use-latest-ref.js\";\n\n/** The signal map `T` declares, from signal name to handler signature. */\ntype Signals<T extends GObject.Object> = NonNullable<T[\"__signals__\"]>;\n/** Every signal name `T` declares, on its own or narrowed by a `::detail` suffix. */\ntype SignalName<T extends GObject.Object> = keyof Signals<T> | `${keyof Signals<T> & string}::${string}`;\n\n/**\n * The handler signature `T` declares for signal `S`, looked up through any `::detail` suffix and\n * falling back to an untyped `SignalHandler` when the object declares no such signal.\n */\ntype TypedSignalHandler<T extends GObject.Object, S extends string> = S extends keyof Signals<T>\n ? Signals<T>[S]\n : S extends `${infer TBase}::${string}`\n ? TBase extends keyof Signals<T>\n ? Signals<T>[TBase]\n : SignalHandler\n : SignalHandler;\n\n/** Options for {@link useSignal}. */\ntype UseSignalOptions = {\n /** Runs the handler after the object's own default handler rather than before it. */\n isAfter?: boolean;\n /** Invokes the handler once, with no arguments, as soon as the signal is connected. */\n isImmediate?: boolean;\n};\n\n/**\n * Connects a handler to a GObject signal for the lifetime of the component, reconnecting when the object changes.\n *\n * Each emission runs the handler from the latest committed render, so it does not have to be stable and a\n * changing handler never reconnects the signal.\n *\n * @param signal The signal name, optionally with a `::detail` suffix.\n * @param options `isAfter` runs the handler after the default handler; `isImmediate` also invokes it on connect.\n */\nfunction useSignal<T extends GObject.Object, S extends SignalName<T> & string>(\n object: RefProp<T>,\n signal: S,\n handler: TypedSignalHandler<T, S>,\n { isAfter = false, isImmediate = false }: UseSignalOptions = {},\n): void {\n const handlerRef = useLatestRef<SignalHandler>(handler as SignalHandler);\n\n useLayoutEffect(() => {\n const resolved = resolveRefProp(object);\n\n if (!resolved) {\n return;\n }\n\n const emit: SignalHandler = (...args) => handlerRef.current(...args);\n resolved.on(signal, emit, isAfter);\n\n if (isImmediate) {\n emit();\n }\n\n return () => {\n resolved.off(signal, emit);\n };\n }, [handlerRef, object, signal, isAfter, isImmediate]);\n}\n\nexport { useSignal };\n"]}
@@ -8,6 +8,7 @@ export { createElementComponent } from "./components/element.js";
8
8
  export { createPortaledComponent } from "./components/portaled.js";
9
9
  /** @internal */
10
10
  export { createWindowComponent } from "./components/window.js";
11
+ export { useLatestRef } from "./hooks/use-latest-ref.js";
11
12
  export { useMergedRef } from "./hooks/use-merged-refs.js";
12
13
  export type * from "./prop-types.js";
13
14
  export { settleAccessible } from "./reconciler/apply-props.js";
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,CAAC;AAExB,gBAAgB;AAChB,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,gBAAgB;AAChB,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,gBAAgB;AAChB,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,gBAAgB;AAChB,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,mBAAmB,iBAAiB,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAC5G,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,CAAC;AAExB,gBAAgB;AAChB,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,gBAAgB;AAChB,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,gBAAgB;AAChB,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,gBAAgB;AAChB,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,mBAAmB,iBAAiB,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAC5G,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/internal.js CHANGED
@@ -8,6 +8,7 @@ export { createElementComponent } from "./components/element.js";
8
8
  export { createPortaledComponent } from "./components/portaled.js";
9
9
  /** @internal */
10
10
  export { createWindowComponent } from "./components/window.js";
11
+ export { useLatestRef } from "./hooks/use-latest-ref.js";
11
12
  export { useMergedRef } from "./hooks/use-merged-refs.js";
12
13
  export { settleAccessible } from "./reconciler/apply-props.js";
13
14
  export { isRootElement } from "./reconciler/root-element.js";
@@ -1 +1 @@
1
- {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,CAAC;AAExB,gBAAgB;AAChB,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,gBAAgB;AAChB,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,gBAAgB;AAChB,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,gBAAgB;AAChB,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAuB,yBAAyB,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["import \"./bootstrap.js\";\n\n/** @internal */\nexport { createApplicationWindowComponent } from \"./components/application-window.js\";\n/** @internal */\nexport { createApplicationComponent } from \"./components/application.js\";\nexport { createElementComponent } from \"./components/element.js\";\n/** @internal */\nexport { createPortaledComponent } from \"./components/portaled.js\";\n/** @internal */\nexport { createWindowComponent } from \"./components/window.js\";\nexport { useMergedRef } from \"./hooks/use-merged-refs.js\";\nexport type * from \"./prop-types.js\";\nexport { settleAccessible } from \"./reconciler/apply-props.js\";\nexport { isRootElement } from \"./reconciler/root-element.js\";\nexport { createReconcilerRoot, type ReconcilerRoot, setReconcilerErrorHandler } from \"./reconciler/root.js\";\nexport type { SettingsSchema, SettingsSchemaKeys, SettingValue } from \"./utils/settings.js\";\n"]}
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,CAAC;AAExB,gBAAgB;AAChB,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,gBAAgB;AAChB,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,gBAAgB;AAChB,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,gBAAgB;AAChB,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAuB,yBAAyB,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["import \"./bootstrap.js\";\n\n/** @internal */\nexport { createApplicationWindowComponent } from \"./components/application-window.js\";\n/** @internal */\nexport { createApplicationComponent } from \"./components/application.js\";\nexport { createElementComponent } from \"./components/element.js\";\n/** @internal */\nexport { createPortaledComponent } from \"./components/portaled.js\";\n/** @internal */\nexport { createWindowComponent } from \"./components/window.js\";\nexport { useLatestRef } from \"./hooks/use-latest-ref.js\";\nexport { useMergedRef } from \"./hooks/use-merged-refs.js\";\nexport type * from \"./prop-types.js\";\nexport { settleAccessible } from \"./reconciler/apply-props.js\";\nexport { isRootElement } from \"./reconciler/root-element.js\";\nexport { createReconcilerRoot, type ReconcilerRoot, setReconcilerErrorHandler } from \"./reconciler/root.js\";\nexport type { SettingsSchema, SettingsSchemaKeys, SettingValue } from \"./utils/settings.js\";\n"]}
@@ -1,5 +1,5 @@
1
1
  import type * as Gio from "@gtkx/gi/gio";
2
- import { type VariantValue } from "./variant.js";
2
+ import { type VariantValue } from "@gtkx/runtime";
3
3
  /** Maps each key of a GSettings schema to its kind: a GVariant type string, or `enum` or `flags`. */
4
4
  type SettingsSchemaKeys = Record<string, string>;
5
5
  /** Value type a key kind stands for: `number` for `enum` and `flags`, otherwise the unpacked GVariant. */
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/utils/settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE/F,qGAAqG;AACrG,KAAK,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACjD,0GAA0G;AAC1G,KAAK,gBAAgB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAChG,0GAA0G;AAC1G,KAAK,YAAY,CAAC,CAAC,SAAS,kBAAkB,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;AAErG,4GAA4G;AAC5G,KAAK,cAAc,CAAC,CAAC,SAAS,kBAAkB,GAAG,kBAAkB,IAAI;IACrE,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,4FAA4F;IAC5F,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uFAAuF;IACvF,IAAI,EAAE,CAAC,CAAC;CACX,CAAC;AAOF,KAAK,uBAAuB,CAAC,CAAC,SAAS,kBAAkB,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI;IAC5E,GAAG,EAAE,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9B,GAAG,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;CAC5C,CAAC;AA4BF,QAAA,MAAM,sBAAsB,GAAI,CAAC,SAAS,kBAAkB,EAAE,CAAC,SAAS,MAAM,CAAC,EAC3E,UAAU,GAAG,CAAC,QAAQ,EACtB,QAAQ,cAAc,CAAC,CAAC,CAAC,EACzB,KAAK,CAAC,GAAG,MAAM,KAChB,uBAAuB,CAAC,CAAC,EAAE,CAAC,CAa9B,CAAC;AAEF,OAAO,EAAE,sBAAsB,EAAE,KAAK,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/utils/settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1E,qGAAqG;AACrG,KAAK,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACjD,0GAA0G;AAC1G,KAAK,gBAAgB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAChG,0GAA0G;AAC1G,KAAK,YAAY,CAAC,CAAC,SAAS,kBAAkB,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;AAErG,4GAA4G;AAC5G,KAAK,cAAc,CAAC,CAAC,SAAS,kBAAkB,GAAG,kBAAkB,IAAI;IACrE,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,4FAA4F;IAC5F,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uFAAuF;IACvF,IAAI,EAAE,CAAC,CAAC;CACX,CAAC;AAOF,KAAK,uBAAuB,CAAC,CAAC,SAAS,kBAAkB,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI;IAC5E,GAAG,EAAE,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9B,GAAG,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;CAC5C,CAAC;AAwBF,QAAA,MAAM,sBAAsB,GAAI,CAAC,SAAS,kBAAkB,EAAE,CAAC,SAAS,MAAM,CAAC,EAC3E,UAAU,GAAG,CAAC,QAAQ,EACtB,QAAQ,cAAc,CAAC,CAAC,CAAC,EACzB,KAAK,CAAC,GAAG,MAAM,KAChB,uBAAuB,CAAC,CAAC,EAAE,CAAC,CAa9B,CAAC;AAEF,OAAO,EAAE,sBAAsB,EAAE,KAAK,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,CAAC"}
@@ -1,4 +1,4 @@
1
- import { packVariant, parseVariantType, unpackVariant } from "./variant.js";
1
+ import { fromVariant, toVariant } from "@gtkx/runtime";
2
2
  const ACCESSORS = {
3
3
  enum: {
4
4
  get: (settings, key) => settings.getEnum(key),
@@ -13,15 +13,12 @@ const ACCESSORS = {
13
13
  },
14
14
  },
15
15
  };
16
- const defaultAccessor = (kind) => {
17
- const node = parseVariantType(kind);
18
- return {
19
- get: (settings, key) => unpackVariant(node, settings.getValue(key)),
20
- set: (settings, key, value) => {
21
- settings.setValue(key, packVariant(node, value));
22
- },
23
- };
24
- };
16
+ const defaultAccessor = (kind) => ({
17
+ get: (settings, key) => fromVariant(kind, settings.getValue(key)),
18
+ set: (settings, key, value) => {
19
+ settings.setValue(key, toVariant(kind, value));
20
+ },
21
+ });
25
22
  const resolveSettingAccessor = (settings, schema, key) => {
26
23
  const kind = schema.keys[key];
27
24
  if (kind === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/utils/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAqB,MAAM,cAAc,CAAC;AA6B/F,MAAM,SAAS,GAAwD;IACnE,IAAI,EAAE;QACF,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC;QACnE,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,KAAa,EAAE,EAAE;YACxD,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;KACJ;IACD,KAAK,EAAE;QACH,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QACpE,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,KAAa,EAAE,EAAE;YACxD,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;KACJ;CACJ,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,IAAY,EAAmB,EAAE;IACtD,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAEpC,OAAO;QACH,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzF,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,KAAc,EAAE,EAAE;YACzD,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;QACrD,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAC3B,QAAsB,EACtB,MAAyB,EACzB,GAAe,EACc,EAAE;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,+BAA+B,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwC,CAAC;IAEnG,OAAO;QACH,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC;QAC3C,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC;KAC9C,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,sBAAsB,EAAmE,CAAC","sourcesContent":["import type * as Gio from \"@gtkx/gi/gio\";\nimport { packVariant, parseVariantType, unpackVariant, type VariantValue } from \"./variant.js\";\n\n/** Maps each key of a GSettings schema to its kind: a GVariant type string, or `enum` or `flags`. */\ntype SettingsSchemaKeys = Record<string, string>;\n/** Value type a key kind stands for: `number` for `enum` and `flags`, otherwise the unpacked GVariant. */\ntype SettingKindValue<S extends string> = S extends \"enum\" | \"flags\" ? number : VariantValue<S>;\n/** Value type of key `P`, looked up by its kind in schema `K`, that reads and writes of that key take. */\ntype SettingValue<K extends SettingsSchemaKeys, P extends keyof K> = SettingKindValue<K[P] & string>;\n\n/** A GSettings schema, as described by the modules GTKX generates from a project's `.gschema.xml` files. */\ntype SettingsSchema<K extends SettingsSchemaKeys = SettingsSchemaKeys> = {\n /** Schema id it is looked up by, such as `org.gtkx.Example`. */\n id: string;\n /** Path a relocatable schema is instantiated at, or `null` to use the schema's own path. */\n path: string | null;\n /** Kind of every key the schema declares, which types reads and writes of that key. */\n keys: K;\n};\n\ntype SettingAccessor<T = unknown> = {\n get: (settings: Gio.Settings, key: string) => T;\n set: (settings: Gio.Settings, key: string, value: T) => void;\n};\n\ntype ResolvedSettingAccessor<K extends SettingsSchemaKeys, P extends keyof K> = {\n get: () => SettingValue<K, P>;\n set: (value: SettingValue<K, P>) => void;\n};\n\nconst ACCESSORS: Record<string, SettingAccessor<number> | undefined> = {\n enum: {\n get: (settings: Gio.Settings, key: string) => settings.getEnum(key),\n set: (settings: Gio.Settings, key: string, value: number) => {\n settings.setEnum(key, value);\n },\n },\n flags: {\n get: (settings: Gio.Settings, key: string) => settings.getFlags(key),\n set: (settings: Gio.Settings, key: string, value: number) => {\n settings.setFlags(key, value);\n },\n },\n};\n\nconst defaultAccessor = (kind: string): SettingAccessor => {\n const node = parseVariantType(kind);\n\n return {\n get: (settings: Gio.Settings, key: string) => unpackVariant(node, settings.getValue(key)),\n set: (settings: Gio.Settings, key: string, value: unknown) => {\n settings.setValue(key, packVariant(node, value));\n },\n };\n};\n\nconst resolveSettingAccessor = <K extends SettingsSchemaKeys, P extends keyof K>(\n settings: Gio.Settings,\n schema: SettingsSchema<K>,\n key: P & string,\n): ResolvedSettingAccessor<K, P> => {\n const kind = schema.keys[key];\n\n if (kind === undefined) {\n throw new Error(`Key \"${key}\" is not defined in schema \"${schema.id}\"`);\n }\n\n const accessor = (ACCESSORS[kind] ?? defaultAccessor(kind)) as SettingAccessor<SettingValue<K, P>>;\n\n return {\n get: accessor.get.bind(null, settings, key),\n set: accessor.set.bind(null, settings, key),\n };\n};\n\nexport { resolveSettingAccessor, type SettingsSchemaKeys, type SettingValue, type SettingsSchema };\n"]}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/utils/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAqB,MAAM,eAAe,CAAC;AA6B1E,MAAM,SAAS,GAAwD;IACnE,IAAI,EAAE;QACF,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC;QACnE,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,KAAa,EAAE,EAAE;YACxD,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;KACJ;IACD,KAAK,EAAE;QACH,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QACpE,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,KAAa,EAAE,EAAE;YACxD,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;KACJ;CACJ,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,IAAY,EAAmB,EAAE,CAAC,CAAC;IACxD,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvF,GAAG,EAAE,CAAC,QAAsB,EAAE,GAAW,EAAE,KAAc,EAAE,EAAE;QACzD,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;CACJ,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,CAC3B,QAAsB,EACtB,MAAyB,EACzB,GAAe,EACc,EAAE;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,+BAA+B,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwC,CAAC;IAEnG,OAAO;QACH,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC;QAC3C,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC;KAC9C,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,sBAAsB,EAAmE,CAAC","sourcesContent":["import type * as Gio from \"@gtkx/gi/gio\";\nimport { fromVariant, toVariant, type VariantValue } from \"@gtkx/runtime\";\n\n/** Maps each key of a GSettings schema to its kind: a GVariant type string, or `enum` or `flags`. */\ntype SettingsSchemaKeys = Record<string, string>;\n/** Value type a key kind stands for: `number` for `enum` and `flags`, otherwise the unpacked GVariant. */\ntype SettingKindValue<S extends string> = S extends \"enum\" | \"flags\" ? number : VariantValue<S>;\n/** Value type of key `P`, looked up by its kind in schema `K`, that reads and writes of that key take. */\ntype SettingValue<K extends SettingsSchemaKeys, P extends keyof K> = SettingKindValue<K[P] & string>;\n\n/** A GSettings schema, as described by the modules GTKX generates from a project's `.gschema.xml` files. */\ntype SettingsSchema<K extends SettingsSchemaKeys = SettingsSchemaKeys> = {\n /** Schema id it is looked up by, such as `org.gtkx.Example`. */\n id: string;\n /** Path a relocatable schema is instantiated at, or `null` to use the schema's own path. */\n path: string | null;\n /** Kind of every key the schema declares, which types reads and writes of that key. */\n keys: K;\n};\n\ntype SettingAccessor<T = unknown> = {\n get: (settings: Gio.Settings, key: string) => T;\n set: (settings: Gio.Settings, key: string, value: T) => void;\n};\n\ntype ResolvedSettingAccessor<K extends SettingsSchemaKeys, P extends keyof K> = {\n get: () => SettingValue<K, P>;\n set: (value: SettingValue<K, P>) => void;\n};\n\nconst ACCESSORS: Record<string, SettingAccessor<number> | undefined> = {\n enum: {\n get: (settings: Gio.Settings, key: string) => settings.getEnum(key),\n set: (settings: Gio.Settings, key: string, value: number) => {\n settings.setEnum(key, value);\n },\n },\n flags: {\n get: (settings: Gio.Settings, key: string) => settings.getFlags(key),\n set: (settings: Gio.Settings, key: string, value: number) => {\n settings.setFlags(key, value);\n },\n },\n};\n\nconst defaultAccessor = (kind: string): SettingAccessor => ({\n get: (settings: Gio.Settings, key: string) => fromVariant(kind, settings.getValue(key)),\n set: (settings: Gio.Settings, key: string, value: unknown) => {\n settings.setValue(key, toVariant(kind, value));\n },\n});\n\nconst resolveSettingAccessor = <K extends SettingsSchemaKeys, P extends keyof K>(\n settings: Gio.Settings,\n schema: SettingsSchema<K>,\n key: P & string,\n): ResolvedSettingAccessor<K, P> => {\n const kind = schema.keys[key];\n\n if (kind === undefined) {\n throw new Error(`Key \"${key}\" is not defined in schema \"${schema.id}\"`);\n }\n\n const accessor = (ACCESSORS[kind] ?? defaultAccessor(kind)) as SettingAccessor<SettingValue<K, P>>;\n\n return {\n get: accessor.get.bind(null, settings, key),\n set: accessor.set.bind(null, settings, key),\n };\n};\n\nexport { resolveSettingAccessor, type SettingsSchemaKeys, type SettingValue, type SettingsSchema };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/react",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "React reconciler that renders GTK4 object trees, with the portals, signal handling, and hooks GTKX apps use",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -86,9 +86,9 @@
86
86
  },
87
87
  "dependencies": {
88
88
  "react-reconciler": "^0.33.0",
89
- "@gtkx/config": "1.1.0",
90
- "@gtkx/runtime": "1.1.0",
91
- "@gtkx/utils": "1.1.0"
89
+ "@gtkx/config": "1.2.1",
90
+ "@gtkx/runtime": "1.2.1",
91
+ "@gtkx/utils": "1.2.1"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@types/react": "^19.2.18",
@@ -0,0 +1,13 @@
1
+ import { type RefObject, useInsertionEffect, useRef } from "react";
2
+
3
+ function useLatestRef<T>(value: T): RefObject<T> {
4
+ const ref = useRef(value);
5
+
6
+ useInsertionEffect(() => {
7
+ ref.current = value;
8
+ });
9
+
10
+ return ref;
11
+ }
12
+
13
+ export { useLatestRef };
@@ -1,7 +1,8 @@
1
1
  import type * as GObject from "@gtkx/gi/gobject";
2
2
  import type { SignalHandler } from "@gtkx/runtime";
3
- import { useEffectEvent, useLayoutEffect } from "react";
3
+ import { useLayoutEffect } from "react";
4
4
  import { type RefProp, resolveRefProp } from "../utils/ref-prop.js";
5
+ import { useLatestRef } from "./use-latest-ref.js";
5
6
 
6
7
  /** The signal map `T` declares, from signal name to handler signature. */
7
8
  type Signals<T extends GObject.Object> = NonNullable<T["__signals__"]>;
@@ -31,13 +32,9 @@ type UseSignalOptions = {
31
32
  /**
32
33
  * Connects a handler to a GObject signal for the lifetime of the component, reconnecting when the object changes.
33
34
  *
34
- * Each emission runs the handler from the latest render, so it does not have to be stable and a
35
+ * Each emission runs the handler from the latest committed render, so it does not have to be stable and a
35
36
  * changing handler never reconnects the signal.
36
37
  *
37
- * On React 19.2 this does not hold inside a component wrapped in `memo` or `forwardRef`, where every emission
38
- * runs the handler captured on the first render. Keep the calling component unwrapped, or read the values the
39
- * handler needs off the GObject itself. React fixes this on the 19.3 line.
40
- *
41
38
  * @param signal The signal name, optionally with a `::detail` suffix.
42
39
  * @param options `isAfter` runs the handler after the default handler; `isImmediate` also invokes it on connect.
43
40
  */
@@ -47,7 +44,7 @@ function useSignal<T extends GObject.Object, S extends SignalName<T> & string>(
47
44
  handler: TypedSignalHandler<T, S>,
48
45
  { isAfter = false, isImmediate = false }: UseSignalOptions = {},
49
46
  ): void {
50
- const emit = useEffectEvent(handler as SignalHandler);
47
+ const handlerRef = useLatestRef<SignalHandler>(handler as SignalHandler);
51
48
 
52
49
  useLayoutEffect(() => {
53
50
  const resolved = resolveRefProp(object);
@@ -56,6 +53,7 @@ function useSignal<T extends GObject.Object, S extends SignalName<T> & string>(
56
53
  return;
57
54
  }
58
55
 
56
+ const emit: SignalHandler = (...args) => handlerRef.current(...args);
59
57
  resolved.on(signal, emit, isAfter);
60
58
 
61
59
  if (isImmediate) {
@@ -65,7 +63,7 @@ function useSignal<T extends GObject.Object, S extends SignalName<T> & string>(
65
63
  return () => {
66
64
  resolved.off(signal, emit);
67
65
  };
68
- }, [object, signal, isAfter, isImmediate]);
66
+ }, [handlerRef, object, signal, isAfter, isImmediate]);
69
67
  }
70
68
 
71
69
  export { useSignal };
package/src/internal.ts CHANGED
@@ -9,6 +9,7 @@ export { createElementComponent } from "./components/element.js";
9
9
  export { createPortaledComponent } from "./components/portaled.js";
10
10
  /** @internal */
11
11
  export { createWindowComponent } from "./components/window.js";
12
+ export { useLatestRef } from "./hooks/use-latest-ref.js";
12
13
  export { useMergedRef } from "./hooks/use-merged-refs.js";
13
14
  export type * from "./prop-types.js";
14
15
  export { settleAccessible } from "./reconciler/apply-props.js";
@@ -1,5 +1,5 @@
1
1
  import type * as Gio from "@gtkx/gi/gio";
2
- import { packVariant, parseVariantType, unpackVariant, type VariantValue } from "./variant.js";
2
+ import { fromVariant, toVariant, type VariantValue } from "@gtkx/runtime";
3
3
 
4
4
  /** Maps each key of a GSettings schema to its kind: a GVariant type string, or `enum` or `flags`. */
5
5
  type SettingsSchemaKeys = Record<string, string>;
@@ -43,16 +43,12 @@ const ACCESSORS: Record<string, SettingAccessor<number> | undefined> = {
43
43
  },
44
44
  };
45
45
 
46
- const defaultAccessor = (kind: string): SettingAccessor => {
47
- const node = parseVariantType(kind);
48
-
49
- return {
50
- get: (settings: Gio.Settings, key: string) => unpackVariant(node, settings.getValue(key)),
51
- set: (settings: Gio.Settings, key: string, value: unknown) => {
52
- settings.setValue(key, packVariant(node, value));
53
- },
54
- };
55
- };
46
+ const defaultAccessor = (kind: string): SettingAccessor => ({
47
+ get: (settings: Gio.Settings, key: string) => fromVariant(kind, settings.getValue(key)),
48
+ set: (settings: Gio.Settings, key: string, value: unknown) => {
49
+ settings.setValue(key, toVariant(kind, value));
50
+ },
51
+ });
56
52
 
57
53
  const resolveSettingAccessor = <K extends SettingsSchemaKeys, P extends keyof K>(
58
54
  settings: Gio.Settings,
@@ -1,89 +0,0 @@
1
- import * as GLib from "@gtkx/gi/glib";
2
- /** JavaScript type every GVariant basic type code unpacks to. */
3
- type BasicValueMap = {
4
- /** Boolean, held as a single byte reading 0 or 1. */
5
- b: boolean;
6
- /** Unsigned byte. */
7
- y: number;
8
- /** Signed 16-bit integer. */
9
- n: number;
10
- /** Unsigned 16-bit integer. */
11
- q: number;
12
- /** Signed 32-bit integer. */
13
- i: number;
14
- /** Unsigned 32-bit integer. */
15
- u: number;
16
- /** Index into the file descriptor list a message carries. */
17
- h: number;
18
- /** Double precision floating point number. */
19
- d: number;
20
- /** Signed 64-bit integer. */
21
- x: bigint;
22
- /** Unsigned 64-bit integer. */
23
- t: bigint;
24
- /** UTF-8 string, under no further constraint on what it holds. */
25
- s: string;
26
- /** D-Bus object path. */
27
- o: string;
28
- /** GVariant type signature. */
29
- g: string;
30
- /** Boxed variant holding a value of any type. */
31
- v: GLib.Variant;
32
- };
33
- /** Single-character code of one of the GVariant basic types in {@link BasicValueMap}. */
34
- type BasicCode = keyof BasicValueMap;
35
- /** Parses the element type of an array, yielding the array type it produces and the rest of the string. */
36
- type ParseArray<S extends string> = Parse<S> extends [infer V, infer R extends string] ? [V[], R] : never;
37
- /** Parses the element type of a maybe, yielding the nullable type it produces and the rest of the string. */
38
- type ParseMaybe<S extends string> = Parse<S> extends [infer V, infer R extends string] ? [V | null, R] : never;
39
- /** Collects tuple member types into `Acc` up to the closing parenthesis, yielding them and the rest of the string. */
40
- type ParseTuple<S extends string, Acc extends unknown[]> = S extends `)${infer Rest}` ? [Acc, Rest] : [Parse<S>] extends [never] ? never : Parse<S> extends [infer V, infer R extends string] ? ParseTuple<R, [...Acc, V]> : never;
41
- /** Types a dictionary entry key can hold. */
42
- type DictKey = string | number | bigint | boolean;
43
- /** Parses the key and value types of a dictionary entry, yielding them and the rest of the string after its brace. */
44
- type ParsePair<S extends string> = Parse<S> extends [infer K, infer R1 extends string] ? Parse<R1> extends [infer V, infer R2 extends string] ? R2 extends `}${infer R3}` ? [K] extends [DictKey] ? [K, V, R3] : never : never : never : never;
45
- /**
46
- * Parses a dictionary entry into the collection an array of those entries unpacks to, a record for string keys and a
47
- * `Map` otherwise, plus the rest of the string.
48
- */
49
- type ParseDict<S extends string> = ParsePair<S> extends [infer K, infer V, infer R extends string] ? [[K] extends [string] ? Record<string, V> : Map<K, V>, R] : never;
50
- /** Parses a standalone dictionary entry into a key and value pair, yielding it and the rest of the string. */
51
- type ParseEntry<S extends string> = ParsePair<S> extends [infer K, infer V, infer R extends string] ? [[K, V], R] : never;
52
- /** Parses what follows an `a` as a dictionary when it opens an entry, and as a plain array otherwise. */
53
- type ParseArrayOrDict<S extends string> = S extends `{${infer Rest}` ? ParseDict<Rest> : ParseArray<S>;
54
- /**
55
- * Parses the type at the head of `S`, yielding the JavaScript type it unpacks to and the rest of the string, or
56
- * `never` when the string is malformed.
57
- */
58
- type Parse<S extends string> = S extends `a${infer Rest}` ? ParseArrayOrDict<Rest> : S extends `m${infer Rest}` ? ParseMaybe<Rest> : S extends `(${infer Rest}` ? ParseTuple<Rest, []> : S extends `{${infer Rest}` ? ParseEntry<Rest> : S extends `${infer C}${infer Rest}` ? C extends BasicCode ? [BasicValueMap[C], Rest] : never : never;
59
- /** JavaScript type a variant of type string `S` unpacks to, or `unknown` when `S` is not one complete type. */
60
- type VariantValue<S extends string> = [Parse<S>] extends [never] ? unknown : Parse<S> extends [infer V, ""] ? V : unknown;
61
- type VariantTypeNode = {
62
- kind: "basic";
63
- code: BasicCode;
64
- } | {
65
- kind: "array";
66
- elementTypeString: string;
67
- element: VariantTypeNode;
68
- } | {
69
- kind: "dict";
70
- entryTypeString: string;
71
- key: VariantTypeNode;
72
- value: VariantTypeNode;
73
- } | {
74
- kind: "entry";
75
- key: VariantTypeNode;
76
- value: VariantTypeNode;
77
- } | {
78
- kind: "tuple";
79
- items: VariantTypeNode[];
80
- } | {
81
- kind: "maybe";
82
- elementTypeString: string;
83
- element: VariantTypeNode;
84
- };
85
- declare const parseVariantType: (typeString: string) => VariantTypeNode;
86
- declare const unpackVariant: (node: VariantTypeNode, variant: GLib.Variant) => unknown;
87
- declare const packVariant: (node: VariantTypeNode, value: unknown) => GLib.Variant;
88
- export { parseVariantType, unpackVariant, packVariant, type VariantValue };
89
- //# sourceMappingURL=variant.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"variant.d.ts","sourceRoot":"","sources":["../../src/utils/variant.ts"],"names":[],"mappings":"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"}
@@ -1,197 +0,0 @@
1
- import * as GLib from "@gtkx/gi/glib";
2
- const BASIC_CODES = "bynqiuxthdsogv";
3
- const STRING_KEY_CODES = new Set(["s", "o", "g"]);
4
- const CONTAINER_PARSERS = {
5
- a: parseArrayNode,
6
- m: parseMaybeNode,
7
- "(": parseTupleNode,
8
- "{": parseEntryNode,
9
- };
10
- const parsedTypes = new Map();
11
- const unpackBasic = {
12
- b: (variant) => variant.getBoolean(),
13
- y: (variant) => variant.getByte(),
14
- n: (variant) => variant.getInt16(),
15
- q: (variant) => variant.getUint16(),
16
- i: (variant) => variant.getInt32(),
17
- u: (variant) => variant.getUint32(),
18
- h: (variant) => variant.getHandle(),
19
- d: (variant) => variant.getDouble(),
20
- x: (variant) => variant.getInt64(),
21
- t: (variant) => variant.getUint64(),
22
- s: (variant) => variant.getString()[0],
23
- o: (variant) => variant.getString()[0],
24
- g: (variant) => variant.getString()[0],
25
- v: (variant) => variant.getVariant(),
26
- };
27
- const packBasic = {
28
- b: (value) => GLib.Variant.newBoolean(value),
29
- y: (value) => GLib.Variant.newByte(value),
30
- n: (value) => GLib.Variant.newInt16(value),
31
- q: (value) => GLib.Variant.newUint16(value),
32
- i: (value) => GLib.Variant.newInt32(value),
33
- u: (value) => GLib.Variant.newUint32(value),
34
- h: (value) => GLib.Variant.newHandle(value),
35
- d: (value) => GLib.Variant.newDouble(value),
36
- x: (value) => GLib.Variant.newInt64(value),
37
- t: (value) => GLib.Variant.newUint64(value),
38
- s: (value) => GLib.Variant.newString(value),
39
- o: packObjectPath,
40
- g: packSignature,
41
- v: (value) => GLib.Variant.newVariant(value),
42
- };
43
- const isBasicCode = (code) => BASIC_CODES.includes(code);
44
- const isStringKeyed = (key) => key.kind === "basic" && STRING_KEY_CODES.has(key.code);
45
- const invalidType = (source) => new Error(`Invalid GVariant type string "${source}"`);
46
- const parsePair = (source, start) => {
47
- const [key, keyEnd] = parseNode(source, start);
48
- if (key.kind !== "basic" || key.code === "v") {
49
- throw invalidType(source);
50
- }
51
- const [value, valueEnd] = parseNode(source, keyEnd);
52
- if (source[valueEnd] !== "}") {
53
- throw invalidType(source);
54
- }
55
- return [key, value, valueEnd + 1];
56
- };
57
- function parseArrayNode(source, start) {
58
- if (source[start] === "{") {
59
- const [key, value, end] = parsePair(source, start + 1);
60
- return [{ kind: "dict", entryTypeString: source.slice(start, end), key, value }, end];
61
- }
62
- const [element, end] = parseNode(source, start);
63
- return [{ kind: "array", elementTypeString: source.slice(start, end), element }, end];
64
- }
65
- function parseMaybeNode(source, start) {
66
- const [element, end] = parseNode(source, start);
67
- return [{ kind: "maybe", elementTypeString: source.slice(start, end), element }, end];
68
- }
69
- function parseTupleNode(source, start) {
70
- const items = [];
71
- let position = start;
72
- while (source[position] !== ")") {
73
- if (position >= source.length) {
74
- throw invalidType(source);
75
- }
76
- const [item, end] = parseNode(source, position);
77
- items.push(item);
78
- position = end;
79
- }
80
- return [{ kind: "tuple", items }, position + 1];
81
- }
82
- function parseEntryNode(source, start) {
83
- const [key, value, end] = parsePair(source, start);
84
- return [{ kind: "entry", key, value }, end];
85
- }
86
- const parseNode = (source, start) => {
87
- const code = source[start];
88
- if (code === undefined) {
89
- throw invalidType(source);
90
- }
91
- const container = CONTAINER_PARSERS[code];
92
- if (container !== undefined) {
93
- return container(source, start + 1);
94
- }
95
- if (isBasicCode(code)) {
96
- return [{ kind: "basic", code }, start + 1];
97
- }
98
- throw invalidType(source);
99
- };
100
- const parseVariantType = (typeString) => {
101
- const cached = parsedTypes.get(typeString);
102
- if (cached !== undefined) {
103
- return cached;
104
- }
105
- const [node, end] = parseNode(typeString, 0);
106
- if (end !== typeString.length) {
107
- throw invalidType(typeString);
108
- }
109
- parsedTypes.set(typeString, node);
110
- return node;
111
- };
112
- const unpackChildren = (variant, unpackChild) => {
113
- const children = [];
114
- const count = variant.nChildren();
115
- for (let index = 0; index < count; index += 1) {
116
- children.push(unpackChild(variant.getChildValue(index)));
117
- }
118
- return children;
119
- };
120
- const unpackPair = (key, value, entry) => [
121
- unpackVariant(key, entry.getChildValue(0)),
122
- unpackVariant(value, entry.getChildValue(1)),
123
- ];
124
- const unpackDict = (node, variant) => {
125
- const entries = unpackChildren(variant, (entry) => unpackPair(node.key, node.value, entry));
126
- if (!isStringKeyed(node.key)) {
127
- return new Map(entries);
128
- }
129
- const stringEntries = entries.map(([key, value]) => [key, value]);
130
- return Object.fromEntries(stringEntries);
131
- };
132
- const unpackMaybe = (element, variant) => {
133
- const child = variant.getMaybe();
134
- return child === null ? null : unpackVariant(element, child);
135
- };
136
- const unpackVariant = (node, variant) => {
137
- switch (node.kind) {
138
- case "basic": {
139
- return unpackBasic[node.code](variant);
140
- }
141
- case "array": {
142
- return unpackChildren(variant, (child) => unpackVariant(node.element, child));
143
- }
144
- case "dict": {
145
- return unpackDict(node, variant);
146
- }
147
- case "entry": {
148
- return unpackPair(node.key, node.value, variant);
149
- }
150
- case "tuple": {
151
- return node.items.map((item, index) => unpackVariant(item, variant.getChildValue(index)));
152
- }
153
- case "maybe": {
154
- return unpackMaybe(node.element, variant);
155
- }
156
- }
157
- };
158
- const packValidatedString = (value, isValid, description, construct) => {
159
- if (typeof value !== "string" || !isValid(value)) {
160
- throw new Error(`"${String(value)}" is not a valid GVariant ${description}`);
161
- }
162
- return construct(value);
163
- };
164
- function packObjectPath(value) {
165
- return packValidatedString(value, (path) => GLib.Variant.isObjectPath(path), "object path", (path) => GLib.Variant.newObjectPath(path));
166
- }
167
- function packSignature(value) {
168
- return packValidatedString(value, (signature) => GLib.Variant.isSignature(signature), "type signature", (signature) => GLib.Variant.newSignature(signature));
169
- }
170
- const packEntry = (key, value, pair) => GLib.Variant.newDictEntry(packVariant(key, pair[0]), packVariant(value, pair[1]));
171
- const dictEntries = (value) => value instanceof Map ? [...value] : Object.entries(value);
172
- const packDict = (node, value) => GLib.Variant.newArray(GLib.VariantType.new(node.entryTypeString), dictEntries(value).map((pair) => packEntry(node.key, node.value, pair)));
173
- const packMaybe = (node, value) => GLib.Variant.newMaybe(GLib.VariantType.new(node.elementTypeString), value === null ? null : packVariant(node.element, value));
174
- const packVariant = (node, value) => {
175
- switch (node.kind) {
176
- case "basic": {
177
- return packBasic[node.code](value);
178
- }
179
- case "array": {
180
- return GLib.Variant.newArray(GLib.VariantType.new(node.elementTypeString), value.map((item) => packVariant(node.element, item)));
181
- }
182
- case "dict": {
183
- return packDict(node, value);
184
- }
185
- case "entry": {
186
- return packEntry(node.key, node.value, value);
187
- }
188
- case "tuple": {
189
- return GLib.Variant.newTuple(node.items.map((item, index) => packVariant(item, value[index])));
190
- }
191
- case "maybe": {
192
- return packMaybe(node, value);
193
- }
194
- }
195
- };
196
- export { parseVariantType, unpackVariant, packVariant };
197
- //# sourceMappingURL=variant.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"variant.js","sourceRoot":"","sources":["../../src/utils/variant.ts"],"names":[],"mappings":"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","sourcesContent":["import * as GLib from \"@gtkx/gi/glib\";\n\n/** JavaScript type every GVariant basic type code unpacks to. */\ntype BasicValueMap = {\n /** Boolean, held as a single byte reading 0 or 1. */\n b: boolean;\n /** Unsigned byte. */\n y: number;\n /** Signed 16-bit integer. */\n n: number;\n /** Unsigned 16-bit integer. */\n q: number;\n /** Signed 32-bit integer. */\n i: number;\n /** Unsigned 32-bit integer. */\n u: number;\n /** Index into the file descriptor list a message carries. */\n h: number;\n /** Double precision floating point number. */\n d: number;\n /** Signed 64-bit integer. */\n x: bigint;\n /** Unsigned 64-bit integer. */\n t: bigint;\n /** UTF-8 string, under no further constraint on what it holds. */\n s: string;\n /** D-Bus object path. */\n o: string;\n /** GVariant type signature. */\n g: string;\n /** Boxed variant holding a value of any type. */\n v: GLib.Variant;\n};\n\n/** Single-character code of one of the GVariant basic types in {@link BasicValueMap}. */\ntype BasicCode = keyof BasicValueMap;\n/** Parses the element type of an array, yielding the array type it produces and the rest of the string. */\ntype ParseArray<S extends string> = Parse<S> extends [infer V, infer R extends string] ? [V[], R] : never;\n/** Parses the element type of a maybe, yielding the nullable type it produces and the rest of the string. */\ntype ParseMaybe<S extends string> = Parse<S> extends [infer V, infer R extends string] ? [V | null, R] : never;\n\n/** Collects tuple member types into `Acc` up to the closing parenthesis, yielding them and the rest of the string. */\ntype ParseTuple<S extends string, Acc extends unknown[]> = S extends `)${infer Rest}`\n ? [Acc, Rest]\n : [Parse<S>] extends [never]\n ? never\n : Parse<S> extends [infer V, infer R extends string]\n ? ParseTuple<R, [...Acc, V]>\n : never;\n\n/** Types a dictionary entry key can hold. */\ntype DictKey = string | number | bigint | boolean;\n\n/** Parses the key and value types of a dictionary entry, yielding them and the rest of the string after its brace. */\ntype ParsePair<S extends string> =\n Parse<S> extends [infer K, infer R1 extends string]\n ? Parse<R1> extends [infer V, infer R2 extends string]\n ? R2 extends `}${infer R3}`\n ? [K] extends [DictKey]\n ? [K, V, R3]\n : never\n : never\n : never\n : never;\n\n/**\n * Parses a dictionary entry into the collection an array of those entries unpacks to, a record for string keys and a\n * `Map` otherwise, plus the rest of the string.\n */\ntype ParseDict<S extends string> =\n ParsePair<S> extends [infer K, infer V, infer R extends string]\n ? [[K] extends [string] ? Record<string, V> : Map<K, V>, R]\n : never;\n\n/** Parses a standalone dictionary entry into a key and value pair, yielding it and the rest of the string. */\ntype ParseEntry<S extends string> =\n ParsePair<S> extends [infer K, infer V, infer R extends string] ? [[K, V], R] : never;\n\n/** Parses what follows an `a` as a dictionary when it opens an entry, and as a plain array otherwise. */\ntype ParseArrayOrDict<S extends string> = S extends `{${infer Rest}` ? ParseDict<Rest> : ParseArray<S>;\n\n/**\n * Parses the type at the head of `S`, yielding the JavaScript type it unpacks to and the rest of the string, or\n * `never` when the string is malformed.\n */\ntype Parse<S extends string> = S extends `a${infer Rest}`\n ? ParseArrayOrDict<Rest>\n : S extends `m${infer Rest}`\n ? ParseMaybe<Rest>\n : S extends `(${infer Rest}`\n ? ParseTuple<Rest, []>\n : S extends `{${infer Rest}`\n ? ParseEntry<Rest>\n : S extends `${infer C}${infer Rest}`\n ? C extends BasicCode\n ? [BasicValueMap[C], Rest]\n : never\n : never;\n\n/** JavaScript type a variant of type string `S` unpacks to, or `unknown` when `S` is not one complete type. */\ntype VariantValue<S extends string> = [Parse<S>] extends [never]\n ? unknown\n : Parse<S> extends [infer V, \"\"]\n ? V\n : unknown;\n\ntype VariantTypeNode =\n | { kind: \"basic\"; code: BasicCode } |\n { kind: \"array\"; elementTypeString: string; element: VariantTypeNode } |\n { kind: \"dict\"; entryTypeString: string; key: VariantTypeNode; value: VariantTypeNode } |\n { kind: \"entry\"; key: VariantTypeNode; value: VariantTypeNode } |\n { kind: \"tuple\"; items: VariantTypeNode[] } |\n { kind: \"maybe\"; elementTypeString: string; element: VariantTypeNode };\n\nconst BASIC_CODES = \"bynqiuxthdsogv\";\nconst STRING_KEY_CODES: Set<string> = new Set([\"s\", \"o\", \"g\"]);\n\nconst CONTAINER_PARSERS: Record<string, (source: string, start: number) => [VariantTypeNode, number]> = {\n a: parseArrayNode,\n m: parseMaybeNode,\n \"(\": parseTupleNode,\n \"{\": parseEntryNode,\n};\n\nconst parsedTypes: Map<string, VariantTypeNode> = new Map();\n\nconst unpackBasic: Record<BasicCode, (variant: GLib.Variant) => unknown> = {\n b: (variant) => variant.getBoolean(),\n y: (variant) => variant.getByte(),\n n: (variant) => variant.getInt16(),\n q: (variant) => variant.getUint16(),\n i: (variant) => variant.getInt32(),\n u: (variant) => variant.getUint32(),\n h: (variant) => variant.getHandle(),\n d: (variant) => variant.getDouble(),\n x: (variant) => variant.getInt64(),\n t: (variant) => variant.getUint64(),\n s: (variant) => variant.getString()[0],\n o: (variant) => variant.getString()[0],\n g: (variant) => variant.getString()[0],\n v: (variant) => variant.getVariant(),\n};\n\nconst packBasic: Record<BasicCode, (value: unknown) => GLib.Variant> = {\n b: (value) => GLib.Variant.newBoolean(value as boolean),\n y: (value) => GLib.Variant.newByte(value as number),\n n: (value) => GLib.Variant.newInt16(value as number),\n q: (value) => GLib.Variant.newUint16(value as number),\n i: (value) => GLib.Variant.newInt32(value as number),\n u: (value) => GLib.Variant.newUint32(value as number),\n h: (value) => GLib.Variant.newHandle(value as number),\n d: (value) => GLib.Variant.newDouble(value as number),\n x: (value) => GLib.Variant.newInt64(value as bigint),\n t: (value) => GLib.Variant.newUint64(value as bigint),\n s: (value) => GLib.Variant.newString(value as string),\n o: packObjectPath,\n g: packSignature,\n v: (value) => GLib.Variant.newVariant(value as GLib.Variant),\n};\n\nconst isBasicCode = (code: string): code is BasicCode => BASIC_CODES.includes(code);\nconst isStringKeyed = (key: VariantTypeNode): boolean => key.kind === \"basic\" && STRING_KEY_CODES.has(key.code);\nconst invalidType = (source: string): Error => new Error(`Invalid GVariant type string \"${source}\"`);\n\nconst parsePair = (source: string, start: number): [VariantTypeNode, VariantTypeNode, number] => {\n const [key, keyEnd] = parseNode(source, start);\n\n if (key.kind !== \"basic\" || key.code === \"v\") {\n throw invalidType(source);\n }\n\n const [value, valueEnd] = parseNode(source, keyEnd);\n\n if (source[valueEnd] !== \"}\") {\n throw invalidType(source);\n }\n\n return [key, value, valueEnd + 1];\n};\n\nfunction parseArrayNode(source: string, start: number): [VariantTypeNode, number] {\n if (source[start] === \"{\") {\n const [key, value, end] = parsePair(source, start + 1);\n\n return [{ kind: \"dict\", entryTypeString: source.slice(start, end), key, value }, end];\n }\n\n const [element, end] = parseNode(source, start);\n\n return [{ kind: \"array\", elementTypeString: source.slice(start, end), element }, end];\n}\n\nfunction parseMaybeNode(source: string, start: number): [VariantTypeNode, number] {\n const [element, end] = parseNode(source, start);\n\n return [{ kind: \"maybe\", elementTypeString: source.slice(start, end), element }, end];\n}\n\nfunction parseTupleNode(source: string, start: number): [VariantTypeNode, number] {\n const items: VariantTypeNode[] = [];\n let position = start;\n\n while (source[position] !== \")\") {\n if (position >= source.length) {\n throw invalidType(source);\n }\n\n const [item, end] = parseNode(source, position);\n items.push(item);\n position = end;\n }\n\n return [{ kind: \"tuple\", items }, position + 1];\n}\n\nfunction parseEntryNode(source: string, start: number): [VariantTypeNode, number] {\n const [key, value, end] = parsePair(source, start);\n\n return [{ kind: \"entry\", key, value }, end];\n}\n\nconst parseNode = (source: string, start: number): [VariantTypeNode, number] => {\n const code = source[start];\n\n if (code === undefined) {\n throw invalidType(source);\n }\n\n const container = CONTAINER_PARSERS[code];\n\n if (container !== undefined) {\n return container(source, start + 1);\n }\n\n if (isBasicCode(code)) {\n return [{ kind: \"basic\", code }, start + 1];\n }\n\n throw invalidType(source);\n};\n\nconst parseVariantType = (typeString: string): VariantTypeNode => {\n const cached = parsedTypes.get(typeString);\n\n if (cached !== undefined) {\n return cached;\n }\n\n const [node, end] = parseNode(typeString, 0);\n\n if (end !== typeString.length) {\n throw invalidType(typeString);\n }\n\n parsedTypes.set(typeString, node);\n\n return node;\n};\n\nconst unpackChildren = (variant: GLib.Variant, unpackChild: (child: GLib.Variant) => unknown): unknown[] => {\n const children: unknown[] = [];\n const count = variant.nChildren();\n\n for (let index = 0; index < count; index += 1) {\n children.push(unpackChild(variant.getChildValue(index)));\n }\n\n return children;\n};\n\nconst unpackPair = (key: VariantTypeNode, value: VariantTypeNode, entry: GLib.Variant): [unknown, unknown] => [\n unpackVariant(key, entry.getChildValue(0)),\n unpackVariant(value, entry.getChildValue(1)),\n];\n\nconst unpackDict = (\n node: { key: VariantTypeNode; value: VariantTypeNode },\n variant: GLib.Variant,\n): Record<string, unknown> | Map<unknown, unknown> => {\n const entries = unpackChildren(variant, (entry) => unpackPair(node.key, node.value, entry)) as [unknown, unknown][];\n\n if (!isStringKeyed(node.key)) {\n return new Map(entries);\n }\n\n const stringEntries: [string, unknown][] = entries.map(([key, value]) => [key as string, value]);\n\n return Object.fromEntries(stringEntries);\n};\n\nconst unpackMaybe = (element: VariantTypeNode, variant: GLib.Variant): unknown => {\n const child = variant.getMaybe();\n\n return child === null ? null : unpackVariant(element, child);\n};\n\nconst unpackVariant = (node: VariantTypeNode, variant: GLib.Variant): unknown => {\n switch (node.kind) {\n case \"basic\": {\n return unpackBasic[node.code](variant);\n }\n case \"array\": {\n return unpackChildren(variant, (child) => unpackVariant(node.element, child));\n }\n case \"dict\": {\n return unpackDict(node, variant);\n }\n case \"entry\": {\n return unpackPair(node.key, node.value, variant);\n }\n case \"tuple\": {\n return node.items.map((item, index) => unpackVariant(item, variant.getChildValue(index)));\n }\n case \"maybe\": {\n return unpackMaybe(node.element, variant);\n }\n }\n};\n\nconst packValidatedString = (\n value: unknown,\n isValid: (value: string) => boolean,\n description: string,\n construct: (value: string) => GLib.Variant,\n): GLib.Variant => {\n if (typeof value !== \"string\" || !isValid(value)) {\n throw new Error(`\"${String(value)}\" is not a valid GVariant ${description}`);\n }\n\n return construct(value);\n};\n\nfunction packObjectPath(value: unknown): GLib.Variant {\n return packValidatedString(\n value,\n (path) => GLib.Variant.isObjectPath(path),\n \"object path\",\n (path) => GLib.Variant.newObjectPath(path),\n );\n}\n\nfunction packSignature(value: unknown): GLib.Variant {\n return packValidatedString(\n value,\n (signature) => GLib.Variant.isSignature(signature),\n \"type signature\",\n (signature) => GLib.Variant.newSignature(signature),\n );\n}\n\nconst packEntry = (key: VariantTypeNode, value: VariantTypeNode, pair: [unknown, unknown]): GLib.Variant =>\n GLib.Variant.newDictEntry(packVariant(key, pair[0]), packVariant(value, pair[1]));\n\nconst dictEntries = (value: unknown): [unknown, unknown][] =>\n value instanceof Map ? [...value] : Object.entries(value as Record<string, unknown>);\n\nconst packDict = (\n node: { entryTypeString: string; key: VariantTypeNode; value: VariantTypeNode },\n value: unknown,\n): GLib.Variant =>\n GLib.Variant.newArray(\n GLib.VariantType.new(node.entryTypeString),\n dictEntries(value).map((pair) => packEntry(node.key, node.value, pair)),\n );\n\nconst packMaybe = (node: { elementTypeString: string; element: VariantTypeNode }, value: unknown): GLib.Variant =>\n GLib.Variant.newMaybe(\n GLib.VariantType.new(node.elementTypeString),\n value === null ? null : packVariant(node.element, value),\n );\n\nconst packVariant = (node: VariantTypeNode, value: unknown): GLib.Variant => {\n switch (node.kind) {\n case \"basic\": {\n return packBasic[node.code](value);\n }\n case \"array\": {\n return GLib.Variant.newArray(\n GLib.VariantType.new(node.elementTypeString),\n (value as unknown[]).map((item) => packVariant(node.element, item)),\n );\n }\n case \"dict\": {\n return packDict(node, value);\n }\n case \"entry\": {\n return packEntry(node.key, node.value, value as [unknown, unknown]);\n }\n case \"tuple\": {\n return GLib.Variant.newTuple(\n node.items.map((item, index) => packVariant(item, (value as unknown[])[index])),\n );\n }\n case \"maybe\": {\n return packMaybe(node, value);\n }\n }\n};\n\nexport { parseVariantType, unpackVariant, packVariant, type VariantValue };\n"]}
@@ -1,400 +0,0 @@
1
- import * as GLib from "@gtkx/gi/glib";
2
-
3
- /** JavaScript type every GVariant basic type code unpacks to. */
4
- type BasicValueMap = {
5
- /** Boolean, held as a single byte reading 0 or 1. */
6
- b: boolean;
7
- /** Unsigned byte. */
8
- y: number;
9
- /** Signed 16-bit integer. */
10
- n: number;
11
- /** Unsigned 16-bit integer. */
12
- q: number;
13
- /** Signed 32-bit integer. */
14
- i: number;
15
- /** Unsigned 32-bit integer. */
16
- u: number;
17
- /** Index into the file descriptor list a message carries. */
18
- h: number;
19
- /** Double precision floating point number. */
20
- d: number;
21
- /** Signed 64-bit integer. */
22
- x: bigint;
23
- /** Unsigned 64-bit integer. */
24
- t: bigint;
25
- /** UTF-8 string, under no further constraint on what it holds. */
26
- s: string;
27
- /** D-Bus object path. */
28
- o: string;
29
- /** GVariant type signature. */
30
- g: string;
31
- /** Boxed variant holding a value of any type. */
32
- v: GLib.Variant;
33
- };
34
-
35
- /** Single-character code of one of the GVariant basic types in {@link BasicValueMap}. */
36
- type BasicCode = keyof BasicValueMap;
37
- /** Parses the element type of an array, yielding the array type it produces and the rest of the string. */
38
- type ParseArray<S extends string> = Parse<S> extends [infer V, infer R extends string] ? [V[], R] : never;
39
- /** Parses the element type of a maybe, yielding the nullable type it produces and the rest of the string. */
40
- type ParseMaybe<S extends string> = Parse<S> extends [infer V, infer R extends string] ? [V | null, R] : never;
41
-
42
- /** Collects tuple member types into `Acc` up to the closing parenthesis, yielding them and the rest of the string. */
43
- type ParseTuple<S extends string, Acc extends unknown[]> = S extends `)${infer Rest}`
44
- ? [Acc, Rest]
45
- : [Parse<S>] extends [never]
46
- ? never
47
- : Parse<S> extends [infer V, infer R extends string]
48
- ? ParseTuple<R, [...Acc, V]>
49
- : never;
50
-
51
- /** Types a dictionary entry key can hold. */
52
- type DictKey = string | number | bigint | boolean;
53
-
54
- /** Parses the key and value types of a dictionary entry, yielding them and the rest of the string after its brace. */
55
- type ParsePair<S extends string> =
56
- Parse<S> extends [infer K, infer R1 extends string]
57
- ? Parse<R1> extends [infer V, infer R2 extends string]
58
- ? R2 extends `}${infer R3}`
59
- ? [K] extends [DictKey]
60
- ? [K, V, R3]
61
- : never
62
- : never
63
- : never
64
- : never;
65
-
66
- /**
67
- * Parses a dictionary entry into the collection an array of those entries unpacks to, a record for string keys and a
68
- * `Map` otherwise, plus the rest of the string.
69
- */
70
- type ParseDict<S extends string> =
71
- ParsePair<S> extends [infer K, infer V, infer R extends string]
72
- ? [[K] extends [string] ? Record<string, V> : Map<K, V>, R]
73
- : never;
74
-
75
- /** Parses a standalone dictionary entry into a key and value pair, yielding it and the rest of the string. */
76
- type ParseEntry<S extends string> =
77
- ParsePair<S> extends [infer K, infer V, infer R extends string] ? [[K, V], R] : never;
78
-
79
- /** Parses what follows an `a` as a dictionary when it opens an entry, and as a plain array otherwise. */
80
- type ParseArrayOrDict<S extends string> = S extends `{${infer Rest}` ? ParseDict<Rest> : ParseArray<S>;
81
-
82
- /**
83
- * Parses the type at the head of `S`, yielding the JavaScript type it unpacks to and the rest of the string, or
84
- * `never` when the string is malformed.
85
- */
86
- type Parse<S extends string> = S extends `a${infer Rest}`
87
- ? ParseArrayOrDict<Rest>
88
- : S extends `m${infer Rest}`
89
- ? ParseMaybe<Rest>
90
- : S extends `(${infer Rest}`
91
- ? ParseTuple<Rest, []>
92
- : S extends `{${infer Rest}`
93
- ? ParseEntry<Rest>
94
- : S extends `${infer C}${infer Rest}`
95
- ? C extends BasicCode
96
- ? [BasicValueMap[C], Rest]
97
- : never
98
- : never;
99
-
100
- /** JavaScript type a variant of type string `S` unpacks to, or `unknown` when `S` is not one complete type. */
101
- type VariantValue<S extends string> = [Parse<S>] extends [never]
102
- ? unknown
103
- : Parse<S> extends [infer V, ""]
104
- ? V
105
- : unknown;
106
-
107
- type VariantTypeNode =
108
- | { kind: "basic"; code: BasicCode } |
109
- { kind: "array"; elementTypeString: string; element: VariantTypeNode } |
110
- { kind: "dict"; entryTypeString: string; key: VariantTypeNode; value: VariantTypeNode } |
111
- { kind: "entry"; key: VariantTypeNode; value: VariantTypeNode } |
112
- { kind: "tuple"; items: VariantTypeNode[] } |
113
- { kind: "maybe"; elementTypeString: string; element: VariantTypeNode };
114
-
115
- const BASIC_CODES = "bynqiuxthdsogv";
116
- const STRING_KEY_CODES: Set<string> = new Set(["s", "o", "g"]);
117
-
118
- const CONTAINER_PARSERS: Record<string, (source: string, start: number) => [VariantTypeNode, number]> = {
119
- a: parseArrayNode,
120
- m: parseMaybeNode,
121
- "(": parseTupleNode,
122
- "{": parseEntryNode,
123
- };
124
-
125
- const parsedTypes: Map<string, VariantTypeNode> = new Map();
126
-
127
- const unpackBasic: Record<BasicCode, (variant: GLib.Variant) => unknown> = {
128
- b: (variant) => variant.getBoolean(),
129
- y: (variant) => variant.getByte(),
130
- n: (variant) => variant.getInt16(),
131
- q: (variant) => variant.getUint16(),
132
- i: (variant) => variant.getInt32(),
133
- u: (variant) => variant.getUint32(),
134
- h: (variant) => variant.getHandle(),
135
- d: (variant) => variant.getDouble(),
136
- x: (variant) => variant.getInt64(),
137
- t: (variant) => variant.getUint64(),
138
- s: (variant) => variant.getString()[0],
139
- o: (variant) => variant.getString()[0],
140
- g: (variant) => variant.getString()[0],
141
- v: (variant) => variant.getVariant(),
142
- };
143
-
144
- const packBasic: Record<BasicCode, (value: unknown) => GLib.Variant> = {
145
- b: (value) => GLib.Variant.newBoolean(value as boolean),
146
- y: (value) => GLib.Variant.newByte(value as number),
147
- n: (value) => GLib.Variant.newInt16(value as number),
148
- q: (value) => GLib.Variant.newUint16(value as number),
149
- i: (value) => GLib.Variant.newInt32(value as number),
150
- u: (value) => GLib.Variant.newUint32(value as number),
151
- h: (value) => GLib.Variant.newHandle(value as number),
152
- d: (value) => GLib.Variant.newDouble(value as number),
153
- x: (value) => GLib.Variant.newInt64(value as bigint),
154
- t: (value) => GLib.Variant.newUint64(value as bigint),
155
- s: (value) => GLib.Variant.newString(value as string),
156
- o: packObjectPath,
157
- g: packSignature,
158
- v: (value) => GLib.Variant.newVariant(value as GLib.Variant),
159
- };
160
-
161
- const isBasicCode = (code: string): code is BasicCode => BASIC_CODES.includes(code);
162
- const isStringKeyed = (key: VariantTypeNode): boolean => key.kind === "basic" && STRING_KEY_CODES.has(key.code);
163
- const invalidType = (source: string): Error => new Error(`Invalid GVariant type string "${source}"`);
164
-
165
- const parsePair = (source: string, start: number): [VariantTypeNode, VariantTypeNode, number] => {
166
- const [key, keyEnd] = parseNode(source, start);
167
-
168
- if (key.kind !== "basic" || key.code === "v") {
169
- throw invalidType(source);
170
- }
171
-
172
- const [value, valueEnd] = parseNode(source, keyEnd);
173
-
174
- if (source[valueEnd] !== "}") {
175
- throw invalidType(source);
176
- }
177
-
178
- return [key, value, valueEnd + 1];
179
- };
180
-
181
- function parseArrayNode(source: string, start: number): [VariantTypeNode, number] {
182
- if (source[start] === "{") {
183
- const [key, value, end] = parsePair(source, start + 1);
184
-
185
- return [{ kind: "dict", entryTypeString: source.slice(start, end), key, value }, end];
186
- }
187
-
188
- const [element, end] = parseNode(source, start);
189
-
190
- return [{ kind: "array", elementTypeString: source.slice(start, end), element }, end];
191
- }
192
-
193
- function parseMaybeNode(source: string, start: number): [VariantTypeNode, number] {
194
- const [element, end] = parseNode(source, start);
195
-
196
- return [{ kind: "maybe", elementTypeString: source.slice(start, end), element }, end];
197
- }
198
-
199
- function parseTupleNode(source: string, start: number): [VariantTypeNode, number] {
200
- const items: VariantTypeNode[] = [];
201
- let position = start;
202
-
203
- while (source[position] !== ")") {
204
- if (position >= source.length) {
205
- throw invalidType(source);
206
- }
207
-
208
- const [item, end] = parseNode(source, position);
209
- items.push(item);
210
- position = end;
211
- }
212
-
213
- return [{ kind: "tuple", items }, position + 1];
214
- }
215
-
216
- function parseEntryNode(source: string, start: number): [VariantTypeNode, number] {
217
- const [key, value, end] = parsePair(source, start);
218
-
219
- return [{ kind: "entry", key, value }, end];
220
- }
221
-
222
- const parseNode = (source: string, start: number): [VariantTypeNode, number] => {
223
- const code = source[start];
224
-
225
- if (code === undefined) {
226
- throw invalidType(source);
227
- }
228
-
229
- const container = CONTAINER_PARSERS[code];
230
-
231
- if (container !== undefined) {
232
- return container(source, start + 1);
233
- }
234
-
235
- if (isBasicCode(code)) {
236
- return [{ kind: "basic", code }, start + 1];
237
- }
238
-
239
- throw invalidType(source);
240
- };
241
-
242
- const parseVariantType = (typeString: string): VariantTypeNode => {
243
- const cached = parsedTypes.get(typeString);
244
-
245
- if (cached !== undefined) {
246
- return cached;
247
- }
248
-
249
- const [node, end] = parseNode(typeString, 0);
250
-
251
- if (end !== typeString.length) {
252
- throw invalidType(typeString);
253
- }
254
-
255
- parsedTypes.set(typeString, node);
256
-
257
- return node;
258
- };
259
-
260
- const unpackChildren = (variant: GLib.Variant, unpackChild: (child: GLib.Variant) => unknown): unknown[] => {
261
- const children: unknown[] = [];
262
- const count = variant.nChildren();
263
-
264
- for (let index = 0; index < count; index += 1) {
265
- children.push(unpackChild(variant.getChildValue(index)));
266
- }
267
-
268
- return children;
269
- };
270
-
271
- const unpackPair = (key: VariantTypeNode, value: VariantTypeNode, entry: GLib.Variant): [unknown, unknown] => [
272
- unpackVariant(key, entry.getChildValue(0)),
273
- unpackVariant(value, entry.getChildValue(1)),
274
- ];
275
-
276
- const unpackDict = (
277
- node: { key: VariantTypeNode; value: VariantTypeNode },
278
- variant: GLib.Variant,
279
- ): Record<string, unknown> | Map<unknown, unknown> => {
280
- const entries = unpackChildren(variant, (entry) => unpackPair(node.key, node.value, entry)) as [unknown, unknown][];
281
-
282
- if (!isStringKeyed(node.key)) {
283
- return new Map(entries);
284
- }
285
-
286
- const stringEntries: [string, unknown][] = entries.map(([key, value]) => [key as string, value]);
287
-
288
- return Object.fromEntries(stringEntries);
289
- };
290
-
291
- const unpackMaybe = (element: VariantTypeNode, variant: GLib.Variant): unknown => {
292
- const child = variant.getMaybe();
293
-
294
- return child === null ? null : unpackVariant(element, child);
295
- };
296
-
297
- const unpackVariant = (node: VariantTypeNode, variant: GLib.Variant): unknown => {
298
- switch (node.kind) {
299
- case "basic": {
300
- return unpackBasic[node.code](variant);
301
- }
302
- case "array": {
303
- return unpackChildren(variant, (child) => unpackVariant(node.element, child));
304
- }
305
- case "dict": {
306
- return unpackDict(node, variant);
307
- }
308
- case "entry": {
309
- return unpackPair(node.key, node.value, variant);
310
- }
311
- case "tuple": {
312
- return node.items.map((item, index) => unpackVariant(item, variant.getChildValue(index)));
313
- }
314
- case "maybe": {
315
- return unpackMaybe(node.element, variant);
316
- }
317
- }
318
- };
319
-
320
- const packValidatedString = (
321
- value: unknown,
322
- isValid: (value: string) => boolean,
323
- description: string,
324
- construct: (value: string) => GLib.Variant,
325
- ): GLib.Variant => {
326
- if (typeof value !== "string" || !isValid(value)) {
327
- throw new Error(`"${String(value)}" is not a valid GVariant ${description}`);
328
- }
329
-
330
- return construct(value);
331
- };
332
-
333
- function packObjectPath(value: unknown): GLib.Variant {
334
- return packValidatedString(
335
- value,
336
- (path) => GLib.Variant.isObjectPath(path),
337
- "object path",
338
- (path) => GLib.Variant.newObjectPath(path),
339
- );
340
- }
341
-
342
- function packSignature(value: unknown): GLib.Variant {
343
- return packValidatedString(
344
- value,
345
- (signature) => GLib.Variant.isSignature(signature),
346
- "type signature",
347
- (signature) => GLib.Variant.newSignature(signature),
348
- );
349
- }
350
-
351
- const packEntry = (key: VariantTypeNode, value: VariantTypeNode, pair: [unknown, unknown]): GLib.Variant =>
352
- GLib.Variant.newDictEntry(packVariant(key, pair[0]), packVariant(value, pair[1]));
353
-
354
- const dictEntries = (value: unknown): [unknown, unknown][] =>
355
- value instanceof Map ? [...value] : Object.entries(value as Record<string, unknown>);
356
-
357
- const packDict = (
358
- node: { entryTypeString: string; key: VariantTypeNode; value: VariantTypeNode },
359
- value: unknown,
360
- ): GLib.Variant =>
361
- GLib.Variant.newArray(
362
- GLib.VariantType.new(node.entryTypeString),
363
- dictEntries(value).map((pair) => packEntry(node.key, node.value, pair)),
364
- );
365
-
366
- const packMaybe = (node: { elementTypeString: string; element: VariantTypeNode }, value: unknown): GLib.Variant =>
367
- GLib.Variant.newMaybe(
368
- GLib.VariantType.new(node.elementTypeString),
369
- value === null ? null : packVariant(node.element, value),
370
- );
371
-
372
- const packVariant = (node: VariantTypeNode, value: unknown): GLib.Variant => {
373
- switch (node.kind) {
374
- case "basic": {
375
- return packBasic[node.code](value);
376
- }
377
- case "array": {
378
- return GLib.Variant.newArray(
379
- GLib.VariantType.new(node.elementTypeString),
380
- (value as unknown[]).map((item) => packVariant(node.element, item)),
381
- );
382
- }
383
- case "dict": {
384
- return packDict(node, value);
385
- }
386
- case "entry": {
387
- return packEntry(node.key, node.value, value as [unknown, unknown]);
388
- }
389
- case "tuple": {
390
- return GLib.Variant.newTuple(
391
- node.items.map((item, index) => packVariant(item, (value as unknown[])[index])),
392
- );
393
- }
394
- case "maybe": {
395
- return packMaybe(node, value);
396
- }
397
- }
398
- };
399
-
400
- export { parseVariantType, unpackVariant, packVariant, type VariantValue };