@gjsify/gtk-host 0.51.1 → 0.53.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 +207 -7
- package/lib/esm/accessibility.js +1 -0
- package/lib/esm/conformance/at-context.js +1 -0
- package/lib/esm/conformance/index.js +1 -1
- package/lib/esm/conformance/shared-tree-builder.js +1 -0
- package/lib/esm/errors.js +1 -1
- package/lib/esm/fonts.js +1 -1
- package/lib/esm/generated/accessibility.js +1 -0
- package/lib/esm/host.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/menu.js +1 -1
- package/lib/esm/policies.js +1 -1
- package/lib/esm/props.js +1 -1
- package/lib/esm/registry.js +1 -1
- package/lib/types/accessibility.d.ts +56 -0
- package/lib/types/accessibility.spec.d.ts +2 -0
- package/lib/types/attrs.d.ts +15 -2
- package/lib/types/conformance/at-context.d.ts +31 -0
- package/lib/types/conformance/index.d.ts +2 -0
- package/lib/types/conformance/nick-vectors.d.mts +26 -0
- package/lib/types/conformance/shared-tree-builder.d.ts +26 -0
- package/lib/types/errors.d.ts +80 -1
- package/lib/types/font-dir.d.ts +5 -3
- package/lib/types/fonts.d.ts +29 -3
- package/lib/types/generated/accessibility.d.ts +208 -0
- package/lib/types/generated/enum-values.d.mts +1 -1
- package/lib/types/generated/props.d.ts +3310 -186
- package/lib/types/generated/surface-data.d.mts +10 -0
- package/lib/types/generated/value-types.d.mts +28 -0
- package/lib/types/generator/emit-types.d.mts +22 -0
- package/lib/types/generator/model.d.mts +20 -0
- package/lib/types/host.d.ts +26 -0
- package/lib/types/index.d.ts +3 -3
- package/lib/types/policies.d.ts +58 -1
- package/lib/types/props.d.ts +32 -5
- package/lib/types/react-jsx-runtime.d.ts +3 -3
- package/lib/types/registry.d.ts +54 -0
- package/lib/types/testing/gate.d.mts +3 -3
- package/lib/types/types.d.ts +66 -0
- package/package.json +20 -17
|
@@ -6,6 +6,16 @@ export declare const OWN_SIGNALS: Readonly<Record<string, readonly string[]>>;
|
|
|
6
6
|
export declare const DECLS: Readonly<Record<string, readonly string[]>>;
|
|
7
7
|
/** Enum GType -> the nicks the surface offers. */
|
|
8
8
|
export declare const ENUM_NICKS: Readonly<Record<string, readonly string[]>>;
|
|
9
|
+
/**
|
|
10
|
+
* Bitfield GType -> the member nicks the surface offers, for the bitfields a property
|
|
11
|
+
* of this surface carries.
|
|
12
|
+
*
|
|
13
|
+
* Derived from `FLAG_VALUES`' KEYS rather than from a nick list, because `@girs`
|
|
14
|
+
* publishes none for a bitfield — GObject resolves no nick SET, so the vocabulary says
|
|
15
|
+
* nothing about sets and the members keep their names in the value table. Held against
|
|
16
|
+
* the installed library the same way `ENUM_NICKS` is.
|
|
17
|
+
*/
|
|
18
|
+
export declare const FLAG_NICKS: Readonly<Record<string, readonly string[]>>;
|
|
9
19
|
/** Widget GType -> its kebab tag. */
|
|
10
20
|
export declare const TAGS: Readonly<Record<string, string>>;
|
|
11
21
|
/**
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The libraries these rows were read from, in the same provenance grammar
|
|
3
|
+
* `methods.mts` uses so one parser reads both lines.
|
|
4
|
+
*/
|
|
5
|
+
export declare const VALUE_TYPES_PROVENANCE = "Adw-1/1.9.3 Gio-2.0 Gtk-4.0/4.22.5";
|
|
6
|
+
/**
|
|
7
|
+
* `<Namespace>.<Member>` -> what the typelib says that type is.
|
|
8
|
+
*
|
|
9
|
+
* One row per entry of `CONSTRUCTIBLE_VALUES` in `scripts/value-types.mjs`: the ledger is
|
|
10
|
+
* the INPUT, this is the answer. `gtype` is the GType the class registers; `widget` is
|
|
11
|
+
* whether its declared parent chain reaches `GtkWidget`, and a `true` here is the
|
|
12
|
+
* finding the whole ledger is guarded for — a widget excused as a value would be the
|
|
13
|
+
* second place a widget is declared.
|
|
14
|
+
*/
|
|
15
|
+
export declare const VALUE_TYPES: Readonly<Record<string, {
|
|
16
|
+
gtype: string;
|
|
17
|
+
widget: boolean;
|
|
18
|
+
}>>;
|
|
19
|
+
/**
|
|
20
|
+
* `<Namespace>.<Member>` -> the loaded typelib that declares no such GObject.
|
|
21
|
+
*
|
|
22
|
+
* The declared remainder, so "every ledger entry has an answer" can be a rule rather than
|
|
23
|
+
* a hope: a member in NEITHER table is a ledger the artifact predates, and the gate says
|
|
24
|
+
* so instead of passing over it. An entry here is a ledger entry that is simply wrong —
|
|
25
|
+
* unlike the sibling artifacts' remainders, it cannot be a version gap, because nothing
|
|
26
|
+
* in this repository may excuse a member whose type the installed GIR has never heard of.
|
|
27
|
+
*/
|
|
28
|
+
export declare const VALUE_TYPES_UNDECLARED: Readonly<Record<string, string>>;
|
|
@@ -40,6 +40,28 @@ export interface EmittedFile {
|
|
|
40
40
|
readonly text: string;
|
|
41
41
|
}
|
|
42
42
|
export declare function emitProps(model: SurfaceModel, provenance: string): EmittedFile;
|
|
43
|
+
/**
|
|
44
|
+
* Emit GTK's ARIA surface: the slot table the runtime reads, and the props interface.
|
|
45
|
+
*
|
|
46
|
+
* WHY THIS FILE EXISTS AND `props.ts` COULD NOT CARRY IT. Every other name a renderer can
|
|
47
|
+
* write on a widget is a GObject property, and the host resolves those through the
|
|
48
|
+
* ParamSpec of the INSTALLED class — the table travels with the package, the coercion
|
|
49
|
+
* travels with the user's GTK. An ARIA slot has no ParamSpec. `GtkAccessible` installs
|
|
50
|
+
* exactly one property, `accessible-role`; the other 53 names live in three ENUMS and are
|
|
51
|
+
* written through three calls, and the value type of each is stated only in that enum
|
|
52
|
+
* member's GIR DOCUMENTATION. So the type has to SHIP, and this is the one generated file
|
|
53
|
+
* whose data the runtime cannot re-derive from the object in front of it.
|
|
54
|
+
*
|
|
55
|
+
* WHY THE TABLE AND THE INTERFACE ARE IN ONE FILE. They are the two halves of one answer
|
|
56
|
+
* and they are keyed identically; split, the day a GTK release adds a name is the day the
|
|
57
|
+
* type surface and the runtime refusal disagree about whether it exists.
|
|
58
|
+
*
|
|
59
|
+
* THE FLOOR IS THE LOAD-BEARING GATE, as it is in `emit.mts`: a reader that silently
|
|
60
|
+
* yields three rows and a generator reporting success over it look identical, and here
|
|
61
|
+
* an under-read does not fail loudly downstream — it emits a smaller vocabulary, and
|
|
62
|
+
* every name it dropped becomes `unknown-aria` at a user's call site.
|
|
63
|
+
*/
|
|
64
|
+
export declare function emitAccessibility(model: SurfaceModel, provenance: string, floor?: number): EmittedFile;
|
|
43
65
|
/**
|
|
44
66
|
* Emit the data the runtime cross-check reads.
|
|
45
67
|
*
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* of that format instead of two. Only the shape survived, which is why the file is
|
|
15
15
|
* `model.mts` and no longer `surface.mts`: `surface` now names the `@girs` subpath.
|
|
16
16
|
*/
|
|
17
|
+
import type { AriaSlot } from '../types.js';
|
|
17
18
|
import type { WidgetRow } from './emit.mjs';
|
|
18
19
|
export interface PropMember {
|
|
19
20
|
readonly kebab: string;
|
|
@@ -75,9 +76,28 @@ export interface SurfaceModel {
|
|
|
75
76
|
readonly closure: ReadonlyMap<string, readonly string[]>;
|
|
76
77
|
/** Enum GType -> nicks, for the emitted aliases and for the runtime nick check. */
|
|
77
78
|
readonly enumNicks: ReadonlyMap<string, readonly string[]>;
|
|
79
|
+
/**
|
|
80
|
+
* Bitfield GType -> member nicks, for the bitfields this surface's properties carry.
|
|
81
|
+
*
|
|
82
|
+
* Separate from `enumNicks`, because the two answer different questions and one map
|
|
83
|
+
* would hide it: an enum property takes ONE nick, so the union IS the type, while a
|
|
84
|
+
* bitfield property takes a `|`-joined SET and the union is only its members.
|
|
85
|
+
* `emit-types.mts` renders each kind accordingly.
|
|
86
|
+
*/
|
|
87
|
+
readonly flagNicks: ReadonlyMap<string, readonly string[]>;
|
|
78
88
|
readonly namespacesUsed: ReadonlySet<string>;
|
|
79
89
|
/** Namespace -> the `@girs` package that types it, so the emitter needs no second source. */
|
|
80
90
|
readonly packages: Readonly<Record<string, string>>;
|
|
91
|
+
/**
|
|
92
|
+
* ARIA name -> its table, value kind and enum, merged over every vocabulary read.
|
|
93
|
+
*
|
|
94
|
+
* Keyed by the NAME alone, not by `<table>.<name>` the way `@girs` keys it, and that
|
|
95
|
+
* is a measured property rather than a convenience: across the three tables of gtk4
|
|
96
|
+
* 4.23.3 the 53 names are distinct, so one authored key can only ever mean one slot.
|
|
97
|
+
* `girs-vocabulary.mts` re-checks it on every run, because the day GTK adds a name a
|
|
98
|
+
* second table already carries, a map would silently keep one of the two.
|
|
99
|
+
*/
|
|
100
|
+
readonly aria: ReadonlyMap<string, AriaSlot>;
|
|
81
101
|
/**
|
|
82
102
|
* Base -> members it must not contribute, because a nearer declaration disagrees.
|
|
83
103
|
*
|
package/lib/types/host.d.ts
CHANGED
|
@@ -21,6 +21,32 @@ export declare const isText: (node: HostNode) => node is HostText;
|
|
|
21
21
|
export declare function materialize(el: HostElement): GObject.Object;
|
|
22
22
|
export declare function setProp(el: HostElement, key: string, next: unknown, _prev?: unknown): void;
|
|
23
23
|
export declare function setEventHandler(el: HostElement, prop: string, next: ((...args: unknown[]) => unknown) | null): void;
|
|
24
|
+
/**
|
|
25
|
+
* The ARIA object, diffed against the one it replaces.
|
|
26
|
+
*
|
|
27
|
+
* ONE GROUPED PROP RATHER THAN 53 FLAT `aria*` ONES, and the reasons are measured rather
|
|
28
|
+
* than aesthetic. (1) TypeScript exempts every hyphen-containing JSX attribute from
|
|
29
|
+
* excess-property checking — the measurement `emit-types.mts` already records for the
|
|
30
|
+
* kebab property spellings — so a flat `aria-labell` would be accepted in silence, while a
|
|
31
|
+
* key inside a fresh object literal IS checked. (2) The ARIA names are not the widget's
|
|
32
|
+
* properties and collide with them: `label`, `orientation`, `checked`, `expanded` and
|
|
33
|
+
* `selected` are all both, and `orientation` is settable on a `GtkLabel` that implements no
|
|
34
|
+
* `GtkOrientable` at all — one object keeps the two vocabularies apart by construction
|
|
35
|
+
* instead of by prefix. (3) The other surface over this same vocabulary already spells it
|
|
36
|
+
* this way: a `.blp` author writes `accessibility { label: "…"; }` (ADR 0034). (4) `setProp`
|
|
37
|
+
* already has this shape for `layout` — a structured, non-ParamSpec prop routed to its own
|
|
38
|
+
* mechanism — so this adds one reserved key to the host, not 53.
|
|
39
|
+
*
|
|
40
|
+
* REFUSED ON THE CLASS, not on the widget: every framework builds bottom-up, so props are
|
|
41
|
+
* authored long before materialisation, and asking the instance would report
|
|
42
|
+
* `<gtk-string-list accessibility={…}>` from inside a later `materialize` rather than at the
|
|
43
|
+
* call that wrote it.
|
|
44
|
+
*
|
|
45
|
+
* The plan is built BEFORE anything is recorded, for the reason the property path states:
|
|
46
|
+
* `el.accessibility` is replayed verbatim by `replayInto`, so a refused value kept there
|
|
47
|
+
* would poison the next rebuild.
|
|
48
|
+
*/
|
|
49
|
+
export declare function setAccessibility(el: HostElement, next: unknown): void;
|
|
24
50
|
export declare function setSlot(el: HostElement, slot: string | null): void;
|
|
25
51
|
export declare function setText(node: HostText | HostAnchor, data: string): void;
|
|
26
52
|
/** Vue's bulk path and React's `shouldSetTextContent`: drop children, set the sink. */
|
package/lib/types/index.d.ts
CHANGED
|
@@ -3,9 +3,9 @@ export { GtkHostError } from './errors.js';
|
|
|
3
3
|
export { adopt, createAnchor, createDetachedContainer, createElement, createText, destroyChildren, destroy, disconnectHandlers, firstChild, insert, isHostElement, isText, materialize, mountRoot, nextSibling, parentNode, prevSibling, remove, setElementText, setEventHandler, setProp, setSlot, setText, widgetOf, } from './host.js';
|
|
4
4
|
export { addressOf, isPortal, placementOf, portalOf, reorderMode } from './policies.js';
|
|
5
5
|
export { toSignalName, isEventProp } from './signals.js';
|
|
6
|
-
export { constructOnlyNames, isConstructOnly, isWritable, lookupEnumNick, paramSpecs, toPropertyName, } from './props.js';
|
|
6
|
+
export { constructOnlyNames, gtypeOfName, isConstructOnly, isWritable, lookupEnumNick, paramSpecs, toPropertyName, } from './props.js';
|
|
7
7
|
export { assertInjective, tagOf } from './tags.js';
|
|
8
8
|
export { blankReason, checkRendered, probeEnabled, runHostProbe, runHostProbeApp, shotEvidence, type CaptureWidget, type HostProbe, type HostProbeApp, type ProbeCheck, type ShotEvidence, } from './probe.js';
|
|
9
|
-
export type { ElementChild, ElementChildren, JsxAttributes, RawSignalAttributes, SlotAttribute, VueAttributes, WithOnce, } from './attrs.js';
|
|
10
|
-
export { clearRegistry, hasWidget, lookupWidget, nearestRegistered, registerWidget, registerWidgets, registeredTags, } from './registry.js';
|
|
9
|
+
export type { AccessibilityAttribute, ElementChild, ElementChildren, JsxAttributes, RawSignalAttributes, SlotAttribute, VueAttributes, WithOnce, } from './attrs.js';
|
|
10
|
+
export { clearRegistry, classOf, hasClass, hasWidget, lookupWidget, nearestRegistered, registerWidget, registerWidgets, registeredTags, requireClass, type InstalledClass, } from './registry.js';
|
|
11
11
|
export { ADW_DESCRIPTORS, BUILTIN_DESCRIPTORS, CURATED_DESCRIPTORS, GENERATED_PROVENANCE, GENERATED_WIDGETS, GTK_DESCRIPTORS, mergeGenerated, registerBuiltinWidgets, tableProvenance, } from './descriptors/index.js';
|
package/lib/types/policies.d.ts
CHANGED
|
@@ -3,6 +3,63 @@ import Gtk from 'gi://Gtk?version=4.0';
|
|
|
3
3
|
import type { ChildPolicy, HostElement, NodePlacement, WidgetDescriptor } from './types.js';
|
|
4
4
|
/** The object the PARENT addresses: a wrapper row when the policy demands one. */
|
|
5
5
|
export declare function addressOf(el: HostElement): Gtk.Widget;
|
|
6
|
+
/**
|
|
7
|
+
* The property a one-child slot method writes — `set_title_widget` -> `title-widget`.
|
|
8
|
+
*
|
|
9
|
+
* GTK SPELLS ONE PLACEMENT TWICE and both spellings reach the same widget:
|
|
10
|
+
* `adw_header_bar_buildable_add_child`'s `<child type="title">` branch calls
|
|
11
|
+
* `adw_header_bar_set_title_widget`, i.e. writes the `title-widget` property. An authored
|
|
12
|
+
* tree carries whichever spelling its SOURCE had — a Blueprint `[title]` bracket is the
|
|
13
|
+
* first, a `title-widget:` property-valued child the second — and `SharedTreeNode.slot`
|
|
14
|
+
* conflates the two by construction (the projection's own header records that, and that it
|
|
15
|
+
* cannot be inverted). A descriptor declaring only the buildable type would therefore refuse
|
|
16
|
+
* a placement GTK itself accepts.
|
|
17
|
+
*
|
|
18
|
+
* A CASE RULE OVER THE SETTER'S OWN NAME, never a table: an ADDER (`pack_start`,
|
|
19
|
+
* `add_top_bar`, `add_prefix`) writes no property, so such a slot answers to its buildable
|
|
20
|
+
* type alone — which is why `[start]` has no second spelling to admit.
|
|
21
|
+
*/
|
|
22
|
+
export declare function slotPropertyOf(method: string): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Every name a policy answers to — what a refusal lists.
|
|
25
|
+
*
|
|
26
|
+
* Each declared key is followed by the property spelling it also answers to, so the order is
|
|
27
|
+
* `['start', 'title', 'title-widget', 'end']` and not the keys first. That is deliberate: a
|
|
28
|
+
* reader matching their own `slot="title-widget"` against the list finds it beside the key it
|
|
29
|
+
* resolves to, rather than in a second group they have to pair up themselves.
|
|
30
|
+
*/
|
|
31
|
+
export declare function slotNames(policy: ChildPolicy): string[];
|
|
32
|
+
/**
|
|
33
|
+
* The DECLARED slot key an authored name asks for, or the default when it asks for nothing.
|
|
34
|
+
*
|
|
35
|
+
* EVERY read of `child.slot` in this file goes through here, so the property spelling
|
|
36
|
+
* {@link slotPropertyOf} admits is canonical everywhere at once: a placement resolved
|
|
37
|
+
* through `title-widget` and a detach resolved through `title` would otherwise be two
|
|
38
|
+
* different keys to `policy.slots[…]`, and the child would leak at unmount.
|
|
39
|
+
*
|
|
40
|
+
* THE DEFAULT IS CHECKED LIKE ANY OTHER NAME, and it is the one that has no author to
|
|
41
|
+
* blame. `defaultSlot` and `slots` are two fields of a descriptor, and an application
|
|
42
|
+
* registers descriptors of its own — nothing else in this package holds the two together.
|
|
43
|
+
* An unchecked default reaches `policy.slots[slot]` as `undefined` and the caller calls it:
|
|
44
|
+
* `TypeError: host[undefined] is not a function`, which is exactly the shape
|
|
45
|
+
* {@link errors.unknownSlot} exists to replace. Returning only keys that are IN `slots` is
|
|
46
|
+
* what makes the lookup at every call site total.
|
|
47
|
+
*/
|
|
48
|
+
export declare function slottedSlot(policy: Extract<ChildPolicy, {
|
|
49
|
+
kind: 'slotted';
|
|
50
|
+
}>, authored: string | null | undefined, gtype: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* A slot the parent cannot honour is refused BY NAME, whatever its policy kind.
|
|
53
|
+
*
|
|
54
|
+
* `slotted` already refused an unknown slot; every OTHER kind read `child.slot` as nothing
|
|
55
|
+
* at all, so a name it has no destination for put the widget in the one place it does have
|
|
56
|
+
* and said nothing. That is the defect measured on a real `.blp`: an authored placement
|
|
57
|
+
* dropped, the widget on screen in the wrong container, exit 0. A `single` parent accepts
|
|
58
|
+
* the property its own setter writes (`AdwApplicationWindow` + `set_content` accepts
|
|
59
|
+
* `content`) and nothing else; `keyed` reads the slot as its page NAME, which is a
|
|
60
|
+
* destination, so it is left alone.
|
|
61
|
+
*/
|
|
62
|
+
export declare function refuseUnknownSlot(parent: HostElement, child: HostElement): void;
|
|
6
63
|
/**
|
|
7
64
|
* `Gtk.ListBox` and `Gtk.FlowBox` wrap arbitrary children; the wrap is the host's job.
|
|
8
65
|
*
|
|
@@ -17,7 +74,7 @@ export declare function addressOf(el: HostElement): Gtk.Widget;
|
|
|
17
74
|
* is that `gtk_list_box_remove` does not unwrap, so without this the child leaks behind
|
|
18
75
|
* one `Gtk-WARNING` at unmount.
|
|
19
76
|
*/
|
|
20
|
-
export declare function makeWrapper(
|
|
77
|
+
export declare function makeWrapper(descriptor: WidgetDescriptor, child: Gtk.Widget, slot: string | null): Gtk.Widget | null;
|
|
21
78
|
/**
|
|
22
79
|
* A container the host owns that no window shows — the DOM's detached `<div>`.
|
|
23
80
|
*
|
package/lib/types/props.d.ts
CHANGED
|
@@ -24,25 +24,52 @@ export declare const isConstructOnly: (spec: GObject.ParamSpec) => boolean;
|
|
|
24
24
|
/** Construct-only property names of a class, in declaration order. */
|
|
25
25
|
export declare function constructOnlyNames(klass: GObject.ObjectClass, gtypeName: string): string[];
|
|
26
26
|
/**
|
|
27
|
-
* The
|
|
27
|
+
* The GType a name registers on this host, forcing the registration if it has to.
|
|
28
|
+
*
|
|
29
|
+
* `type_from_name` is asked FIRST because it is the answer that needs no table. It
|
|
30
|
+
* answers null until something has touched the type, which is why the table is still
|
|
31
|
+
* reachable at all: reading `Gio.PasswordSave` is what registers `GPasswordSave`.
|
|
32
|
+
*
|
|
33
|
+
* NEITHER BRANCH IS THE FIX ALONE, and the order is what makes the measured case work:
|
|
34
|
+
* a type nobody has read is absent from `type_from_name`, and a name
|
|
35
|
+
* {@link giTypeObject} cannot reach is absent from the table. Exported because it is
|
|
36
|
+
* THE answer to "does this host have that type" — a consumer gating on a GTK version
|
|
37
|
+
* asks here rather than walking a namespace list of its own.
|
|
38
|
+
*/
|
|
39
|
+
export declare function gtypeOfName(gtypeName: string): GObject.GType | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* The value a nick names on an enum or bitfield GType, or undefined if it names none.
|
|
28
42
|
*
|
|
29
43
|
* Exported for the generated surface's own check: the type surface offers a union
|
|
30
44
|
* of nicks per enum, and a nick this host cannot resolve would type-check and then
|
|
31
45
|
* be refused at runtime. `generated.spec.ts` resolves every emitted nick through
|
|
32
46
|
* this function, so the GIR-member-to-nick spelling is measured rather than
|
|
33
47
|
* assumed. Also the primitive a renderer needs for a "did you mean" diagnostic.
|
|
48
|
+
*
|
|
49
|
+
* The NAME is kept in the signature although a GType would need no lookup, because
|
|
50
|
+
* every caller has the name and not the type — the check reads it off a generated
|
|
51
|
+
* table, a renderer off `GObject.type_name(spec.value_type)`.
|
|
34
52
|
*/
|
|
35
53
|
export declare const lookupEnumNick: (gtypeName: string, nick: string) => number | undefined;
|
|
36
54
|
/**
|
|
37
|
-
* The member names an installed enum registers, or `undefined` if this
|
|
55
|
+
* The member names an installed enum or bitfield registers, or `undefined` if this
|
|
56
|
+
* host has none.
|
|
38
57
|
*
|
|
39
58
|
* The INVERSE of {@link lookupEnumNick}, and it exists for the one question that
|
|
40
59
|
* function cannot answer: a nick the vocabulary never emitted is absent from every
|
|
41
|
-
* list a check could iterate, so only the host's own members can reveal it.
|
|
42
|
-
*
|
|
43
|
-
*
|
|
60
|
+
* list a check could iterate, so only the host's own members can reveal it. GJS
|
|
61
|
+
* offers no route to a `GEnumClass`, so the members come off the namespace object —
|
|
62
|
+
* which is the whole remaining reason {@link GI_NAMESPACES} exists.
|
|
44
63
|
*
|
|
45
64
|
* `$gtype` and anything non-numeric are not members; GJS puts both on the same object.
|
|
65
|
+
*
|
|
66
|
+
* AND THE TYPE HAS TO BE ONE, or the widened {@link giTypeObject} turns this into a
|
|
67
|
+
* second answer rather than a wider one. It now returns a CLASS as readily as an enum,
|
|
68
|
+
* and a class carries no numeric members — `undefined` would be wrong (the type is
|
|
69
|
+
* there) and `[]` is worse (it reads as "an enum that registers nothing", which is the
|
|
70
|
+
* claim every caller is entitled to trust). The GType the lookup already confirmed is
|
|
71
|
+
* what asks, so this is the same predicate the nicks branches above are routed on
|
|
72
|
+
* rather than a new way of spelling it.
|
|
46
73
|
*/
|
|
47
74
|
export declare function enumMembers(gtypeName: string): string[] | undefined;
|
|
48
75
|
/**
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
* The element list itself is the generated `WidgetPropsByTag`/`WidgetClassByTag`,
|
|
29
29
|
* which `scripts/check-type-surfaces.mjs` already holds negative-first through its
|
|
30
30
|
* `jsx` half. The React-specific plumbing below has no half yet — that gap, and
|
|
31
|
-
* why adding one is not a one-liner, is in `status/open-todos.md`. Its RUNTIME
|
|
31
|
+
* why adding one is not a one-liner, is in `status/open-todos/README.md`. Its RUNTIME
|
|
32
32
|
* half is `adapters/react.spec.ts`.
|
|
33
33
|
*/
|
|
34
34
|
import type { Key, ReactElement, ReactNode, Ref } from 'react';
|
|
35
35
|
import type { WidgetClassByTag, WidgetPropsByTag } from './generated/props.js';
|
|
36
|
-
import type { RawSignalAttributes, SlotAttribute, WithOnce, WithPortableValues } from './attrs.js';
|
|
36
|
+
import type { AccessibilityAttribute, RawSignalAttributes, SlotAttribute, WithOnce, WithPortableValues } from './attrs.js';
|
|
37
37
|
export { Fragment } from 'react/jsx-runtime';
|
|
38
38
|
/**
|
|
39
39
|
* React's own factories, RE-TYPED over this package's element list.
|
|
@@ -67,7 +67,7 @@ type GtkJsxDevFactory = (type: GtkElementType, props: unknown, key: Key | undefi
|
|
|
67
67
|
* element TS2559. `children` must also be optional, or a self-closing tag is
|
|
68
68
|
* TS2741.
|
|
69
69
|
*/
|
|
70
|
-
export interface ReactWidgetAttributes<T> extends SlotAttribute, RawSignalAttributes {
|
|
70
|
+
export interface ReactWidgetAttributes<T> extends AccessibilityAttribute, SlotAttribute, RawSignalAttributes {
|
|
71
71
|
children?: ReactNode;
|
|
72
72
|
ref?: Ref<T> | undefined;
|
|
73
73
|
key?: Key | null | undefined;
|
package/lib/types/registry.d.ts
CHANGED
|
@@ -4,6 +4,60 @@ export declare function registerWidget(descriptor: WidgetDescriptor): void;
|
|
|
4
4
|
export declare function registerWidgets(descriptors: readonly WidgetDescriptor[]): void;
|
|
5
5
|
export declare function lookupWidget(tag: string): WidgetDescriptor;
|
|
6
6
|
export declare const hasWidget: (tag: string) => boolean;
|
|
7
|
+
/** A row's class, in the shape every consumer here needs it. */
|
|
8
|
+
export type InstalledClass = GObject.ObjectClass & (new (props?: Record<string, unknown>) => GObject.Object);
|
|
9
|
+
/**
|
|
10
|
+
* The class the RUNNING typelib has for this row, or `null` when it has none.
|
|
11
|
+
*
|
|
12
|
+
* The general form of "does this GTK have that class", and the only honest place
|
|
13
|
+
* to ask it: the generated table is produced from ONE platform's GIR (#1446), and
|
|
14
|
+
* a platform does not build every class that GIR describes — GTK `#ifdef`s its
|
|
15
|
+
* Unix print stack out on Windows, so `GtkPrintUnixDialog` and
|
|
16
|
+
* `GtkPageSetupUnixDialog` are rows whose class is `undefined` there and a real
|
|
17
|
+
* class on Linux and macOS. Nothing narrower is available: the vocabulary comes
|
|
18
|
+
* from one GIR pool with no second platform to compare against, and a claim
|
|
19
|
+
* derived from a NAME (`*Unix*`) breaks precisely when it matters, on the next
|
|
20
|
+
* absent class nobody spelled that way.
|
|
21
|
+
*
|
|
22
|
+
* THE CAST is where the gap between the declared type and the runtime is
|
|
23
|
+
* admitted, ONCE, with the reason. `ctor` is typed as promising a constructor
|
|
24
|
+
* unconditionally, which is what lets `new Klass(props)` read as a constructor
|
|
25
|
+
* call; the promise is true on every host the table was generated on and false
|
|
26
|
+
* on a host that omits a class, and the admission belongs beside the question
|
|
27
|
+
* rather than at each of the dozen call sites.
|
|
28
|
+
*
|
|
29
|
+
* WHY THE ROW'S OWN `ctor()` IS THE ORACLE, and it is a measured trap rather
|
|
30
|
+
* than a stylistic choice. `GObject.type_from_name` is the one-call version of
|
|
31
|
+
* this question and it answers WRONG in the direction that costs a working row:
|
|
32
|
+
* measured on gjs 1.88.1 / Homebrew GTK 4.24.0, `type_from_name('GtkPrintUnixDialog')`
|
|
33
|
+
* answers **0** while `Gtk.PrintUnixDialog` is present and constructs — a typelib
|
|
34
|
+
* registers a class when the namespace member is first READ, not when the
|
|
35
|
+
* typelib loads. `ctor()` IS that read, which is why it answers correctly in
|
|
36
|
+
* both directions and why nothing here calls `type_from_name`. It also costs
|
|
37
|
+
* nothing to ask per row: an oracle over the WHOLE table has to force the
|
|
38
|
+
* registration of every class it walks, whereas a row is only ever asked about
|
|
39
|
+
* when something is about to use it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function classOf(descriptor: {
|
|
42
|
+
readonly ctor: () => unknown;
|
|
43
|
+
}): InstalledClass | null;
|
|
44
|
+
/** Whether this host has the class a row names — a table sweep's way to not be a row. */
|
|
45
|
+
export declare const hasClass: (descriptor: {
|
|
46
|
+
readonly ctor: () => unknown;
|
|
47
|
+
}) => boolean;
|
|
48
|
+
/**
|
|
49
|
+
* {@link classOf}, refusing BY NAME rather than handing back `undefined`.
|
|
50
|
+
*
|
|
51
|
+
* The single gate every read of a row's class goes through, so an absent class is
|
|
52
|
+
* one named refusal instead of six anonymous `TypeError`s — dereferencing it
|
|
53
|
+
* produced `Cannot read properties of undefined (reading 'list_properties')` and
|
|
54
|
+
* `… (reading '$gtype')` with no row in either message, which is how a
|
|
55
|
+
* one-platform-generated table arrived as six failures that named one class.
|
|
56
|
+
*/
|
|
57
|
+
export declare function requireClass(descriptor: {
|
|
58
|
+
readonly gtype: string;
|
|
59
|
+
readonly ctor: () => unknown;
|
|
60
|
+
}): InstalledClass;
|
|
7
61
|
/** Every registered GType name — the conformance suite walks this, so coverage is data. */
|
|
8
62
|
export declare const registeredTags: () => string[];
|
|
9
63
|
/**
|
|
@@ -10,9 +10,9 @@ export declare const gated: (gate: DiagnosticsGate, name: string, body: () => Pr
|
|
|
10
10
|
* failure mode rather than taste.
|
|
11
11
|
*
|
|
12
12
|
* A capability can only be PROBED — nothing about `(os, env)` answers "is the Gtk
|
|
13
|
-
* typelib reachable from this process"
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* typelib reachable from this process". A probe that answers "no" makes the whole
|
|
14
|
+
* suite STAND DOWN, and `requireAxes` cannot catch that: it only holds axes the
|
|
15
|
+
* host MATCHES (`GJSIFY_TEST_EXPECT_AXES` can, but only on a leg that sets it).
|
|
16
16
|
* So a container that lost its GTK would run zero tests and report success — the
|
|
17
17
|
* green-that-checked-nothing shape, arriving through the very gate meant to widen
|
|
18
18
|
* coverage. Measured once already: gated on `'Gjs'` alone, this suite built for the
|
package/lib/types/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type GObject from '@girs/gobject-2.0';
|
|
2
2
|
import type Gtk from '@girs/gtk-4.0';
|
|
3
|
+
import type { AriaValueType } from '@girs/gtk-4.0/vocabulary';
|
|
3
4
|
export type NodeKind = 'element' | 'text' | 'anchor';
|
|
4
5
|
export interface HostNodeBase {
|
|
5
6
|
readonly kind: NodeKind;
|
|
@@ -50,6 +51,15 @@ export interface HostElement extends HostNodeBase {
|
|
|
50
51
|
listeners: Map<string, (...args: unknown[]) => unknown>;
|
|
51
52
|
/** Positional data for `coords` parents (`Gtk.Grid`), read off the child. */
|
|
52
53
|
layout: Record<string, unknown> | null;
|
|
54
|
+
/**
|
|
55
|
+
* The authored ARIA object, or null — the accessibility GTK holds for this widget.
|
|
56
|
+
*
|
|
57
|
+
* A field of its own and NOT a key in `props`, for the reason `layout` is one: `props`
|
|
58
|
+
* is replayed into `g_object_new` by `materialize`, and none of these names is a
|
|
59
|
+
* construct property. It is the LAST authored value, so a patch can compute which
|
|
60
|
+
* slots the new object no longer sets and reset exactly those.
|
|
61
|
+
*/
|
|
62
|
+
accessibility: Record<string, unknown> | null;
|
|
53
63
|
/** True once text CHILDREN wrote the sink, so removing the last one clears it
|
|
54
64
|
* instead of leaving the stale string an authored prop never set. */
|
|
55
65
|
textFromChildren: boolean;
|
|
@@ -416,6 +426,20 @@ export type ChildPolicy = {
|
|
|
416
426
|
export interface GeneratedWidget {
|
|
417
427
|
readonly gtype: string;
|
|
418
428
|
readonly tag: string;
|
|
429
|
+
/**
|
|
430
|
+
* Availability-CONDITIONAL, and the declared type deliberately does not say so.
|
|
431
|
+
*
|
|
432
|
+
* A row comes from one platform's GIR, so on a platform whose GTK does not
|
|
433
|
+
* build the class this reads `Gtk.PrintUnixDialog` and gets `undefined` —
|
|
434
|
+
* the whole of GTK's Unix print stack is compiled out on win32 (#1446).
|
|
435
|
+
* Widening the signature to `| undefined` would force every `ctor()` reader
|
|
436
|
+
* to handle the absence, and they all handle it through ONE predicate
|
|
437
|
+
* instead (`classOf`/`requireClass`, `registry.ts`); annotating the signature
|
|
438
|
+
* as well would be a second statement of the same fact that nothing checks.
|
|
439
|
+
* The gap this leaves is real and deliberate: a reader that bypasses both
|
|
440
|
+
* gets `undefined` where the type promised a class — which is why every
|
|
441
|
+
* call site refuses rather than dereferences.
|
|
442
|
+
*/
|
|
419
443
|
readonly ctor: () => GObject.ObjectClass & (new (props?: Record<string, unknown>) => GObject.Object);
|
|
420
444
|
}
|
|
421
445
|
export interface WidgetDescriptor {
|
|
@@ -452,3 +476,45 @@ export interface WidgetDescriptor {
|
|
|
452
476
|
*/
|
|
453
477
|
readonly requiresProps?: readonly string[];
|
|
454
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* The three enums whose MEMBERS are GTK's ARIA names.
|
|
481
|
+
*
|
|
482
|
+
* `GtkAccessibleProperty`, `GtkAccessibleState` and `GtkAccessibleRelation` are three
|
|
483
|
+
* tables and three calls — `update_property`, `update_state`, `update_relation` — and
|
|
484
|
+
* which name belongs to which is GTK's answer, never ours. The runtime derives the call
|
|
485
|
+
* from this string, which is why a fourth table is refused at generation time rather
|
|
486
|
+
* than emitted: a call that does not exist is a `TypeError` inside a render.
|
|
487
|
+
*/
|
|
488
|
+
export type AriaTable = 'GtkAccessibleProperty' | 'GtkAccessibleRelation' | 'GtkAccessibleState';
|
|
489
|
+
/**
|
|
490
|
+
* One ARIA slot: the table it lives in, and the kind of value GTK collects for it.
|
|
491
|
+
*
|
|
492
|
+
* WHY THIS EXISTS AT ALL, and why it is not a ParamSpec. An ARIA slot is not a GObject
|
|
493
|
+
* property and never can be: `gtk_accessible_update_property()` takes a `GValue` the
|
|
494
|
+
* CALLER builds, and GTK reads it back with a fixed `g_value_get_*` per slot. There is
|
|
495
|
+
* nothing on the object to interrogate — so the type this table carries is the only
|
|
496
|
+
* thing standing between an authored value and the measured failure below.
|
|
497
|
+
*
|
|
498
|
+
* MEASURED on gjs 1.88.1 / GTK 4.22.5, one process per line. GJS guesses a GValue type
|
|
499
|
+
* from the JS value, and the guess is made on the value's INTEGRALITY:
|
|
500
|
+
*
|
|
501
|
+
* update_property([VALUE_NOW], [3]) g_value_get_double: G_VALUE_HOLDS_DOUBLE failed
|
|
502
|
+
* update_property([LEVEL], [3.5]) g_value_get_int: G_VALUE_HOLDS_INT failed
|
|
503
|
+
* update_property([SORT], ['ascending']) g_value_get_int: G_VALUE_HOLDS_INT failed
|
|
504
|
+
* update_state([CHECKED], [true]) g_value_get_int: G_VALUE_HOLDS_INT failed
|
|
505
|
+
*
|
|
506
|
+
* Every one of those is a CRITICAL at exit 0 with the slot left unset — the silent
|
|
507
|
+
* mis-store this package exists to refuse — and the last is the one a DOM author writes
|
|
508
|
+
* first, because `checked` is a `GtkAccessibleTristate` and not a boolean.
|
|
509
|
+
*/
|
|
510
|
+
export interface AriaSlot {
|
|
511
|
+
/**
|
|
512
|
+
* The table this name lives in. The NAME itself is the key the slot is stored under —
|
|
513
|
+
* kebab, as GTK spells the enum nick (`has-popup`, `row-index`) — and is deliberately
|
|
514
|
+
* not repeated in the row: a second copy of a map key is a second thing to keep in step.
|
|
515
|
+
*/
|
|
516
|
+
readonly table: AriaTable;
|
|
517
|
+
readonly kind: AriaValueType;
|
|
518
|
+
/** `kind: 'enum'` only — the GType whose nicks the value takes. */
|
|
519
|
+
readonly enumGType?: string;
|
|
520
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/gtk-host",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.0",
|
|
4
4
|
"description": "Framework-agnostic GTK4/Adwaita host: the element model UI-framework renderers bind to",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -75,14 +75,15 @@
|
|
|
75
75
|
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
76
76
|
"build:types": "gjsify tsc",
|
|
77
77
|
"build:test": "gjsify run build:test:gjs",
|
|
78
|
-
"build:test:node": "gjsify build src/test.mts --app node --outfile dist/test.node.mjs --define __VUE_OPTIONS_API__=false --define __VUE_PROD_DEVTOOLS__=false --define __VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false --define \"process.env.NODE_ENV='production'\"
|
|
79
|
-
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs --define __VUE_OPTIONS_API__=false --define __VUE_PROD_DEVTOOLS__=false --define __VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false --define \"process.env.NODE_ENV='production'\"
|
|
78
|
+
"build:test:node": "gjsify build src/test.mts --app node --outfile dist/test.node.mjs --define __VUE_OPTIONS_API__=false --define __VUE_PROD_DEVTOOLS__=false --define __VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false --define \"process.env.NODE_ENV='production'\"",
|
|
79
|
+
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs --define __VUE_OPTIONS_API__=false --define __VUE_PROD_DEVTOOLS__=false --define __VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false --define \"process.env.NODE_ENV='production'\"",
|
|
80
80
|
"test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:gjs",
|
|
81
81
|
"test:gjs": "gjsify run test.gjs.mjs",
|
|
82
82
|
"test:gjs-on-node": "gjsify run build:gjsify && gjsify run build:test:node && node dist/test.node.mjs",
|
|
83
83
|
"generate": "gjsify build src/generator/main.mts --app gjs --outfile tmp/generate.gjs.mjs && gjsify run tmp/generate.gjs.mjs -- --out src/generated && gjsify format src/generated",
|
|
84
84
|
"generate:enum-values": "gjs -m ../../../scripts/generate-enum-values.mjs",
|
|
85
|
-
"generate:methods": "gjs -m ../../../scripts/generate-widget-methods.mjs"
|
|
85
|
+
"generate:methods": "gjs -m ../../../scripts/generate-widget-methods.mjs",
|
|
86
|
+
"generate:value-types": "gjs -m ../../../scripts/generate-value-types.mjs"
|
|
86
87
|
},
|
|
87
88
|
"keywords": [
|
|
88
89
|
"gjs",
|
|
@@ -92,16 +93,16 @@
|
|
|
92
93
|
"host"
|
|
93
94
|
],
|
|
94
95
|
"dependencies": {
|
|
95
|
-
"@girs/adw-1": "5.
|
|
96
|
-
"@girs/gdk-4.0": "5.
|
|
97
|
-
"@girs/gio-2.0": "5.
|
|
98
|
-
"@girs/gjs": "5.
|
|
99
|
-
"@girs/glib-2.0": "5.
|
|
100
|
-
"@girs/gobject-2.0": "5.
|
|
101
|
-
"@girs/gtk-4.0": "5.
|
|
102
|
-
"@girs/pango-1.0": "5.
|
|
103
|
-
"@girs/pangocairo-1.0": "5.
|
|
104
|
-
"@gjsify/adwaita-core": "^0.
|
|
96
|
+
"@girs/adw-1": "5.4.0",
|
|
97
|
+
"@girs/gdk-4.0": "5.4.0",
|
|
98
|
+
"@girs/gio-2.0": "5.4.0",
|
|
99
|
+
"@girs/gjs": "5.4.0",
|
|
100
|
+
"@girs/glib-2.0": "5.4.0",
|
|
101
|
+
"@girs/gobject-2.0": "5.4.0",
|
|
102
|
+
"@girs/gtk-4.0": "5.4.0",
|
|
103
|
+
"@girs/pango-1.0": "5.4.0",
|
|
104
|
+
"@girs/pangocairo-1.0": "5.4.0",
|
|
105
|
+
"@gjsify/adwaita-core": "^0.53.0"
|
|
105
106
|
},
|
|
106
107
|
"peerDependencies": {
|
|
107
108
|
"@vue/runtime-core": "^3.5.0",
|
|
@@ -124,10 +125,11 @@
|
|
|
124
125
|
}
|
|
125
126
|
},
|
|
126
127
|
"devDependencies": {
|
|
127
|
-
"@gjsify/cli": "^0.
|
|
128
|
+
"@gjsify/cli": "^0.53.0",
|
|
129
|
+
"@gjsify/utils": "^0.53.0",
|
|
128
130
|
"@vue/runtime-core": "^3.5.0",
|
|
129
131
|
"solid-js": "^1.9.0",
|
|
130
|
-
"@gjsify/unit": "^0.
|
|
132
|
+
"@gjsify/unit": "^0.53.0",
|
|
131
133
|
"@types/node": "^25.9.2",
|
|
132
134
|
"typescript": "^6.0.3",
|
|
133
135
|
"@gjsify/node-gi": "file:../../node-gi/node-gi",
|
|
@@ -136,7 +138,8 @@
|
|
|
136
138
|
"react": "^19.2.0",
|
|
137
139
|
"react-reconciler": "^0.33.0",
|
|
138
140
|
"@types/react": "^19.2.2",
|
|
139
|
-
"@types/react-reconciler": "^0.33.0"
|
|
141
|
+
"@types/react-reconciler": "^0.33.0",
|
|
142
|
+
"@girs/girepository-3.0": "5.4.0"
|
|
140
143
|
},
|
|
141
144
|
"gjsify": {
|
|
142
145
|
"runtimes": {
|