@gjsify/gtk-host 0.51.1 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +154 -1
  2. package/lib/esm/accessibility.js +1 -0
  3. package/lib/esm/conformance/at-context.js +1 -0
  4. package/lib/esm/conformance/index.js +1 -1
  5. package/lib/esm/conformance/shared-tree-builder.js +1 -0
  6. package/lib/esm/errors.js +1 -1
  7. package/lib/esm/generated/accessibility.js +1 -0
  8. package/lib/esm/host.js +1 -1
  9. package/lib/esm/index.js +1 -1
  10. package/lib/esm/menu.js +1 -1
  11. package/lib/esm/policies.js +1 -1
  12. package/lib/esm/props.js +1 -1
  13. package/lib/types/accessibility.d.ts +56 -0
  14. package/lib/types/accessibility.spec.d.ts +2 -0
  15. package/lib/types/attrs.d.ts +15 -2
  16. package/lib/types/conformance/at-context.d.ts +31 -0
  17. package/lib/types/conformance/index.d.ts +2 -0
  18. package/lib/types/conformance/nick-vectors.d.mts +26 -0
  19. package/lib/types/conformance/shared-tree-builder.d.ts +26 -0
  20. package/lib/types/errors.d.ts +61 -1
  21. package/lib/types/font-dir.d.ts +5 -3
  22. package/lib/types/fonts.d.ts +6 -3
  23. package/lib/types/generated/accessibility.d.ts +208 -0
  24. package/lib/types/generated/enum-values.d.mts +1 -1
  25. package/lib/types/generated/props.d.ts +3310 -186
  26. package/lib/types/generated/surface-data.d.mts +10 -0
  27. package/lib/types/generated/value-types.d.mts +28 -0
  28. package/lib/types/generator/emit-types.d.mts +22 -0
  29. package/lib/types/generator/model.d.mts +20 -0
  30. package/lib/types/host.d.ts +26 -0
  31. package/lib/types/index.d.ts +1 -1
  32. package/lib/types/policies.d.ts +58 -1
  33. package/lib/types/props.d.ts +10 -5
  34. package/lib/types/react-jsx-runtime.d.ts +2 -2
  35. package/lib/types/types.d.ts +52 -0
  36. package/package.json +17 -15
package/README.md CHANGED
@@ -52,11 +52,70 @@ gjs 1.88.1:
52
52
  | text inside `<GtkImage>` | nothing | throws, naming the tag and the fix |
53
53
  | a child under a childless widget | `Gtk-WARNING` at exit 0 | throws, naming the three fixes |
54
54
  | `selectable: 'false'` (a string) | JS truthiness makes it TRUE | honours `'true'`/`'false'`, throws on any other string |
55
- | a string for a flags property | dropped silently | throws, naming the flags GType and asking for the numeric value |
55
+ | `input-hints: 'spellcheck|lowercase'` | dropped silently | resolves the nick SET through GTK's own `.ui` parser |
56
+ | `input-hints: 'spellchek'` | same silence | throws `bad-flags`, naming the set and the GType |
57
+ | `input-hints: ''` or `'spellcheck|'` | reads as 0 — every flag cleared, no diagnostic | throws `blank-flags` |
58
+ | `licenseType: '0bsd'` | GTK's parser reads the leading `0` and drops `bsd` — 0 is `unknown`, no diagnostic | resolves the nick off the installed type: 18 |
59
+ | `input-hints: '0nope'` or `'0|spellcheck'` | the same truncation on the flags side — plain 0 | throws `bad-flags` |
56
60
  | `model: 'Blue'` on a `Gio.ListModel` property | a CRITICAL and an EMPTY list | throws `bad-list-model`, naming the tag and the kind it got |
57
61
  | `model: ['a']` on `Gtk.ListView`, whose model is a `Gtk.SelectionModel` | `set_property` turns it into NULL and logs NOTHING — an empty view, and even the diagnostics gate is quiet; constructed with it, GJS throws from inside `materialize` | throws `list-model-mismatch` at the authoring call, naming the type GTK wants |
58
62
  | `adjustment: 5` on a `Gtk.Adjustment` property | guesses a GType, stores nothing | throws `bad-adjustment`: a number would be the `value`, which is its own property |
59
63
 
64
+ ### One nick parser, and it is GTK's
65
+
66
+ An enum nick and a flags nick SET go through the same call:
67
+ `gtk_builder_value_from_string_type`, the parser every enum and flags attribute of a
68
+ `.ui` file already goes through. So what this host accepts is what GTK accepts — a
69
+ nick, the C member name, a numeric string, mixed case, `|`-joined members with or
70
+ without spaces — and there is one vocabulary rather than two.
71
+
72
+ **GObject was asked first and cannot answer.** `GObject.enum_get_value_by_nick` and
73
+ `flags_get_value_by_nick` are both on the GJS namespace and both unreachable from it:
74
+ the only route to a class is `GObject.type_class_ref`, which returns a
75
+ `GObject.TypeClass` that GJS refuses to convert to `GObject.EnumClass`. That is the
76
+ measurement the old refusal ("a nick set is not something GObject exposes to us") was
77
+ written against, and it is still true — it just is not the whole answer.
78
+
79
+ **Two inputs are still refused, and one of them is why the blank check exists.**
80
+ Measured on GTK 4.22.4: `""` and `" "` parse to `[true, 0]`, and a LEADING empty
81
+ member is dropped without a word. Zero is a legal flags value, so a stray separator
82
+ would be a widget with every flag cleared at exit 0 — the exact silent-wrong value
83
+ this host exists to refuse. `blank-flags` covers all of them; `bad-flags` is the member
84
+ that names nothing.
85
+
86
+ **A nick with a leading DIGIT does not reach the parser.** `_gtk_builder_enum_value_from_string`
87
+ and its flags twin try the number first and keep it as soon as one character parses as
88
+ one, discarding the rest in silence. Measured on GTK 4.22.5: `GtkLicense` `"0bsd"` comes
89
+ back `[true, 0]` where the member is 18, and `0` is `GTK_LICENSE_UNKNOWN` — a legal
90
+ value, so there is nothing to detect afterwards. `GskTransformCategory` is worse: all
91
+ four of `3d`, `2d`, `2d-affine`, `2d-translate` resolve to some OTHER valid member. So
92
+ the numeric reading is allowed only where the WHOLE string is a number (`"18"`, `"0x12"`,
93
+ `18` — base 0, as the parser reads it), and a member that merely starts numeric is
94
+ resolved off the installed type's own members. One nick in the shipped surface has that
95
+ shape (1 of 778 enum nicks, 0 of 95 bitfield ones) and none anywhere is made of digits
96
+ alone; a digit-leading member inside a `|` set is refused rather than resolved, because
97
+ no bitfield in any installed vocabulary has one.
98
+
99
+ **The type surface takes both spellings.** A bitfield property is `<GType>NickSet |
100
+ number`, where the set alias pins the FIRST member exactly and leaves the rest to the
101
+ host: checking every member of a set of arbitrary length means enumerating its
102
+ permutations, n! terms for an n-member bitfield and 26 members on the largest one here.
103
+ The member names come from `FLAG_VALUES`' KEYS — `@girs` publishes no nick LIST for a
104
+ bitfield, precisely because GObject resolves no set — joined to the property by
105
+ `PROP_ENUMS`, since nothing in the rendered `number` says which bitfield it is.
106
+
107
+ **The namespace list is no longer on the property path.** `coerce` holds the
108
+ ParamSpec's own `value_type`, so it needs no table at all. What is left of the list
109
+ answers the NAME-keyed question `lookupEnumNick`/`enumMembers` ask, the prefix only
110
+ says where to look, and a candidate is confirmed against the GType it carries itself —
111
+ which is what lets `G`, the prefix Gio, GLib and GObject share, appear more than once.
112
+ It had to: `GPasswordSave` is `Gio.PasswordSave`, the surface offered
113
+ `GPasswordSaveNick`, and the host refused all three of those nicks at the call. The
114
+ check that would have said so excused it as "newer than the installed library", which
115
+ was false about every one of them, so `generated.spec.ts` now holds an unresolvable
116
+ nick against two witnesses outside that list — the installed classes' ParamSpecs and
117
+ the typelib-read values artifact — instead of against a version comparison.
118
+
60
119
  ### Values that cross the seam
61
120
 
62
121
  A GObject with no literal spelling can have a PORTABLE form in `@gjsify/adwaita-core`, and
@@ -82,6 +141,74 @@ widen the same properties by the same rule — `WithPortableValues<T>` in `attrs
82
141
  `<gtk-list-view model={[…]}>` is a compile error for the reason it is a runtime refusal:
83
142
  `Gtk.ListView:model` is a `Gtk.SelectionModel`, which a string list is not.
84
143
 
144
+ ## Accessibility — the axis no ParamSpec carries
145
+
146
+ Everything else a renderer writes is a GObject property, resolved through the ParamSpec of
147
+ the class that is INSTALLED. GTK's ARIA surface is not: `GtkAccessible` installs exactly
148
+ one property, `accessible-role`, and the other 53 names are members of three ENUMS —
149
+ `GtkAccessibleProperty`, `GtkAccessibleState`, `GtkAccessibleRelation` — written through
150
+ `update_property`, `update_state` and `update_relation`. There is nothing on the object to
151
+ interrogate, so **the value types have to ship**: `@girs`' `ARIA_VALUE_TYPES` /
152
+ `ARIA_VALUE_ENUMS` (read from each member's own GIR documentation, because
153
+ `gtk_accessible_property_init_value()` is not introspectable) become
154
+ `src/generated/accessibility.ts`, which is the one generated table the runtime cannot
155
+ re-derive.
156
+
157
+ ```tsx
158
+ <gtk-label label="Total" accessibility={{ label: 'Total for the year', checked: 'mixed', 'row-index': 3 }} />
159
+ ```
160
+
161
+ **One grouped prop, not 53 flat `aria*` ones**, for four measured reasons. TypeScript
162
+ exempts every hyphen-containing JSX attribute from excess-property checking, so a flat
163
+ `aria-labell` would be accepted in silence while a key inside a fresh object literal is
164
+ checked (`type-tests/jsx/negative-props.tsx`). The ARIA names are not the widget's
165
+ properties and COLLIDE with them — `label`, `orientation`, `checked`, `expanded` and
166
+ `selected` are all both, and `orientation` is settable on a `GtkLabel` that implements no
167
+ `GtkOrientable` at all. A `.blp` author already writes `accessibility { label: "…"; }` over
168
+ the same vocabulary (ADR 0034). And `setProp` already has this shape for `layout`, so this
169
+ adds ONE reserved key to the host rather than 53.
170
+
171
+ **Why the table is load-bearing**, measured on gjs 1.88.1 / GTK 4.22.5, one process per
172
+ row. GJS guesses a GValue type from the JS value's INTEGRALITY, and GTK reads it back with
173
+ a fixed `g_value_get_*`:
174
+
175
+ | What you write | What GTK does | What this host does |
176
+ |---|---|---|
177
+ | `{ 'value-now': 3 }` | `g_value_get_double` assertion fails on a `G_TYPE_INT`; **the slot still reads as SET** | boxes a `G_TYPE_DOUBLE` and writes it |
178
+ | `{ level: 3.5 }` | `g_value_get_int` fails; nothing stored | truncates, as an `int` property does |
179
+ | `{ checked: true }` | `checked` is a `GtkAccessibleTristate`: `g_value_get_int` fails, slot reads as SET | takes `'mixed'`/`'true'`/`'false'`, or the constant |
180
+ | `{ sort: 'ascending' }` as a bare string | `g_value_get_int` fails | resolves the nick against `GtkAccessibleSort` |
181
+ | a name GTK has not got | two `Gtk-CRITICAL`s, exit 0 | throws `unknown-aria` / `aria-not-installed` |
182
+ | a name the next render drops | keeps it for the life of the widget | `reset_property` / `_state` / `_relation` |
183
+
184
+ That two of those still report the slot as SET is why the conformance vectors run inside the
185
+ diagnostics gate: `Gtk.test_accessible_has_*` alone passes the defect, and it is the SILENCE
186
+ that separates a correct write from a mis-typed one. `accessibility.spec.ts` keeps the
187
+ witness — the three raw calls, outside the gate, asserting what GTK really does with them.
188
+
189
+ **And the oracle itself has a precondition.** `gtk_accessible_update_*` writes into the
190
+ widget's `GtkATContext`, and `gtk_test_accessible_has_*` reads back out of it — so under
191
+ `GTK_A11Y=none` there is no context, every write records nothing, every read answers false,
192
+ and nothing is logged. Measured on GTK 4.22.5: gjs and node-gi agree in every cell
193
+ (`unset`/`test` set the slots, `none` sets none of them), which is how six vectors red on
194
+ three node-gi CI legs turned out to be an env var rather than a marshalling defect.
195
+ `@gjsify/gtk-host/conformance` exports the two halves: `installAccessibilityBackend()` for a
196
+ test entry point — GTK's in-process `test` backend, no a11y bus, which is what `none` was
197
+ chosen for — and `withAtContext(widget)`, which throws a sentence instead of letting a vector
198
+ read `false` off an absent layer, including the vectors that EXPECT false and would otherwise
199
+ pass vacuously.
200
+
201
+ **Relations that point at another widget are a NAMED GAP.** Fourteen of the 53 slots take a
202
+ reference (`labelled-by`, `described-by`, `controls`, …), and marshalling one is not what is
203
+ missing — `Gtk.AccessibleList.new_from_list([widget])` builds exactly the value GTK wants.
204
+ ADDRESSING is: this host has no `id` prop, and a framework `ref` is resolved AFTER the props
205
+ of the element that names it are applied, so a ref read at that point is `null` on the render
206
+ that authored it. The names are therefore **declared and unwritable** (`?: never`) rather than
207
+ omitted — omitting them would make the excess-property check say GTK has no such name, which
208
+ is false — and the runtime refuses them with `aria-reference`, which names the imperative
209
+ `ref={…}` spelling that does work today. The other ten relation slots carry integers or
210
+ strings (`row-index`, `col-count`, `pos-in-set`) and are expressible now.
211
+
85
212
  ## The node tree
86
213
 
87
214
  Three node kinds — `element`, `text`, `anchor` — linked by the host's own
@@ -711,6 +838,32 @@ host's own `coerce()` path. A member the installed library lacks is accepted onl
711
838
  if the GIR says it arrived in a newer release — `GtkApplicationWindow::save-state`
712
839
  is GTK 4.24 and the check runs on 4.22.4.
713
840
 
841
+ ### A base that leaves the namespace
842
+
843
+ The generator reads `@girs/<ns>/vocabulary` (ADR 0029) for Gtk and Adw — the only two that
844
+ declare widgets — and it also reads the siblings those two say their rows reach into,
845
+ `PROVENANCE.requiredVocabularies`. Those are read for LOOKUP only: they declare no widget,
846
+ contribute no GType prefix, and reach the artefact only for a GType the widget surface already
847
+ REFERENCES, which is what keeps it from growing by the whole of Gio.
848
+
849
+ **The incident is why that pass exists.** `GtkApplication` extends `GApplication` and
850
+ `GtkMountOperation` extends `GMountOperation`, both Gio, both reached only as ancestors. Through
851
+ `@girs` 5.2.0 they arrived free, because `gtk-4.0`'s vocabulary INLINED them — its
852
+ `PROVENANCE.inlinedBases` named `Gio.Application` and `Gio.MountOperation` for exactly that
853
+ reason. ts-for-gir #476 gave every namespace a UI file can name its own vocabulary, so 5.3.0
854
+ stops inlining and the two classes are Gio's to describe. Regenerating across that bump without
855
+ the pass emptied `GApplicationProps` (23 members) and `GMountOperationProps` (27) in a 400 KB
856
+ artefact where nothing else moved, and **an `extends` clause pointing at an interface that
857
+ carries nothing still compiles**. The verbatim check one section up could not see it either: it
858
+ compares the artefact against `gtk-4.0` alone, and the classes had left that package. What holds
859
+ it now is `generator.spec.ts` § "carries a base that left the namespace" — over every chain link
860
+ the artefact names, not over those two — and it goes red when the pass is removed.
861
+
862
+ The nicks come one at a time and by name: a restored prop's rendered type reads
863
+ `GPasswordSaveNick | Gio.PasswordSave`, and that union compiles only where `GPasswordSave`
864
+ reached the table. Merging a sibling's whole nick list instead would add a hundred unions
865
+ nothing in this surface references.
866
+
714
867
  ### Solid / JSX
715
868
 
716
869
  ```jsonc
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{err as e}from"./errors.js";import{ARIA_SLOTS as t}from"./generated/accessibility.js";import{lookupEnumNick as n}from"./props.js";import r from"gi://GObject?version=2.0";import i from"gi://Gtk?version=4.0";const verbOf=e=>e.slice(13).toLowerCase(),kindOf=e=>e===null?`null`:Array.isArray(e)?`an array`:`a ${typeof e}`,value=(e,t)=>{let n=new r.Value;return n.init(e),t(n),n};function ariaValue(t,i,a,o){switch(i.kind){case`string`:if(typeof o==`string`)return value(r.TYPE_STRING,e=>e.set_string(o));if(typeof o==`number`||typeof o==`boolean`)return value(r.TYPE_STRING,e=>e.set_string(String(o)));throw e.badAriaValue(a,t,`string`,kindOf(o));case`boolean`:if(typeof o==`boolean`)return value(r.TYPE_BOOLEAN,e=>e.set_boolean(o));if(o===`true`||o===`false`)return value(r.TYPE_BOOLEAN,e=>e.set_boolean(o===`true`));throw e.badAriaValue(a,t,`boolean`,kindOf(o));case`integer`:if(typeof o!=`number`)throw e.badAriaValue(a,t,`integer`,kindOf(o));return value(r.TYPE_INT,e=>e.set_int(Math.trunc(o)));case`double`:if(typeof o!=`number`)throw e.badAriaValue(a,t,`double`,kindOf(o));return value(r.TYPE_DOUBLE,e=>e.set_double(o));case`enum`:{let s=i.enumGType;if(typeof o==`number`)return value(r.TYPE_INT,e=>e.set_int(o));if(typeof o!=`string`)throw e.badAriaValue(a,t,s,kindOf(o));let c=n(s,o);if(c===void 0)throw e.badAriaEnum(a,t,o,s);return value(r.TYPE_INT,e=>e.set_int(c))}default:throw e.ariaReference(a,t)}}function memberOf(t,r,i){let a=n(r.table,t);if(a===void 0)throw e.ariaNotInstalled(i,t,r.table);return a}function slotOf(n,r){let i=t[r];if(!i)throw e.unknownAria(n,r);return i}const isInput=e=>typeof e==`object`&&!!e&&!Array.isArray(e)&&!(e instanceof r.Object);function planAccessibility(t,n,r){if(r!==null&&!isInput(r))throw e.badAccessibility(t,kindOf(r));let i=[],a=[],o=new Set;for(let[e,n]of Object.entries(r??{})){let r=slotOf(t,e),s=memberOf(e,r,t);o.add(e),n==null?a.push({table:r.table,member:s}):i.push({table:r.table,member:s,value:ariaValue(e,r,t,n)})}for(let e of Object.keys(n??{})){if(o.has(e))continue;let n=slotOf(t,e);n.kind!==`reference`&&a.push({table:n.table,member:memberOf(e,n,t)})}return{writes:i,resets:a}}function applyAccessibilityPlan(e,t){if(t.writes.length===0&&t.resets.length===0)return;let n=e,r=new Map;for(let e of t.writes){let t=r.get(e.table)??{members:[],values:[]};t.members.push(e.member),t.values.push(e.value),r.set(e.table,t)}for(let[e,t]of r)n[`update_${verbOf(e)}`]?.(t.members,t.values);for(let e of t.resets)n[`reset_${verbOf(e.table)}`]?.(e.member)}const isAccessibleClass=e=>r.type_is_a(e.$gtype,i.Accessible.$gtype);export{applyAccessibilityPlan,isAccessibleClass,planAccessibility};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import e from"gi://GLib?version=2.0";function installAccessibilityBackend(){e.setenv(`GTK_A11Y`,`test`,!0)}function withAtContext(e){if(e.get_at_context()===null)throw Error("this widget has no GtkATContext, so gtk_accessible_update_property/_state/_relation record nothing and every Gtk.test_accessible_has_* answers false — silently, at exit 0. These vectors would be measuring an absent accessibility layer rather than this package. GTK_A11Y=none does exactly that; the test entry point calls installAccessibilityBackend() to install GTK’s in-process `test` backend instead, so either something unset it again or an AT context was asked for before it ran.");return e}export{installAccessibilityBackend,withAtContext};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{adderSlots as e,addressOf as t,classPlacementKind as n,isUnparented as r,placementOf as i,unhandledPlacement as a,unhandledPolicy as o}from"../policies.js";import{describeLogRecord as s,installDiagnosticsGate as c,isEnvironmentDiagnostic as l}from"./diagnostics.js";import{descendants as u,dumpTree as d,findDescendant as f,gtkChildTypes as p,gtkChildren as m}from"./tree.js";import{windowChromeCensus as h,windowChromeProblems as g}from"./window-chrome.js";import{BUILTIN_DESCRIPTORS as _}from"../descriptors/index.js";import v from"gi://GObject?version=2.0";function methodsOf(e){switch(e.kind){case`none`:case`uncurated`:return[];case`single`:return[e.set];case`ordered`:return e.after?[e.append,e.after,e.remove]:[e.append,e.remove];case`indexed`:return[e.insert,e.remove];case`slotted`:return e.remove?[...Object.values(e.slots),e.remove]:Object.values(e.slots);case`keyed`:return[e.add,e.remove];case`coords`:return[e.attach,e.remove];default:return o(e)}}function placementMethodsOf(e){switch(e.kind){case`parented`:return[];case`portal`:case`toplevel`:return[e.present,e.close];default:return a(e)}}function presentArityOf(e){switch(e.kind){case`parented`:return null;case`portal`:return 1;case`toplevel`:return 0;default:return a(e)}}function descriptorProblems(e=_){let t=[];for(let r of e){let e;try{e=r.ctor()}catch(e){t.push({gtype:r.gtype,problem:`ctor() threw: ${e.message}`});continue}if(!e)continue;let a=v.type_name(e.$gtype);a!==r.gtype&&t.push({gtype:r.gtype,problem:`ctor() is ${a}, not ${r.gtype}`});for(let n of methodsOf(r.children))typeof e.prototype[n]!=`function`&&t.push({gtype:r.gtype,problem:`declares children.${n}(), which ${a} does not have`});let o=i(r);for(let n of placementMethodsOf(o))typeof e.prototype[n]!=`function`&&t.push({gtype:r.gtype,problem:`declares placement.${n}(), which ${a} does not have`});let s=presentArityOf(o);if(s!==null&&o.kind!==`parented`){let n=e.prototype[o.present];typeof n==`function`&&n.length!==s&&t.push({gtype:r.gtype,problem:`placement.${o.present}() takes ${n.length} argument(s) on ${a}, and a ${o.kind} is presented with exactly ${s}`})}let c=e.prototype.present,l=n(e.$gtype,c);if(l&&o.kind===`parented`&&typeof c==`function`&&t.push({gtype:r.gtype,problem:l===`toplevel`?`implements Gtk.Root and declares no placement, so a parent would take it as an ordinary child — which GTK accepts at exit 0, leaving a root with a parent; it needs placement: { kind: 'toplevel', … }`:`has a present() that takes a parent and declares no placement, so a parent would call its adder on it — which is g_error() and aborts the process; it needs placement: { kind: 'portal', … }`}),r.textSink){let n=e.list_properties().find(e=>e.get_name()===r.textSink);n?(n.flags&v.ParamFlags.WRITABLE)===0?t.push({gtype:r.gtype,problem:`declares a READ-ONLY textSink "${r.textSink}"`}):v.type_is_a(n.value_type,v.TYPE_STRING)||t.push({gtype:r.gtype,problem:`declares textSink "${r.textSink}", which is ${v.type_name(n.value_type)}, not a string`}):t.push({gtype:r.gtype,problem:`declares textSink "${r.textSink}", which ${a} does not have`})}if(r.children.kind===`indexed`&&r.children.perLineCap!==void 0){let n=r.children.perLineCap,i=e.list_properties().find(e=>e.get_name()===n);i?(i.flags&v.ParamFlags.WRITABLE)===0?t.push({gtype:r.gtype,problem:`declares a READ-ONLY perLineCap "${n}"`}):v.type_is_a(i.value_type,v.TYPE_UINT)||t.push({gtype:r.gtype,problem:`declares perLineCap "${n}", which is ${v.type_name(i.value_type)}, not a count`}):t.push({gtype:r.gtype,problem:`declares perLineCap "${n}", which ${a} does not have`})}t.push(...policyProblems(r,e,a))}return t}function policyProblems(t,n,r){let i=[],a=n.prototype,o=t.children,requireGetter=(e,n)=>{let o=e.replace(/^set_/,`get_`);typeof a[o]!=`function`&&i.push({gtype:t.gtype,problem:`${n} uses ${e}() but ${r} has no ${o}(), so removal cannot check whether this child is still the one in place`})};if(o.kind===`single`&&requireGetter(o.set,`children.set`),o.kind===`slotted`){for(let[e,t]of Object.entries(o.slots))t.startsWith(`set_`)&&requireGetter(t,`slot "${e}"`);for(let e of Object.keys(o.wrapSlots??{}))e in o.slots||i.push({gtype:t.gtype,problem:`wrapSlots names "${e}", which is not one of ${Object.keys(o.slots).join(`, `)}`});o.defaultSlot in o.slots||i.push({gtype:t.gtype,problem:`defaultSlot "${o.defaultSlot}" is not one of ${Object.keys(o.slots).join(`, `)}`});let n=e(o);n.length>0&&!o.remove&&i.push({gtype:t.gtype,problem:`slot(s) ${n.map(e=>`"${e}"`).join(`, `)} are adder-backed, so removal needs a "remove" method and this policy names none`})}if(o.kind===`ordered`&&o.reorder===`native`&&!o.after&&i.push({gtype:t.gtype,problem:`claims reorder: 'native' with no "after" method — reorderMode() would tell an adapter the wrong thing`}),o.kind===`keyed`){let e=a[o.add],n=o.titled?3:1;typeof e==`function`&&e.length!==n&&i.push({gtype:t.gtype,problem:`titled: ${o.titled} implies ${o.add}() takes ${n} argument(s), but ${r}'s takes ${e.length}`})}return i}function addressesOf(e){let n=[];for(let i=e.first;i;i=i.next)i.kind===`element`&&i.widget&&!r(i)&&n.push(t(i));return n}export{addressesOf,u as descendants,s as describeLogRecord,descriptorProblems,d as dumpTree,f as findDescendant,p as gtkChildTypes,m as gtkChildren,c as installDiagnosticsGate,l as isEnvironmentDiagnostic,methodsOf,placementMethodsOf,presentArityOf,h as windowChromeCensus,g as windowChromeProblems};
1
+ import"../_virtual/_rolldown/runtime.js";import{adderSlots as e,addressOf as t,classPlacementKind as n,isUnparented as r,placementOf as i,unhandledPlacement as a,unhandledPolicy as o}from"../policies.js";import{installAccessibilityBackend as s,withAtContext as c}from"./at-context.js";import{describeLogRecord as l,installDiagnosticsGate as u,isEnvironmentDiagnostic as d}from"./diagnostics.js";import{descendants as f,dumpTree as p,findDescendant as m,gtkChildTypes as h,gtkChildren as g}from"./tree.js";import{windowChromeCensus as _,windowChromeProblems as v}from"./window-chrome.js";import{buildSharedTree as y}from"./shared-tree-builder.js";import{BUILTIN_DESCRIPTORS as b}from"../descriptors/index.js";import x from"gi://GObject?version=2.0";function methodsOf(e){switch(e.kind){case`none`:case`uncurated`:return[];case`single`:return[e.set];case`ordered`:return e.after?[e.append,e.after,e.remove]:[e.append,e.remove];case`indexed`:return[e.insert,e.remove];case`slotted`:return e.remove?[...Object.values(e.slots),e.remove]:Object.values(e.slots);case`keyed`:return[e.add,e.remove];case`coords`:return[e.attach,e.remove];default:return o(e)}}function placementMethodsOf(e){switch(e.kind){case`parented`:return[];case`portal`:case`toplevel`:return[e.present,e.close];default:return a(e)}}function presentArityOf(e){switch(e.kind){case`parented`:return null;case`portal`:return 1;case`toplevel`:return 0;default:return a(e)}}function descriptorProblems(e=b){let t=[];for(let r of e){let e;try{e=r.ctor()}catch(e){t.push({gtype:r.gtype,problem:`ctor() threw: ${e.message}`});continue}if(!e)continue;let a=x.type_name(e.$gtype);a!==r.gtype&&t.push({gtype:r.gtype,problem:`ctor() is ${a}, not ${r.gtype}`});for(let n of methodsOf(r.children))typeof e.prototype[n]!=`function`&&t.push({gtype:r.gtype,problem:`declares children.${n}(), which ${a} does not have`});let o=i(r);for(let n of placementMethodsOf(o))typeof e.prototype[n]!=`function`&&t.push({gtype:r.gtype,problem:`declares placement.${n}(), which ${a} does not have`});let s=presentArityOf(o);if(s!==null&&o.kind!==`parented`){let n=e.prototype[o.present];typeof n==`function`&&n.length!==s&&t.push({gtype:r.gtype,problem:`placement.${o.present}() takes ${n.length} argument(s) on ${a}, and a ${o.kind} is presented with exactly ${s}`})}let c=e.prototype.present,l=n(e.$gtype,c);if(l&&o.kind===`parented`&&typeof c==`function`&&t.push({gtype:r.gtype,problem:l===`toplevel`?`implements Gtk.Root and declares no placement, so a parent would take it as an ordinary child — which GTK accepts at exit 0, leaving a root with a parent; it needs placement: { kind: 'toplevel', … }`:`has a present() that takes a parent and declares no placement, so a parent would call its adder on it — which is g_error() and aborts the process; it needs placement: { kind: 'portal', … }`}),r.textSink){let n=e.list_properties().find(e=>e.get_name()===r.textSink);n?(n.flags&x.ParamFlags.WRITABLE)===0?t.push({gtype:r.gtype,problem:`declares a READ-ONLY textSink "${r.textSink}"`}):x.type_is_a(n.value_type,x.TYPE_STRING)||t.push({gtype:r.gtype,problem:`declares textSink "${r.textSink}", which is ${x.type_name(n.value_type)}, not a string`}):t.push({gtype:r.gtype,problem:`declares textSink "${r.textSink}", which ${a} does not have`})}if(r.children.kind===`indexed`&&r.children.perLineCap!==void 0){let n=r.children.perLineCap,i=e.list_properties().find(e=>e.get_name()===n);i?(i.flags&x.ParamFlags.WRITABLE)===0?t.push({gtype:r.gtype,problem:`declares a READ-ONLY perLineCap "${n}"`}):x.type_is_a(i.value_type,x.TYPE_UINT)||t.push({gtype:r.gtype,problem:`declares perLineCap "${n}", which is ${x.type_name(i.value_type)}, not a count`}):t.push({gtype:r.gtype,problem:`declares perLineCap "${n}", which ${a} does not have`})}t.push(...policyProblems(r,e,a))}return t}function policyProblems(t,n,r){let i=[],a=n.prototype,o=t.children,requireGetter=(e,n)=>{let o=e.replace(/^set_/,`get_`);typeof a[o]!=`function`&&i.push({gtype:t.gtype,problem:`${n} uses ${e}() but ${r} has no ${o}(), so removal cannot check whether this child is still the one in place`})};if(o.kind===`single`&&requireGetter(o.set,`children.set`),o.kind===`slotted`){for(let[e,t]of Object.entries(o.slots))t.startsWith(`set_`)&&requireGetter(t,`slot "${e}"`);for(let e of Object.keys(o.wrapSlots??{}))e in o.slots||i.push({gtype:t.gtype,problem:`wrapSlots names "${e}", which is not one of ${Object.keys(o.slots).join(`, `)}`});o.defaultSlot in o.slots||i.push({gtype:t.gtype,problem:`defaultSlot "${o.defaultSlot}" is not one of ${Object.keys(o.slots).join(`, `)}`});let n=e(o);n.length>0&&!o.remove&&i.push({gtype:t.gtype,problem:`slot(s) ${n.map(e=>`"${e}"`).join(`, `)} are adder-backed, so removal needs a "remove" method and this policy names none`})}if(o.kind===`ordered`&&o.reorder===`native`&&!o.after&&i.push({gtype:t.gtype,problem:`claims reorder: 'native' with no "after" method — reorderMode() would tell an adapter the wrong thing`}),o.kind===`keyed`){let e=a[o.add],n=o.titled?3:1;typeof e==`function`&&e.length!==n&&i.push({gtype:t.gtype,problem:`titled: ${o.titled} implies ${o.add}() takes ${n} argument(s), but ${r}'s takes ${e.length}`})}return i}function addressesOf(e){let n=[];for(let i=e.first;i;i=i.next)i.kind===`element`&&i.widget&&!r(i)&&n.push(t(i));return n}export{addressesOf,y as buildSharedTree,f as descendants,l as describeLogRecord,descriptorProblems,p as dumpTree,m as findDescendant,h as gtkChildTypes,g as gtkChildren,s as installAccessibilityBackend,u as installDiagnosticsGate,d as isEnvironmentDiagnostic,methodsOf,placementMethodsOf,presentArityOf,_ as windowChromeCensus,v as windowChromeProblems,c as withAtContext};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{createElement as e,insert as t,materialize as n,setProp as r}from"../host.js";function buildSharedTree(i,a=[]){if(i.extensions!==void 0)throw Error(`gtk-host's shared-tree builder has no door for \`${i.tag}\`'s ${Object.keys(i.extensions).join(` and `)} (ADR 0072); load the .blp through Gtk.Builder instead.`);let o=e(i.tag,i.props);a.push(o),n(o),i.slot!==void 0&&r(o,`slot`,i.slot);for(let e of i.children??[])t(buildSharedTree(e,a),o);return o}export{buildSharedTree};
package/lib/esm/errors.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";var GtkHostError=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`GtkHostError`}};const e={unknownTag:e=>new GtkHostError(`unknown-tag`,`No descriptor registered for <${e}>. Register one with registerWidget({ gtype: '${e}', … }). Being a real GType in the installed typelib is not enough on its own.`),missingConstructProp:(e,t)=>new GtkHostError(`missing-construct-prop`,`<${e}> cannot be constructed without ${t}. In the installed library this is not an exception but a g_error(): the process ABORTS (SIGABRT, exit 134, core dump) with no catch and no diagnostic, so the host refuses here while a refusal is still reportable. Author ${t} on the element.`),unknownProp:(e,t)=>new GtkHostError(`unknown-prop`,`<${e}> has no property "${t}". Check the spelling against the installed GTK (camelCase and kebab-case both resolve), or bind it as a signal with on${t[0]?.toUpperCase()}${t.slice(1)}.`),readOnlyProp:(e,t)=>new GtkHostError(`read-only-prop`,`<${e}>.${t} is read-only in the installed GTK. Writing it is a silent no-op in GObject, so this host refuses it instead of dropping the value.`),noAccessor:(e,t,n)=>new GtkHostError(`no-accessor`,`<${e}>.${t} has to be written through its JS accessor — a null or a list cannot be handed to set_property, which guesses a GType and finds none — and GJS installed no "${n}" on this object. Assigning it anyway would create a plain JS property: no GObject write, no error, and notify::${t} never fires.`),badDetailedAction:(e,t,n)=>new GtkHostError(`bad-detailed-action`,`The menu item "${e}" names the action ${JSON.stringify(t)}, which GIO cannot parse: ${n}. In the installed GIO this is not an exception but a g_error() inside g_menu_item_set_detailed_action: the process ABORTS (SIGABRT, exit 134) with no catch and no diagnostic, so the host refuses here while a refusal is still reportable. A detailed action name is "app.act", "app.act::target" or "app.act(variant)".`),badListModel:(e,t,n)=>new GtkHostError(`bad-list-model`,`<${e}>.${t} is a Gio.ListModel and got ${n}. Write the portable list model — an array of strings or of { value, label } descriptors (ADR 0046) — or a real Gio.ListModel. Anything else reaches set_property as a value GObject cannot store: a CRITICAL at exit 0 and an EMPTY list, which a reader cannot tell from "no items yet".`),listModelMismatch:(e,t,n)=>new GtkHostError(`list-model-mismatch`,`<${e}>.${t} is a ${n}, and the portable list model becomes a Gtk.StringList — a Gio.ListModel, not a ${n}. GObject would turn that write into NULL without a diagnostic and leave the widget empty at exit 0. Wrap it yourself (Gtk.NoSelection.new(new Gtk.StringList({ strings }))), or use @gjsify/gtk-host/list for a factory-driven view.`),badAdjustment:(e,t,n)=>new GtkHostError(`bad-adjustment`,`<${e}>.${t} is a Gtk.Adjustment and got ${n}. Write the portable adjustment — an object naming any of value, lower, upper, stepIncrement, pageIncrement, pageSize (ADR 0047) — or a real Gtk.Adjustment. A bare number is refused on purpose: it would be the value, and value is a property of its own on every widget that takes an adjustment, so ${t}={3} and value={3} would be two spellings of one write.`),badEnum:(e,t,n,r)=>new GtkHostError(`bad-enum`,`<${e}>.${t} expects ${r}, and "${n}" is not one of its values. Note that GObject accepts the wrong string SILENTLY — the property would have kept its old value.`),unknownSignal:(e,t,n)=>new GtkHostError(`unknown-signal`,`<${e}> emits no signal "${n}" (bound as ${t}). Check the spelling against the installed GTK, or use the escape hatch on:<raw-signal-name> if the name is irregular.`),signalTaken:(e,t,n,r)=>new GtkHostError(`signal-taken`,`<${e}> already binds "${r}" through ${n}, so ${t} would silently replace it — GObject has one handler per connect, and this host keeps one per signal name. Use one spelling, or combine the two callbacks yourself.`),eventModifier:(e,t)=>new GtkHostError(`event-modifier`,`${e} carries the DOM listener modifier ".${t}", which has no GObject meaning: a signal is emitted on one object and does not propagate through a tree, so there is no capture phase and nothing to be passive about. Drop the modifier (${e.slice(0,e.length-t.length)}); for GTK4's own propagation phases set "propagation-phase" on a Gtk.EventController instead.`),badString:(e,t,n)=>new GtkHostError(`bad-string`,`<${e}>.${t} is a string property and got a ${n}. Numbers and booleans are stringified; anything else has no unambiguous spelling, and GObject would have thrown from inside the next rebuild.`),badBoolean:(e,t,n)=>new GtkHostError(`bad-boolean`,`<${e}>.${t} is a boolean and got the string "${n}". JS truthiness would make "false" mean TRUE — the exact silent-wrong-value this host exists to refuse. Pass a real boolean.`),badFlags:(e,t,n,r)=>new GtkHostError(`bad-flags`,`<${e}>.${t} expects the flags type ${r}, and a string ("${n}") cannot be resolved to one. Pass the numeric value (bitwise-or the members). GObject would have dropped the string silently.`),unresolvableEnum:e=>new GtkHostError(`unresolvable-enum`,`Cannot resolve the enum type ${e} to a GI namespace. Pass the numeric value instead, or extend ENUM_NAMESPACES in props.ts.`),textNotAccepted:(e,t)=>new GtkHostError(`text-not-accepted`,`<${e}> has no text sink, so the text ${JSON.stringify(t.slice(0,32))} has nowhere to go. Wrap it in a widget that takes text (<GtkLabel>), or set the property directly.`),unclaimedChild:(e,t)=>new GtkHostError(`unclaimed-child`,`<${e}> declares children: { kind: 'none' }, so it cannot adopt <${t}>. Fix one of three things: give the parent a child policy, wrap the child in a container, or set the child on a property (e.g. a "child" or "content" property).`),unknownSlot:(e,t,n)=>new GtkHostError(`unknown-slot`,`<${e}> has no slot "${t}". Known slots: ${n.join(`, `)}.`),slotNeedsRemove:(e,t,n)=>new GtkHostError(`slot-needs-remove`,`<${e}> puts children into slot "${t}" with ${n}() and its policy names no "remove" method, so this child cannot be taken out again. A set_-prefixed slot is emptied by writing null back through the setter and needs nothing; an adder-backed one needs children.remove. Add it to the descriptor.`),rejectedChild:(e,t,n)=>new GtkHostError(`rejected-child`,`<${e}> refused <${t}>: ${n}. The container accepts only certain child types (e.g. AdwPreferencesPage takes AdwPreferencesGroup); the descriptor cannot know that, GTK does.`),uncuratedPlacement:(e,t)=>new GtkHostError(`uncurated-placement`,`<${e}> comes from the GENERATED table, which knows the tag but not how the widget adopts a child, so it cannot take <${t}>. Guessing is the one thing that is not available here: \`add\`, \`append\` and \`set_child\` all exist somewhere in GTK and calling the wrong one is a warning at exit 0. Add a curated policy for ${e} in descriptors/, or mount into a container that has one.`),siblingCycle:e=>new GtkHostError(`sibling-cycle`,`The child list of <${e}> does not terminate. A renderer linked a node to itself or into a loop; the host refuses to walk it rather than spin. This is a host or adapter bug, not an application one — please report it with the reordering that produced it.`),notAWidget:e=>new GtkHostError(`not-a-widget`,`<${e}> is not a Gtk.Widget, so it cannot be placed as a child. Non-widget GObjects (controllers, filters, models) attach to a property, not to a parent.`),occupiedSlot:(e,t,n)=>new GtkHostError(`occupied-slot`,`<${e}> already holds a child the application put there, and ${n}() takes only ONE — placing <${t}> would unparent it. GTK does that silently: no throw, no warning, exit 0, and the application's own widget is simply gone. Mount into a container of your own inside <${e}>, or clear the existing child first (${n}(null)) if replacing it is the intent.`),placementMethodMissing:(e,t,n,r)=>new GtkHostError(`placement-method-missing`,`<${e}> declares placement: { kind: '${t}', ${r}: '${n}' } and the installed class has no ${n}(). A node with this placement is placed by calling that method on the node itself — nothing goes into the parent — so without it the node can never reach the screen and never leave it. Fix the descriptor, or drop the placement and give the widget an ordinary child policy.`),unparentableChild:(e,t,n,r)=>new GtkHostError(`unparentable-child`,`<${e}> cannot adopt <${t}>: ${r}. In the installed libraries placing it anyway is not an exception — it is either a g_error() that ABORTS the process (SIGABRT, exit 134, no catch, no diagnostic) or an acceptance at exit 0 that leaves a root inside a child list — so the host refuses here while a refusal is still reportable. Declare placement: { kind: '${n}', … } on the descriptor for <${t}> so the host places it the way the library does, or, if this widget really is an ordinary child, say so with placement: { kind: 'parented' }.`),notAnElement:e=>new GtkHostError(`not-an-element`,`Only an element node owns a widget, and this node is a ${e}. A text node's content lives in its PARENT's text sink and an anchor owns nothing at all — neither has a widget to hand back. Ask the parent element instead.`),destroyedNode:e=>new GtkHostError(`destroyed-node`,`<${e}> was destroyed, so its widget is gone. Asking again would MATERIALISE a fresh, propertyless, unparented widget — \`destroy\` clears props and layout precisely so a destroyed element cannot look re-materialisable — and a caller holding that widget would be looking at nothing on screen.`),notAHostParent:e=>new GtkHostError(`not-a-host-parent`,`insert() needs a host element as the parent and got ${e}. A raw widget cannot be one: the shadow tree lives in the host's own fields, so writing them onto a GObject wrapper renders nothing and reports nothing — Vue's <Teleport to="someWidget"> hands the widget through verbatim and landed exactly here. Wrap it with adopt(widget) first, which is what mountRoot() does.`)};export{GtkHostError,e as err};
1
+ import"./_virtual/_rolldown/runtime.js";var GtkHostError=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`GtkHostError`}};const e={unknownTag:e=>new GtkHostError(`unknown-tag`,`No descriptor registered for <${e}>. Register one with registerWidget({ gtype: '${e}', … }). Being a real GType in the installed typelib is not enough on its own.`),missingConstructProp:(e,t)=>new GtkHostError(`missing-construct-prop`,`<${e}> cannot be constructed without ${t}. In the installed library this is not an exception but a g_error(): the process ABORTS (SIGABRT, exit 134, core dump) with no catch and no diagnostic, so the host refuses here while a refusal is still reportable. Author ${t} on the element.`),unknownProp:(e,t)=>new GtkHostError(`unknown-prop`,`<${e}> has no property "${t}". Check the spelling against the installed GTK (camelCase and kebab-case both resolve), or bind it as a signal with on${t[0]?.toUpperCase()}${t.slice(1)}.`),readOnlyProp:(e,t)=>new GtkHostError(`read-only-prop`,`<${e}>.${t} is read-only in the installed GTK. Writing it is a silent no-op in GObject, so this host refuses it instead of dropping the value.`),noAccessor:(e,t,n)=>new GtkHostError(`no-accessor`,`<${e}>.${t} has to be written through its JS accessor — a null or a list cannot be handed to set_property, which guesses a GType and finds none — and GJS installed no "${n}" on this object. Assigning it anyway would create a plain JS property: no GObject write, no error, and notify::${t} never fires.`),badDetailedAction:(e,t,n)=>new GtkHostError(`bad-detailed-action`,`The menu item "${e}" names the action ${JSON.stringify(t)}, which GIO cannot parse: ${n}. In the installed GIO this is not an exception but a g_error() inside g_menu_item_set_detailed_action: the process ABORTS (SIGABRT, exit 134) with no catch and no diagnostic, so the host refuses here while a refusal is still reportable. A detailed action name is "app.act", "app.act::target" or "app.act(variant)".`),badListModel:(e,t,n)=>new GtkHostError(`bad-list-model`,`<${e}>.${t} is a Gio.ListModel and got ${n}. Write the portable list model — an array of strings or of { value, label } descriptors (ADR 0046) — or a real Gio.ListModel. Anything else reaches set_property as a value GObject cannot store: a CRITICAL at exit 0 and an EMPTY list, which a reader cannot tell from "no items yet".`),listModelMismatch:(e,t,n)=>new GtkHostError(`list-model-mismatch`,`<${e}>.${t} is a ${n}, and the portable list model becomes a Gtk.StringList — a Gio.ListModel, not a ${n}. GObject would turn that write into NULL without a diagnostic and leave the widget empty at exit 0. Wrap it yourself (Gtk.NoSelection.new(new Gtk.StringList({ strings }))), or use @gjsify/gtk-host/list for a factory-driven view.`),badAdjustment:(e,t,n)=>new GtkHostError(`bad-adjustment`,`<${e}>.${t} is a Gtk.Adjustment and got ${n}. Write the portable adjustment — an object naming any of value, lower, upper, stepIncrement, pageIncrement, pageSize (ADR 0047) — or a real Gtk.Adjustment. A bare number is refused on purpose: it would be the value, and value is a property of its own on every widget that takes an adjustment, so ${t}={3} and value={3} would be two spellings of one write.`),badAccessibility:(e,t)=>new GtkHostError(`bad-accessibility`,`<${e}> accessibility takes an object of ARIA names and got ${t}. Write accessibility={{ label: "Save", "row-index": 3 }} — one object, the names GTK's own accessibility block uses — or null to clear everything it set.`),unknownAria:(e,t)=>new GtkHostError(`unknown-aria`,`<${e}> accessibility has no name "${t}". The names are GTK's three ARIA tables — the members of GtkAccessibleProperty, GtkAccessibleState and GtkAccessibleRelation, kebab-spelled (label, has-popup, checked, row-index) — and they are NOT the widget's properties: "orientation" is settable on a GtkLabel that implements no GtkOrientable at all.`),ariaNotInstalled:(e,t,n)=>new GtkHostError(`aria-not-installed`,`<${e}> accessibility names "${t}", which this package's table has and the installed GTK's ${n} does not — it arrived in a newer release. Upgrade GTK, or drop the name: writing it anyway is two criticals and an unset slot at exit 0.`),badAriaValue:(e,t,n,r)=>new GtkHostError(`bad-aria-value`,`<${e}> accessibility "${t}" is typed ${n} in GTK's ARIA table and got ${r}. GTK builds no GValue of its own here — it reads back the one the caller passed with a fixed g_value_get_* — so a wrong type is a critical at exit 0 and nothing readable in the slot; measured, the slot still reports as SET afterwards for two of the three types it was tried on, which is why presence is not an oracle here. GJS guesses the GValue type from a NUMBER's integrality: 3 is an int and 3.5 a double, so a double slot written 3 goes missing and an integer slot written 3.5 does too.`),badAriaEnum:(e,t,n,r)=>new GtkHostError(`bad-aria-enum`,`<${e}> accessibility "${t}" expects ${r}, and "${n}" is not one of its values. The ARIA tables type these slots themselves and disagree with the widget where it matters: checked is a GtkAccessibleTristate, so "true" is a nick and the boolean true is a wrong GValue GTK drops without a word.`),ariaReference:(e,t)=>new GtkHostError(`aria-reference`,`<${e}> accessibility "${t}" points at ANOTHER widget, and this host has no way to name one: there is no id prop, and a framework ref is resolved after these props are applied. Set the relation imperatively for now — ref={(w) => w.update_relation([Gtk.AccessibleRelation.${t.toUpperCase().replace(/-/g,`_`)}], [Gtk.AccessibleList.new_from_list([other])])} — where you already hold both widgets.`),notAccessible:e=>new GtkHostError(`not-accessible`,`<${e}> is not a Gtk.Accessible, so accessibility has nowhere to go on it. Not every row of the generated table is a widget — the list carriers are plain GObjects that HOLD one — and those have no update_property at all (measured on Gtk.StringList). Put the accessibility on the widget that renders.`),badEnum:(e,t,n,r)=>new GtkHostError(`bad-enum`,`<${e}>.${t} expects ${r}, and "${n}" is not one of its values. Note that GObject accepts the wrong string SILENTLY — the property would have kept its old value.`),unknownSignal:(e,t,n)=>new GtkHostError(`unknown-signal`,`<${e}> emits no signal "${n}" (bound as ${t}). Check the spelling against the installed GTK, or use the escape hatch on:<raw-signal-name> if the name is irregular.`),signalTaken:(e,t,n,r)=>new GtkHostError(`signal-taken`,`<${e}> already binds "${r}" through ${n}, so ${t} would silently replace it — GObject has one handler per connect, and this host keeps one per signal name. Use one spelling, or combine the two callbacks yourself.`),eventModifier:(e,t)=>new GtkHostError(`event-modifier`,`${e} carries the DOM listener modifier ".${t}", which has no GObject meaning: a signal is emitted on one object and does not propagate through a tree, so there is no capture phase and nothing to be passive about. Drop the modifier (${e.slice(0,e.length-t.length)}); for GTK4's own propagation phases set "propagation-phase" on a Gtk.EventController instead.`),badString:(e,t,n)=>new GtkHostError(`bad-string`,`<${e}>.${t} is a string property and got a ${n}. Numbers and booleans are stringified; anything else has no unambiguous spelling, and GObject would have thrown from inside the next rebuild.`),badBoolean:(e,t,n)=>new GtkHostError(`bad-boolean`,`<${e}>.${t} is a boolean and got the string "${n}". JS truthiness would make "false" mean TRUE — the exact silent-wrong-value this host exists to refuse. Pass a real boolean.`),badFlags:(e,t,n,r)=>new GtkHostError(`bad-flags`,`<${e}>.${t} is the flags type ${r}, and "${n}" names a member it does not have. Join the member nicks with "|" ("spellcheck|lowercase"), or pass the numeric value. GObject would have dropped the string silently.`),blankFlags:(e,t,n,r)=>new GtkHostError(`blank-flags`,`<${e}>.${t} is the flags type ${r}, and "${n}" has an empty member. GTK reads an empty flags string as 0 — every flag cleared, no diagnostic — so this host refuses it. Drop the stray "|", or write the members you mean.`),textNotAccepted:(e,t)=>new GtkHostError(`text-not-accepted`,`<${e}> has no text sink, so the text ${JSON.stringify(t.slice(0,32))} has nowhere to go. Wrap it in a widget that takes text (<GtkLabel>), or set the property directly.`),unclaimedChild:(e,t)=>new GtkHostError(`unclaimed-child`,`<${e}> declares children: { kind: 'none' }, so it cannot adopt <${t}>. Fix one of three things: give the parent a child policy, wrap the child in a container, or set the child on a property (e.g. a "child" or "content" property).`),unknownSlot:(e,t,n)=>new GtkHostError(`unknown-slot`,`<${e}> has no slot "${t}". Known slots: ${n.length>0?n.join(`, `):`none — it declares no slot names`}.`),slotNeedsRemove:(e,t,n)=>new GtkHostError(`slot-needs-remove`,`<${e}> puts children into slot "${t}" with ${n}() and its policy names no "remove" method, so this child cannot be taken out again. A set_-prefixed slot is emptied by writing null back through the setter and needs nothing; an adder-backed one needs children.remove. Add it to the descriptor.`),rejectedChild:(e,t,n)=>new GtkHostError(`rejected-child`,`<${e}> refused <${t}>: ${n}. The container accepts only certain child types (e.g. AdwPreferencesPage takes AdwPreferencesGroup); the descriptor cannot know that, GTK does.`),uncuratedPlacement:(e,t)=>new GtkHostError(`uncurated-placement`,`<${e}> comes from the GENERATED table, which knows the tag but not how the widget adopts a child, so it cannot take <${t}>. Guessing is the one thing that is not available here: \`add\`, \`append\` and \`set_child\` all exist somewhere in GTK and calling the wrong one is a warning at exit 0. Add a curated policy for ${e} in descriptors/, or mount into a container that has one.`),siblingCycle:e=>new GtkHostError(`sibling-cycle`,`The child list of <${e}> does not terminate. A renderer linked a node to itself or into a loop; the host refuses to walk it rather than spin. This is a host or adapter bug, not an application one — please report it with the reordering that produced it.`),notAWidget:e=>new GtkHostError(`not-a-widget`,`<${e}> is not a Gtk.Widget, so it cannot be placed as a child. Non-widget GObjects (controllers, filters, models) attach to a property, not to a parent.`),occupiedSlot:(e,t,n)=>new GtkHostError(`occupied-slot`,`<${e}> already holds a child the application put there, and ${n}() takes only ONE — placing <${t}> would unparent it. GTK does that silently: no throw, no warning, exit 0, and the application's own widget is simply gone. Mount into a container of your own inside <${e}>, or clear the existing child first (${n}(null)) if replacing it is the intent.`),placementMethodMissing:(e,t,n,r)=>new GtkHostError(`placement-method-missing`,`<${e}> declares placement: { kind: '${t}', ${r}: '${n}' } and the installed class has no ${n}(). A node with this placement is placed by calling that method on the node itself — nothing goes into the parent — so without it the node can never reach the screen and never leave it. Fix the descriptor, or drop the placement and give the widget an ordinary child policy.`),unparentableChild:(e,t,n,r)=>new GtkHostError(`unparentable-child`,`<${e}> cannot adopt <${t}>: ${r}. In the installed libraries placing it anyway is not an exception — it is either a g_error() that ABORTS the process (SIGABRT, exit 134, no catch, no diagnostic) or an acceptance at exit 0 that leaves a root inside a child list — so the host refuses here while a refusal is still reportable. Declare placement: { kind: '${n}', … } on the descriptor for <${t}> so the host places it the way the library does, or, if this widget really is an ordinary child, say so with placement: { kind: 'parented' }.`),notAnElement:e=>new GtkHostError(`not-an-element`,`Only an element node owns a widget, and this node is a ${e}. A text node's content lives in its PARENT's text sink and an anchor owns nothing at all — neither has a widget to hand back. Ask the parent element instead.`),destroyedNode:e=>new GtkHostError(`destroyed-node`,`<${e}> was destroyed, so its widget is gone. Asking again would MATERIALISE a fresh, propertyless, unparented widget — \`destroy\` clears props and layout precisely so a destroyed element cannot look re-materialisable — and a caller holding that widget would be looking at nothing on screen.`),notAHostParent:e=>new GtkHostError(`not-a-host-parent`,`insert() needs a host element as the parent and got ${e}. A raw widget cannot be one: the shadow tree lives in the host's own fields, so writing them onto a GObject wrapper renders nothing and reports nothing — Vue's <Teleport to="someWidget"> hands the widget through verbatim and landed exactly here. Wrap it with adopt(widget) first, which is what mountRoot() does.`)};export{GtkHostError,e as err};
@@ -0,0 +1 @@
1
+ const e={"active-descendant":{table:`GtkAccessibleRelation`,kind:`reference`},autocomplete:{table:`GtkAccessibleProperty`,kind:`enum`,enumGType:`GtkAccessibleAutocomplete`},busy:{table:`GtkAccessibleState`,kind:`boolean`},checked:{table:`GtkAccessibleState`,kind:`enum`,enumGType:`GtkAccessibleTristate`},"col-count":{table:`GtkAccessibleRelation`,kind:`integer`},"col-index":{table:`GtkAccessibleRelation`,kind:`integer`},"col-index-text":{table:`GtkAccessibleRelation`,kind:`string`},"col-span":{table:`GtkAccessibleRelation`,kind:`integer`},"controlled-by":{table:`GtkAccessibleRelation`,kind:`reference`},controls:{table:`GtkAccessibleRelation`,kind:`reference`},"described-by":{table:`GtkAccessibleRelation`,kind:`reference`},description:{table:`GtkAccessibleProperty`,kind:`string`},"description-for":{table:`GtkAccessibleRelation`,kind:`reference`},details:{table:`GtkAccessibleRelation`,kind:`reference`},"details-for":{table:`GtkAccessibleRelation`,kind:`reference`},disabled:{table:`GtkAccessibleState`,kind:`boolean`},"error-message":{table:`GtkAccessibleRelation`,kind:`reference`},"error-message-for":{table:`GtkAccessibleRelation`,kind:`reference`},expanded:{table:`GtkAccessibleState`,kind:`boolean`},"flow-from":{table:`GtkAccessibleRelation`,kind:`reference`},"flow-to":{table:`GtkAccessibleRelation`,kind:`reference`},"has-popup":{table:`GtkAccessibleProperty`,kind:`boolean`},"help-text":{table:`GtkAccessibleProperty`,kind:`string`},hidden:{table:`GtkAccessibleState`,kind:`boolean`},invalid:{table:`GtkAccessibleState`,kind:`enum`,enumGType:`GtkAccessibleInvalidState`},"key-shortcuts":{table:`GtkAccessibleProperty`,kind:`string`},label:{table:`GtkAccessibleProperty`,kind:`string`},"label-for":{table:`GtkAccessibleRelation`,kind:`reference`},"labelled-by":{table:`GtkAccessibleRelation`,kind:`reference`},level:{table:`GtkAccessibleProperty`,kind:`integer`},modal:{table:`GtkAccessibleProperty`,kind:`boolean`},"multi-line":{table:`GtkAccessibleProperty`,kind:`boolean`},"multi-selectable":{table:`GtkAccessibleProperty`,kind:`boolean`},orientation:{table:`GtkAccessibleProperty`,kind:`enum`,enumGType:`GtkOrientation`},owns:{table:`GtkAccessibleRelation`,kind:`reference`},placeholder:{table:`GtkAccessibleProperty`,kind:`string`},"pos-in-set":{table:`GtkAccessibleRelation`,kind:`integer`},pressed:{table:`GtkAccessibleState`,kind:`enum`,enumGType:`GtkAccessibleTristate`},"read-only":{table:`GtkAccessibleProperty`,kind:`boolean`},required:{table:`GtkAccessibleProperty`,kind:`boolean`},"role-description":{table:`GtkAccessibleProperty`,kind:`string`},"row-count":{table:`GtkAccessibleRelation`,kind:`integer`},"row-index":{table:`GtkAccessibleRelation`,kind:`integer`},"row-index-text":{table:`GtkAccessibleRelation`,kind:`string`},"row-span":{table:`GtkAccessibleRelation`,kind:`integer`},selected:{table:`GtkAccessibleState`,kind:`boolean`},"set-size":{table:`GtkAccessibleRelation`,kind:`integer`},sort:{table:`GtkAccessibleProperty`,kind:`enum`,enumGType:`GtkAccessibleSort`},"value-max":{table:`GtkAccessibleProperty`,kind:`double`},"value-min":{table:`GtkAccessibleProperty`,kind:`double`},"value-now":{table:`GtkAccessibleProperty`,kind:`double`},"value-text":{table:`GtkAccessibleProperty`,kind:`string`},visited:{table:`GtkAccessibleState`,kind:`boolean`}};export{e as ARIA_SLOTS};
package/lib/esm/host.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{GtkHostError as e,err as t}from"./errors.js";import{beginHostWrite as n,clearHandlers as r,endHostWrite as i,isEventProp as a,setHandler as o,toSignalName as s}from"./signals.js";import{addressOf as c,closeOutsideParent as l,detachOutsideParent as u,insertChild as d,isUnparented as f,makeDetachedContainer as p,makeWrapper as m,outsideParentOf as h,placeOutsideParent as g,refuseUnparentable as _,removeChild as v,setterSlotOf as y,setterSlots as b,slotOccupant as x}from"./policies.js";import{reconcileStringList as S}from"./list-model.js";import{coerce as C,isConstructOnly as w,paramSpecs as T,removedValue as E,requireSpec as D,toPropertyName as O}from"./props.js";import{lookupWidget as k,nearestRegistered as A}from"./registry.js";import j from"gi://GObject?version=2.0";function createElement(e,t){let n={kind:`element`,descriptor:k(e),widget:null,wrapper:null,slot:null,parent:null,prev:null,next:null,first:null,last:null,handlers:new Map,listeners:new Map,props:{},layout:null,textFromChildren:!1,attached:!1,destroyed:!1,foreign:[],portalWatch:null};if(t)for(let[e,r]of Object.entries(t))setProp(n,e,r);return n}const createText=e=>({kind:`text`,data:e,parent:null,prev:null,next:null}),createAnchor=(e=``)=>({kind:`anchor`,data:e,parent:null,prev:null,next:null}),isText=e=>e.kind===`text`;function releaseWidget(e){let t=e.widget?h(e.descriptor):null;t&&l(e,t),e.widget=null,e.wrapper=null}function materialize(e){if(e.widget)return e.widget;for(let n of e.descriptor.requiresProps??[])if(!(n in e.props))throw t.missingConstructProp(e.descriptor.gtype,n);let a=e.descriptor.ctor(),o=T(a,e.descriptor.gtype),s={};for(let[t,n]of Object.entries(e.props))s[t]=C(D(o,e.descriptor.gtype,t),n,e.descriptor.gtype);n(null);try{e.widget=new a(s)}finally{i()}try{replayInto(e)}catch(t){r(e);for(let t of childSnapshot(e))t.kind===`element`&&t.attached&&(v(e,t),t.attached=!1);throw releaseWidget(e),t}return e.widget}function replayInto(e){for(let[t,n]of e.listeners)o(e,t,n);for(let t of siblingsFrom(e.first,e))t.kind===`element`&&attach(e,t);e.textFromChildren&&flushText(e)}function setProp(e,t,r,o){if(a(t))return setEventHandler(e,t,r);if(t===`slot`)return setSlot(e,r);if(t===`layout`){let t=r,n=e.parent;if(!n||!e.widget){e.layout=t;return}let i=e.layout;replaceAt(e,n,()=>{e.layout=t},()=>{e.layout=i});return}let s=O(t),c=D(T(e.descriptor.ctor(),e.descriptor.gtype),e.descriptor.gtype,s),l=r==null,u=l?E(e.descriptor,c):C(c,r,e.descriptor.gtype);e.widget!==null&&takesAccessorRoute(u)&&!w(c)&&requireAccessor(e,e.widget,s);let d=s in e.props?e.props[s]:void 0;if(l?delete e.props[s]:e.props[s]=r,e.widget){if(w(c))return rebuild(e,s,d);n(e.widget);try{S(e.widget,accessorName(s),u)||writeProperty(e.widget,s,u)}finally{i()}}}function writeProperty(e,t,n){if(!takesAccessorRoute(n)){e.set_property(t,n);return}let r=accessorName(t);e[r]=n}const accessorName=e=>e.replace(/-([a-z0-9])/g,(e,t)=>t.toUpperCase()),takesAccessorRoute=e=>e===null||Array.isArray(e);function requireAccessor(e,n,r){let i=accessorName(r);if(!(i in n))throw t.noAccessor(e.descriptor.gtype,r,i)}function setEventHandler(e,t,n){e.widget?o(e,t,n):n&&assertSignalExists(e,t),n?e.listeners.set(t,n):e.listeners.delete(t)}function assertSignalExists(e,n){let r=s(n,e.descriptor.eventAliases).split(`::`)[0],i=e.descriptor.ctor().$gtype;if(j.signal_lookup(r,i)===0)throw t.unknownSignal(e.descriptor.gtype,n,r)}function setSlot(e,t){if(e.slot===t)return;let n=e.parent;if(!n||!e.widget){e.slot=t;return}let r=e.slot;replaceAt(e,n,()=>{e.slot=t},()=>{e.slot=r})}function replaceAt(e,t,n,r){v(t,e),e.attached=!1,n();try{attach(t,e)}catch(n){r();try{attach(t,e)}catch{}throw n}}function rebuild(e,t,n){let i=e.parent;if(e.widget){r(e);for(let t of childSnapshot(e))t.kind===`element`&&(v(e,t),t.attached=!1);i&&!h(e.descriptor)&&v(i,e)}releaseWidget(e),e.attached=!1;try{materialize(e)}catch(r){t!==void 0&&(n===void 0?delete e.props[t]:e.props[t]=n);try{materialize(e),i&&attach(i,e)}catch{}throw r}i&&attach(i,e)}function setText(e,t){e.data=t,e.kind===`text`&&e.parent&&flushText(e.parent)}function setElementText(e,t){writeTextSink(e,t),e.textFromChildren=!1,destroyChildren(e)}function flushText(e){let t=``,n=!1;for(let r of childNodes(e))r.kind===`text`&&(t+=r.data,n=!0);if(t===``&&!e.textFromChildren)return;let r=e.descriptor.textSink;if(t===``&&r&&holdsElementInSetterSlot(e)){e.textFromChildren=!1,delete e.props[r];return}writeTextSink(e,t),e.textFromChildren=n}function*setterSlotChildren(e){for(let t of siblingsFrom(e.first,e))t.kind===`element`&&t.attached&&!f(t)&&y(e,t)&&(yield t)}const holdsElementInSetterSlot=e=>!setterSlotChildren(e).next().done;function writeTextSink(e,r){let a=e.descriptor.textSink;if(!a)throw t.textNotAccepted(e.descriptor.gtype,r);materialize(e);let o=e.descriptor.children,s=o.kind===`single`?o.set:null;if(s&&!holdsOursInSlot(e,null)&&appOccupant(e.widget,e.descriptor,s))throw t.occupiedSlot(e.descriptor.gtype,`text`,s);let c=D(T(e.descriptor.ctor(),e.descriptor.gtype),e.descriptor.gtype,a);n(e.widget);try{e.widget.set_property(a,C(c,r,e.descriptor.gtype))}finally{i()}e.props[a]=r;for(let t of setterSlotChildren(e))t.attached=!1}function*childNodes(e){yield*siblingsFrom(e.first,e)}function childSnapshot(e){let t=[];for(let n of siblingsFrom(e.first,e))t.push(n);return t}function*siblingsFrom(e,n){let r=0;for(let i=e;i;i=i.next){if(++r>1e5)throw t.siblingCycle(n.descriptor.gtype);yield i}}function link(e,t,n){t.parent=e,n?(t.prev=n.prev,t.next=n,n.prev?n.prev.next=t:e.first=t,n.prev=t):(t.prev=e.last,t.next=null,e.last?e.last.next=t:e.first=t,e.last=t)}function unlink(e){let t=e.parent;t&&(e.prev?e.prev.next=e.next:t.first=e.next,e.next?e.next.prev=e.prev:t.last=e.prev,e.prev=null,e.next=null,e.parent=null)}function attach(e,t){if(!e.widget)return;materialize(t);let n=h(t.descriptor);if(n){t.attached=g(e,t,n);return}_(e,t),ensureWrapper(e,t),refuseOccupiedSlot(e,t);let r=e.foreign.length>0?e.foreign.filter(t=>t.get_parent()===e.widget):e.foreign,i=r.length>0?r[r.length-1]:null,a=r.length;for(let n of siblingsFrom(e.first,e)){if(n===t)break;n.kind!==`element`||!n.attached||f(n)||(i=c(n),a+=1)}let o=[];for(let n of siblingsFrom(t.next,e))n.kind===`element`&&n.attached&&!f(n)&&o.push(n);d({parent:e,child:t,prevWidget:i,index:a,following:o}),t.attached=!0}function refuseOccupiedSlot(e,n){let r=y(e,n);if(r&&!holdsOursInSlot(e,n.slot)&&appOccupant(e.widget,e.descriptor,r))throw t.occupiedSlot(e.descriptor.gtype,n.descriptor.gtype,r)}function holdsOursInSlot(e,t){for(let n of siblingsFrom(e.first,e))if(n.kind===`element`&&n.attached&&n.slot===t&&!f(n))return!0;return!1}function ensureWrapper(n,r){if(r.wrapper)return;let i;try{i=m(n.descriptor.children,r.widget,r.slot)}catch(i){throw i instanceof e?i:t.rejectedChild(n.descriptor.gtype,r.descriptor.gtype,i.message)}i&&(r.wrapper=i)}function insert(e,t,n=null){assertHostParent(t);let r=e.parent,i=e.next,a=n===e?i:n;e.parent&&remove(e),link(t,e,a);try{e.kind===`element`?attach(t,e):e.kind===`text`&&flushText(t)}catch(t){throw unlink(e),r&&restore(e,r,i),t}}function assertHostParent(e){if(!isHostElement(e))throw t.notAHostParent(describeValue(e))}function isHostElement(e){let t=e;return!!t&&t.kind===`element`&&typeof t.descriptor==`object`}function describeValue(e){if(e==null)return String(e);if(typeof e!=`object`)return`a ${typeof e}`;let t=e.tagName;if(typeof t==`string`)return`a DOM element <${t.toLowerCase()}>`;let n=e.constructor?.$gtype,r=n?j.type_name(n)??`an unnamed GType`:null;if(r!==null&&r!==`JSObject`)return r;let i=e.constructor?.name;return i&&i!==`Object`?`a ${i}`:`a plain object`}function restore(e,t,n){try{link(t,e,n),e.kind===`element`?attach(t,e):e.kind===`text`&&flushText(t)}catch{unlink(e)}}function restoreTextSink(e){let t=e.descriptor.textSink;if(!t||e.destroyed||!e.widget)return;let r=e.descriptor.children;if(r.kind!==`single`||holdsOursInSlot(e,null)||x(e.widget,r.set))return;let a=t.replace(/-([a-z])/g,(e,t)=>t.toUpperCase()),o=e.props[t]??e.props[a];if(typeof o!=`string`||o===``)return;let s=D(T(e.descriptor.ctor(),e.descriptor.gtype),e.descriptor.gtype,t);n(e.widget);try{e.widget.set_property(t,C(s,o,e.descriptor.gtype))}finally{i()}}function remove(e){let t=e.parent;if(!t&&e.kind===`element`){let t=h(e.descriptor);t&&(u(e,t),e.attached=!1)}t&&e.kind===`element`&&(v(t,e),e.attached=!1,e.wrapper&&=(e.wrapper.set_child(null),null),restoreTextSink(t)),unlink(e),t&&e.kind===`text`&&flushText(t)}function destroyChildren(e){for(let t of childSnapshot(e))destroy(t)}function disconnectHandlers(e){r(e),e.listeners.clear()}function destroy(e){e.kind===`element`&&(destroyChildren(e),r(e),e.listeners.clear());let t=e.kind===`element`?h(e.descriptor):null;if(t&&releaseWidget(e),remove(e),e.kind===`element`){let n=e.widget;!t&&n&&typeof n.destroy==`function`&&typeof n.get_parent==`function`&&n.get_parent()===null&&n.destroy(),releaseWidget(e),e.props={},e.layout=null,e.textFromChildren=!1,e.destroyed=!0}}function mountRoot(e,t){materialize(e),insert(e,adopt(t))}function widgetOf(e){if(e.kind!==`element`)throw t.notAnElement(e.kind);if(e.destroyed)throw t.destroyedNode(e.descriptor.gtype);return materialize(e)}const createDetachedContainer=()=>adopt(p());function adopt(e){let n=e.constructor.$gtype,r=A(n);if(!r)throw t.unknownTag(gtypeNameOf(e));return{kind:`element`,descriptor:r,widget:e,wrapper:null,slot:null,parent:null,prev:null,next:null,first:null,last:null,handlers:new Map,listeners:new Map,props:{},layout:null,textFromChildren:!1,attached:!0,destroyed:!1,foreign:adoptedChildren(e,r),portalWatch:null}}function adoptedChildren(e,t){let n=b(t.children);if(n.length===0)return directChildren(e);let r=[];for(let i of n){let n=appOccupant(e,t,i);n&&r.push(n)}return r}function appOccupant(e,t,n){let r=x(e,n);if(!r)return null;let i=t.textSink;if(!i)return r;let a=e[i.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())];return typeof a==`string`&&a!==``?null:r}function directChildren(e){let t=[],n=e;if(typeof n.get_first_child!=`function`)return t;for(let e=n.get_first_child();e;e=e.get_next_sibling())t.push(e);return t}const gtypeNameOf=e=>j.type_name(e.constructor.$gtype),parentNode=e=>e.parent,firstChild=e=>e.first,nextSibling=e=>e.next,prevSibling=e=>e.prev;export{adopt,createAnchor,createDetachedContainer,createElement,createText,describeValue,destroy,destroyChildren,disconnectHandlers,firstChild,insert,isHostElement,isText,materialize,mountRoot,nextSibling,parentNode,prevSibling,remove,setElementText,setEventHandler,setProp,setSlot,setText,widgetOf};
1
+ import"./_virtual/_rolldown/runtime.js";import{GtkHostError as e,err as t}from"./errors.js";import{reconcileStringList as n}from"./list-model.js";import{coerce as r,isConstructOnly as i,paramSpecs as a,removedValue as o,requireSpec as s,toPropertyName as c}from"./props.js";import{applyAccessibilityPlan as l,isAccessibleClass as u,planAccessibility as d}from"./accessibility.js";import{beginHostWrite as f,clearHandlers as p,endHostWrite as m,isEventProp as h,setHandler as g,toSignalName as _}from"./signals.js";import{addressOf as v,closeOutsideParent as y,detachOutsideParent as b,insertChild as x,isUnparented as S,makeDetachedContainer as C,makeWrapper as w,outsideParentOf as T,placeOutsideParent as E,refuseUnknownSlot as D,refuseUnparentable as O,removeChild as k,setterSlotOf as A,setterSlots as j,slotOccupant as M}from"./policies.js";import{lookupWidget as N,nearestRegistered as P}from"./registry.js";import F from"gi://GObject?version=2.0";function createElement(e,t){let n={kind:`element`,descriptor:N(e),widget:null,wrapper:null,slot:null,parent:null,prev:null,next:null,first:null,last:null,handlers:new Map,listeners:new Map,props:{},layout:null,accessibility:null,textFromChildren:!1,attached:!1,destroyed:!1,foreign:[],portalWatch:null};if(t)for(let[e,r]of Object.entries(t))setProp(n,e,r);return n}const createText=e=>({kind:`text`,data:e,parent:null,prev:null,next:null}),createAnchor=(e=``)=>({kind:`anchor`,data:e,parent:null,prev:null,next:null}),isText=e=>e.kind===`text`;function releaseWidget(e){let t=e.widget?T(e.descriptor):null;t&&y(e,t),e.widget=null,e.wrapper=null}function materialize(e){if(e.widget)return e.widget;for(let n of e.descriptor.requiresProps??[])if(!(n in e.props))throw t.missingConstructProp(e.descriptor.gtype,n);let n=e.descriptor.ctor(),i=a(n,e.descriptor.gtype),o={};for(let[t,n]of Object.entries(e.props))o[t]=r(s(i,e.descriptor.gtype,t),n,e.descriptor.gtype);f(null);try{e.widget=new n(o)}finally{m()}try{replayInto(e)}catch(t){p(e);for(let t of childSnapshot(e))t.kind===`element`&&t.attached&&(k(e,t),t.attached=!1);throw releaseWidget(e),t}return e.widget}function replayInto(e){for(let[t,n]of e.listeners)g(e,t,n);e.accessibility&&l(e.widget,d(e.descriptor.gtype,null,e.accessibility));for(let t of siblingsFrom(e.first,e))t.kind===`element`&&attach(e,t);e.textFromChildren&&flushText(e)}function setProp(e,t,l,u){if(h(t))return setEventHandler(e,t,l);if(t===`slot`)return setSlot(e,l);if(t===`accessibility`)return setAccessibility(e,l);if(t===`layout`){let t=l,n=e.parent;if(!n||!e.widget){e.layout=t;return}let r=e.layout;replaceAt(e,n,()=>{e.layout=t},()=>{e.layout=r});return}let d=c(t),p=s(a(e.descriptor.ctor(),e.descriptor.gtype),e.descriptor.gtype,d),g=l==null,_=g?o(e.descriptor,p):r(p,l,e.descriptor.gtype);e.widget!==null&&takesAccessorRoute(_)&&!i(p)&&requireAccessor(e,e.widget,d);let v=d in e.props?e.props[d]:void 0;if(g?delete e.props[d]:e.props[d]=l,e.widget){if(i(p))return rebuild(e,d,v);f(e.widget);try{n(e.widget,accessorName(d),_)||writeProperty(e.widget,d,_)}finally{m()}}}function writeProperty(e,t,n){if(!takesAccessorRoute(n)){e.set_property(t,n);return}let r=accessorName(t);e[r]=n}const accessorName=e=>e.replace(/-([a-z0-9])/g,(e,t)=>t.toUpperCase()),takesAccessorRoute=e=>e===null||Array.isArray(e);function requireAccessor(e,n,r){let i=accessorName(r);if(!(i in n))throw t.noAccessor(e.descriptor.gtype,r,i)}function setEventHandler(e,t,n){e.widget?g(e,t,n):n&&assertSignalExists(e,t),n?e.listeners.set(t,n):e.listeners.delete(t)}function assertSignalExists(e,n){let r=_(n,e.descriptor.eventAliases).split(`::`)[0],i=e.descriptor.ctor().$gtype;if(F.signal_lookup(r,i)===0)throw t.unknownSignal(e.descriptor.gtype,n,r)}function setAccessibility(e,n){let r=n??null,i=d(e.descriptor.gtype,e.accessibility,r);if(r!==null&&!u(e.descriptor.ctor()))throw t.notAccessible(e.descriptor.gtype);e.widget&&l(e.widget,i),e.accessibility=r}function setSlot(e,t){if(e.slot===t)return;let n=e.parent;if(!n||!e.widget){e.slot=t;return}let r=e.slot;replaceAt(e,n,()=>{e.slot=t},()=>{e.slot=r})}function replaceAt(e,t,n,r){k(t,e),e.attached=!1,n();try{attach(t,e)}catch(n){r();try{attach(t,e)}catch{}throw n}}function rebuild(e,t,n){let r=e.parent;if(e.widget){p(e);for(let t of childSnapshot(e))t.kind===`element`&&(k(e,t),t.attached=!1);r&&!T(e.descriptor)&&k(r,e)}releaseWidget(e),e.attached=!1;try{materialize(e)}catch(i){t!==void 0&&(n===void 0?delete e.props[t]:e.props[t]=n);try{materialize(e),r&&attach(r,e)}catch{}throw i}r&&attach(r,e)}function setText(e,t){e.data=t,e.kind===`text`&&e.parent&&flushText(e.parent)}function setElementText(e,t){writeTextSink(e,t),e.textFromChildren=!1,destroyChildren(e)}function flushText(e){let t=``,n=!1;for(let r of childNodes(e))r.kind===`text`&&(t+=r.data,n=!0);if(t===``&&!e.textFromChildren)return;let r=e.descriptor.textSink;if(t===``&&r&&holdsElementInSetterSlot(e)){e.textFromChildren=!1,delete e.props[r];return}writeTextSink(e,t),e.textFromChildren=n}function*setterSlotChildren(e){for(let t of siblingsFrom(e.first,e))t.kind===`element`&&t.attached&&!S(t)&&A(e,t)&&(yield t)}const holdsElementInSetterSlot=e=>!setterSlotChildren(e).next().done;function writeTextSink(e,n){let i=e.descriptor.textSink;if(!i)throw t.textNotAccepted(e.descriptor.gtype,n);materialize(e);let o=e.descriptor.children,c=o.kind===`single`?o.set:null;if(c&&!holdsOursInSlot(e,null)&&appOccupant(e.widget,e.descriptor,c))throw t.occupiedSlot(e.descriptor.gtype,`text`,c);let l=s(a(e.descriptor.ctor(),e.descriptor.gtype),e.descriptor.gtype,i);f(e.widget);try{e.widget.set_property(i,r(l,n,e.descriptor.gtype))}finally{m()}e.props[i]=n;for(let t of setterSlotChildren(e))t.attached=!1}function*childNodes(e){yield*siblingsFrom(e.first,e)}function childSnapshot(e){let t=[];for(let n of siblingsFrom(e.first,e))t.push(n);return t}function*siblingsFrom(e,n){let r=0;for(let i=e;i;i=i.next){if(++r>1e5)throw t.siblingCycle(n.descriptor.gtype);yield i}}function link(e,t,n){t.parent=e,n?(t.prev=n.prev,t.next=n,n.prev?n.prev.next=t:e.first=t,n.prev=t):(t.prev=e.last,t.next=null,e.last?e.last.next=t:e.first=t,e.last=t)}function unlink(e){let t=e.parent;t&&(e.prev?e.prev.next=e.next:t.first=e.next,e.next?e.next.prev=e.prev:t.last=e.prev,e.prev=null,e.next=null,e.parent=null)}function attach(e,t){if(!e.widget)return;materialize(t);let n=T(t.descriptor);if(n){t.attached=E(e,t,n);return}O(e,t),D(e,t),ensureWrapper(e,t),refuseOccupiedSlot(e,t);let r=e.foreign.length>0?e.foreign.filter(t=>t.get_parent()===e.widget):e.foreign,i=r.length>0?r[r.length-1]:null,a=r.length;for(let n of siblingsFrom(e.first,e)){if(n===t)break;n.kind!==`element`||!n.attached||S(n)||(i=v(n),a+=1)}let o=[];for(let n of siblingsFrom(t.next,e))n.kind===`element`&&n.attached&&!S(n)&&o.push(n);x({parent:e,child:t,prevWidget:i,index:a,following:o}),t.attached=!0}function refuseOccupiedSlot(e,n){let r=A(e,n);if(r&&!holdsOursInSlot(e,n.slot)&&appOccupant(e.widget,e.descriptor,r))throw t.occupiedSlot(e.descriptor.gtype,n.descriptor.gtype,r)}function holdsOursInSlot(e,t){for(let n of siblingsFrom(e.first,e))if(n.kind===`element`&&n.attached&&n.slot===t&&!S(n))return!0;return!1}function ensureWrapper(n,r){if(r.wrapper)return;let i;try{i=w(n.descriptor,r.widget,r.slot)}catch(i){throw i instanceof e?i:t.rejectedChild(n.descriptor.gtype,r.descriptor.gtype,i.message)}i&&(r.wrapper=i)}function insert(e,t,n=null){assertHostParent(t);let r=e.parent,i=e.next,a=n===e?i:n;e.parent&&remove(e),link(t,e,a);try{e.kind===`element`?attach(t,e):e.kind===`text`&&flushText(t)}catch(t){throw unlink(e),r&&restore(e,r,i),t}}function assertHostParent(e){if(!isHostElement(e))throw t.notAHostParent(describeValue(e))}function isHostElement(e){let t=e;return!!t&&t.kind===`element`&&typeof t.descriptor==`object`}function describeValue(e){if(e==null)return String(e);if(typeof e!=`object`)return`a ${typeof e}`;let t=e.tagName;if(typeof t==`string`)return`a DOM element <${t.toLowerCase()}>`;let n=e.constructor?.$gtype,r=n?F.type_name(n)??`an unnamed GType`:null;if(r!==null&&r!==`JSObject`)return r;let i=e.constructor?.name;return i&&i!==`Object`?`a ${i}`:`a plain object`}function restore(e,t,n){try{link(t,e,n),e.kind===`element`?attach(t,e):e.kind===`text`&&flushText(t)}catch{unlink(e)}}function restoreTextSink(e){let t=e.descriptor.textSink;if(!t||e.destroyed||!e.widget)return;let n=e.descriptor.children;if(n.kind!==`single`||holdsOursInSlot(e,null)||M(e.widget,n.set))return;let i=t.replace(/-([a-z])/g,(e,t)=>t.toUpperCase()),o=e.props[t]??e.props[i];if(typeof o!=`string`||o===``)return;let c=s(a(e.descriptor.ctor(),e.descriptor.gtype),e.descriptor.gtype,t);f(e.widget);try{e.widget.set_property(t,r(c,o,e.descriptor.gtype))}finally{m()}}function remove(e){let t=e.parent;if(!t&&e.kind===`element`){let t=T(e.descriptor);t&&(b(e,t),e.attached=!1)}t&&e.kind===`element`&&(k(t,e),e.attached=!1,e.wrapper&&=(e.wrapper.set_child(null),null),restoreTextSink(t)),unlink(e),t&&e.kind===`text`&&flushText(t)}function destroyChildren(e){for(let t of childSnapshot(e))destroy(t)}function disconnectHandlers(e){p(e),e.listeners.clear()}function destroy(e){e.kind===`element`&&(destroyChildren(e),p(e),e.listeners.clear());let t=e.kind===`element`?T(e.descriptor):null;if(t&&releaseWidget(e),remove(e),e.kind===`element`){let n=e.widget;!t&&n&&typeof n.destroy==`function`&&typeof n.get_parent==`function`&&n.get_parent()===null&&n.destroy(),releaseWidget(e),e.props={},e.layout=null,e.accessibility=null,e.textFromChildren=!1,e.destroyed=!0}}function mountRoot(e,t){materialize(e),insert(e,adopt(t))}function widgetOf(e){if(e.kind!==`element`)throw t.notAnElement(e.kind);if(e.destroyed)throw t.destroyedNode(e.descriptor.gtype);return materialize(e)}const createDetachedContainer=()=>adopt(C());function adopt(e){let n=e.constructor.$gtype,r=P(n);if(!r)throw t.unknownTag(gtypeNameOf(e));return{kind:`element`,descriptor:r,widget:e,wrapper:null,slot:null,parent:null,prev:null,next:null,first:null,last:null,handlers:new Map,listeners:new Map,props:{},layout:null,accessibility:null,textFromChildren:!1,attached:!0,destroyed:!1,foreign:adoptedChildren(e,r),portalWatch:null}}function adoptedChildren(e,t){let n=j(t.children);if(n.length===0)return directChildren(e);let r=[];for(let i of n){let n=appOccupant(e,t,i);n&&r.push(n)}return r}function appOccupant(e,t,n){let r=M(e,n);if(!r)return null;let i=t.textSink;if(!i)return r;let a=e[i.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())];return typeof a==`string`&&a!==``?null:r}function directChildren(e){let t=[],n=e;if(typeof n.get_first_child!=`function`)return t;for(let e=n.get_first_child();e;e=e.get_next_sibling())t.push(e);return t}const gtypeNameOf=e=>F.type_name(e.constructor.$gtype),parentNode=e=>e.parent,firstChild=e=>e.first,nextSibling=e=>e.next,prevSibling=e=>e.prev;export{adopt,createAnchor,createDetachedContainer,createElement,createText,describeValue,destroy,destroyChildren,disconnectHandlers,firstChild,insert,isHostElement,isText,materialize,mountRoot,nextSibling,parentNode,prevSibling,remove,setAccessibility,setElementText,setEventHandler,setProp,setSlot,setText,widgetOf};
package/lib/esm/index.js CHANGED
@@ -1 +1 @@
1
- import{GtkHostError as e}from"./errors.js";import{isEventProp as t,toSignalName as n}from"./signals.js";import{addressOf as r,isPortal as i,placementOf as a,portalOf as o,reorderMode as s}from"./policies.js";import{constructOnlyNames as c,isConstructOnly as l,isWritable as u,lookupEnumNick as d,paramSpecs as f,toPropertyName as p}from"./props.js";import{assertInjective as m,tagOf as h}from"./tags.js";import{clearRegistry as g,hasWidget as _,lookupWidget as v,nearestRegistered as y,registerWidget as b,registerWidgets as x,registeredTags as S}from"./registry.js";import{adopt as C,createAnchor as w,createDetachedContainer as T,createElement as E,createText as D,destroy as O,destroyChildren as k,disconnectHandlers as A,firstChild as j,insert as M,isHostElement as N,isText as P,materialize as F,mountRoot as I,nextSibling as L,parentNode as R,prevSibling as z,remove as B,setElementText as V,setEventHandler as H,setProp as U,setSlot as W,setText as G,widgetOf as K}from"./host.js";import{GENERATED_PROVENANCE as q,GENERATED_WIDGETS as J}from"./generated/widgets.js";import{GTK_DESCRIPTORS as Y}from"./descriptors/gtk.js";import{ADW_DESCRIPTORS as X}from"./descriptors/adw.js";import{BUILTIN_DESCRIPTORS as Z,CURATED_DESCRIPTORS as Q,mergeGenerated as $,registerBuiltinWidgets as ee,tableProvenance as te}from"./descriptors/index.js";import"./types.js";import{blankReason as ne,checkRendered as re,probeEnabled as ie,runHostProbe as ae,runHostProbeApp as oe,shotEvidence as se}from"./probe.js";export{X as ADW_DESCRIPTORS,Z as BUILTIN_DESCRIPTORS,Q as CURATED_DESCRIPTORS,q as GENERATED_PROVENANCE,J as GENERATED_WIDGETS,Y as GTK_DESCRIPTORS,e as GtkHostError,r as addressOf,C as adopt,m as assertInjective,ne as blankReason,re as checkRendered,g as clearRegistry,c as constructOnlyNames,w as createAnchor,T as createDetachedContainer,E as createElement,D as createText,O as destroy,k as destroyChildren,A as disconnectHandlers,j as firstChild,_ as hasWidget,M as insert,l as isConstructOnly,t as isEventProp,N as isHostElement,i as isPortal,P as isText,u as isWritable,d as lookupEnumNick,v as lookupWidget,F as materialize,$ as mergeGenerated,I as mountRoot,y as nearestRegistered,L as nextSibling,f as paramSpecs,R as parentNode,a as placementOf,o as portalOf,z as prevSibling,ie as probeEnabled,ee as registerBuiltinWidgets,b as registerWidget,x as registerWidgets,S as registeredTags,B as remove,s as reorderMode,ae as runHostProbe,oe as runHostProbeApp,V as setElementText,H as setEventHandler,U as setProp,W as setSlot,G as setText,se as shotEvidence,te as tableProvenance,h as tagOf,p as toPropertyName,n as toSignalName,K as widgetOf};
1
+ import{GtkHostError as e}from"./errors.js";import{constructOnlyNames as t,isConstructOnly as n,isWritable as r,lookupEnumNick as i,paramSpecs as a,toPropertyName as o}from"./props.js";import{isEventProp as s,toSignalName as c}from"./signals.js";import{addressOf as l,isPortal as u,placementOf as d,portalOf as f,reorderMode as p}from"./policies.js";import{assertInjective as m,tagOf as h}from"./tags.js";import{clearRegistry as g,hasWidget as _,lookupWidget as v,nearestRegistered as y,registerWidget as b,registerWidgets as x,registeredTags as S}from"./registry.js";import{adopt as C,createAnchor as w,createDetachedContainer as T,createElement as E,createText as D,destroy as O,destroyChildren as k,disconnectHandlers as A,firstChild as j,insert as M,isHostElement as N,isText as P,materialize as F,mountRoot as I,nextSibling as L,parentNode as R,prevSibling as z,remove as B,setElementText as V,setEventHandler as H,setProp as U,setSlot as W,setText as G,widgetOf as K}from"./host.js";import{GENERATED_PROVENANCE as q,GENERATED_WIDGETS as J}from"./generated/widgets.js";import{GTK_DESCRIPTORS as Y}from"./descriptors/gtk.js";import{ADW_DESCRIPTORS as X}from"./descriptors/adw.js";import{BUILTIN_DESCRIPTORS as Z,CURATED_DESCRIPTORS as Q,mergeGenerated as $,registerBuiltinWidgets as ee,tableProvenance as te}from"./descriptors/index.js";import"./types.js";import{blankReason as ne,checkRendered as re,probeEnabled as ie,runHostProbe as ae,runHostProbeApp as oe,shotEvidence as se}from"./probe.js";export{X as ADW_DESCRIPTORS,Z as BUILTIN_DESCRIPTORS,Q as CURATED_DESCRIPTORS,q as GENERATED_PROVENANCE,J as GENERATED_WIDGETS,Y as GTK_DESCRIPTORS,e as GtkHostError,l as addressOf,C as adopt,m as assertInjective,ne as blankReason,re as checkRendered,g as clearRegistry,t as constructOnlyNames,w as createAnchor,T as createDetachedContainer,E as createElement,D as createText,O as destroy,k as destroyChildren,A as disconnectHandlers,j as firstChild,_ as hasWidget,M as insert,n as isConstructOnly,s as isEventProp,N as isHostElement,u as isPortal,P as isText,r as isWritable,i as lookupEnumNick,v as lookupWidget,F as materialize,$ as mergeGenerated,I as mountRoot,y as nearestRegistered,L as nextSibling,a as paramSpecs,R as parentNode,d as placementOf,f as portalOf,z as prevSibling,ie as probeEnabled,ee as registerBuiltinWidgets,b as registerWidget,x as registerWidgets,S as registeredTags,B as remove,p as reorderMode,ae as runHostProbe,oe as runHostProbeApp,V as setElementText,H as setEventHandler,U as setProp,W as setSlot,G as setText,se as shotEvidence,te as tableProvenance,h as tagOf,o as toPropertyName,c as toSignalName,K as widgetOf};
package/lib/esm/menu.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{err as e}from"./errors.js";import{normalizeMenuModel as t}from"@gjsify/adwaita-core";import n from"gi://Gio?version=2.0";import r from"gi://GLib?version=2.0";const i={label:`label`,action:`action`,icon:`icon`,verbIcon:`verb-icon`,accel:`accel`,hiddenWhen:`hidden-when`,custom:`custom`,id:`id`};function requireDetailedAction(t,r){try{n.Action.parse_detailed_name(t)}catch(n){throw e.badDetailedAction(r,t,n instanceof Error?n.message:String(n))}}function itemOf(e){let t=new n.MenuItem;if(e.kind===`item`){e.action!==void 0&&(requireDetailedAction(e.action,e.label),t.set_detailed_action(e.action));for(let[n,a]of Object.entries(i)){let i=e[n];n===`action`||typeof i!=`string`||t.set_attribute_value(a,r.Variant.new_string(i))}return e.useMarkup===!0&&t.set_attribute_value(`use-markup`,r.Variant.new_string(`true`)),t}let a=buildGioMenu(e.items);return e.kind===`section`?(t.set_section(a),e.label!==void 0&&t.set_label(e.label),e.displayHint!==void 0&&t.set_attribute_value(`display-hint`,r.Variant.new_string(e.displayHint)),e.textDirection!==void 0&&t.set_attribute_value(`text-direction`,r.Variant.new_string(e.textDirection)),t):(t.set_submenu(a),t.set_label(e.label),e.icon!==void 0&&t.set_attribute_value(`icon`,r.Variant.new_string(e.icon)),e.submenuAction!==void 0&&t.set_attribute_value(`submenu-action`,r.Variant.new_string(e.submenuAction)),e.macosSpecial!==void 0&&t.set_attribute_value(`gtk-macos-special`,r.Variant.new_string(e.macosSpecial)),t)}function buildGioMenu(e){let r=new n.Menu;for(let n of t(e))r.append_item(itemOf(n));return r}const isPortableMenu=e=>Array.isArray(e);function attr(e,t,n){let i=e.get_item_attribute_value(t,n,r.VariantType.new(`s`));return i===null?void 0:i.get_string()[0]}function detailedAction(e,t){let n=attr(e,t,`action`);if(n===void 0)return;let r=e.get_item_attribute_value(t,`target`,null);return r===null?n:r.get_type_string()===`s`?`${n}::${r.get_string()[0]}`:`${n}(${r.print(!1)})`}function fromGioMenu(e){let t=[];for(let r=0;r<e.get_n_items();r+=1){let i=e.get_item_link(r,n.MENU_LINK_SECTION),a=e.get_item_link(r,n.MENU_LINK_SUBMENU),o=attr(e,r,`label`);if(i!==null){let n={kind:`section`,items:fromGioMenu(i)};o!==void 0&&(n.label=o);let a=attr(e,r,`display-hint`);a!==void 0&&(n.displayHint=a);let s=attr(e,r,`text-direction`);s!==void 0&&(n.textDirection=s),t.push(n);continue}if(a!==null){let n={kind:`submenu`,label:o??``,items:fromGioMenu(a)};for(let[t,i]of[[`icon`,`icon`],[`submenuAction`,`submenu-action`],[`macosSpecial`,`gtk-macos-special`]]){let a=attr(e,r,i);a!==void 0&&(n[t]=a)}t.push(n);continue}let s={kind:`item`,label:o??``},c=detailedAction(e,r);c!==void 0&&(s.action=c);for(let[t,n]of[[`icon`,`icon`],[`verbIcon`,`verb-icon`],[`accel`,`accel`],[`hiddenWhen`,`hidden-when`],[`custom`,`custom`],[`id`,`id`]]){let i=attr(e,r,n);i!==void 0&&(s[t]=i)}attr(e,r,`use-markup`)!==void 0&&(s.useMarkup=!0),t.push(s)}return t}export{buildGioMenu,fromGioMenu,isPortableMenu};
1
+ import"./_virtual/_rolldown/runtime.js";import{err as e}from"./errors.js";import t from"gi://Gio?version=2.0";import{normalizeMenuModel as n}from"@gjsify/adwaita-core";import r from"gi://GLib?version=2.0";const i={label:`label`,action:`action`,icon:`icon`,verbIcon:`verb-icon`,accel:`accel`,hiddenWhen:`hidden-when`,custom:`custom`,id:`id`};function requireDetailedAction(n,r){try{t.Action.parse_detailed_name(n)}catch(t){throw e.badDetailedAction(r,n,t instanceof Error?t.message:String(t))}}function itemOf(e){let n=new t.MenuItem;if(e.kind===`item`){e.action!==void 0&&(requireDetailedAction(e.action,e.label),n.set_detailed_action(e.action));for(let[t,a]of Object.entries(i)){let i=e[t];t===`action`||typeof i!=`string`||n.set_attribute_value(a,r.Variant.new_string(i))}return e.useMarkup===!0&&n.set_attribute_value(`use-markup`,r.Variant.new_string(`true`)),n}let a=buildGioMenu(e.items);return e.kind===`section`?(n.set_section(a),e.label!==void 0&&n.set_label(e.label),e.displayHint!==void 0&&n.set_attribute_value(`display-hint`,r.Variant.new_string(e.displayHint)),e.textDirection!==void 0&&n.set_attribute_value(`text-direction`,r.Variant.new_string(e.textDirection)),n):(n.set_submenu(a),n.set_label(e.label),e.icon!==void 0&&n.set_attribute_value(`icon`,r.Variant.new_string(e.icon)),e.submenuAction!==void 0&&n.set_attribute_value(`submenu-action`,r.Variant.new_string(e.submenuAction)),e.macosSpecial!==void 0&&n.set_attribute_value(`gtk-macos-special`,r.Variant.new_string(e.macosSpecial)),n)}function buildGioMenu(e){let r=new t.Menu;for(let t of n(e))r.append_item(itemOf(t));return r}const isPortableMenu=e=>Array.isArray(e);function attr(e,t,n){let i=e.get_item_attribute_value(t,n,r.VariantType.new(`s`));return i===null?void 0:i.get_string()[0]}function detailedAction(e,t){let n=attr(e,t,`action`);if(n===void 0)return;let r=e.get_item_attribute_value(t,`target`,null);return r===null?n:r.get_type_string()===`s`?`${n}::${r.get_string()[0]}`:`${n}(${r.print(!1)})`}function fromGioMenu(e){let n=[];for(let r=0;r<e.get_n_items();r+=1){let i=e.get_item_link(r,t.MENU_LINK_SECTION),a=e.get_item_link(r,t.MENU_LINK_SUBMENU),o=attr(e,r,`label`);if(i!==null){let t={kind:`section`,items:fromGioMenu(i)};o!==void 0&&(t.label=o);let a=attr(e,r,`display-hint`);a!==void 0&&(t.displayHint=a);let s=attr(e,r,`text-direction`);s!==void 0&&(t.textDirection=s),n.push(t);continue}if(a!==null){let t={kind:`submenu`,label:o??``,items:fromGioMenu(a)};for(let[n,i]of[[`icon`,`icon`],[`submenuAction`,`submenu-action`],[`macosSpecial`,`gtk-macos-special`]]){let a=attr(e,r,i);a!==void 0&&(t[n]=a)}n.push(t);continue}let s={kind:`item`,label:o??``},c=detailedAction(e,r);c!==void 0&&(s.action=c);for(let[t,n]of[[`icon`,`icon`],[`verbIcon`,`verb-icon`],[`accel`,`accel`],[`hiddenWhen`,`hidden-when`],[`custom`,`custom`],[`id`,`id`]]){let i=attr(e,r,n);i!==void 0&&(s[t]=i)}attr(e,r,`use-markup`)!==void 0&&(s.useMarkup=!0),n.push(s)}return n}export{buildGioMenu,fromGioMenu,isPortableMenu};
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{GtkHostError as e,err as t}from"./errors.js";import{beginHostWrite as n,endHostWrite as r}from"./signals.js";import i from"gi://GObject?version=2.0";import a from"gi://Gtk?version=4.0";function addressOf(e){let n=e.wrapper??e.widget;if(!n)throw t.notAWidget(e.descriptor.gtype);return n}function makeWrapper(e,t,n){let r=e.kind===`indexed`?e.wrap:e.kind===`slotted`?e.wrapSlots?.[n??e.defaultSlot]??null:null;if(!r)return null;if(r===`list-box-row`){if(t instanceof a.ListBoxRow)return null;let e=new a.ListBoxRow;return e.set_child(t),e}if(t instanceof a.FlowBoxChild)return null;let i=new a.FlowBoxChild;return i.set_child(t),i}const makeDetachedContainer=()=>new a.Box;function unhandledPolicy(e){throw Error(`unhandled child policy: ${JSON.stringify(e)}`)}function setterSlotOf(e,t){let n=e.descriptor.children;if(n.kind===`single`)return n.set;if(n.kind!==`slotted`)return null;let r=n.slots[t.slot??n.defaultSlot];return r?.startsWith(`set_`)===!0?r:null}function adderSlots(e){return e.kind===`slotted`?Object.entries(e.slots).filter(([,e])=>!e.startsWith(`set_`)).map(([e])=>e):[]}function setterSlots(e){return e.kind===`single`?[e.set]:e.kind===`slotted`?Object.values(e.slots).filter(e=>e.startsWith(`set_`)):[]}function slotOccupant(e,t){let n=e,r=t.replace(/^set_/,`get_`);if(typeof n[r]==`function`)return n[r]()??null}const o={kind:`parented`},placementOf=e=>e.placement??o;function outsideParentOf(e){let t=placementOf(e);switch(t.kind){case`parented`:return null;case`portal`:case`toplevel`:return t;default:return unhandledPlacement(t)}}function portalOf(e){let t=outsideParentOf(e);return t?.kind===`portal`?t:null}function unhandledPlacement(e){throw Error(`unhandled node placement: ${JSON.stringify(e)}`)}const isPortal=e=>portalOf(e.descriptor)!==null,isUnparented=e=>outsideParentOf(e.descriptor)!==null;function placementMethod(e,n,r,i){let a=e.widget?.[r];if(typeof a!=`function`)throw t.placementMethodMissing(e.descriptor.gtype,n.kind,r,i);return a}const toplevelOf=e=>{let t=e.get_root();return t instanceof a.Window?t:null};function presentPortal(e,t,n){let r=e.widget;return r?(placementMethod(t,n,n.present,`present`),placementMethod(t,n,n.close,`close`),watchPortalRoot(r,t,n),placeAgainst(r,t,n)):!1}function placeAgainst(e,t,n){let r=t.widget;if(!r)return!1;let i=toplevelOf(e);if(!i)return placementMethod(t,n,n.close,`close`).call(r),!1;if(r.get_parent()){if(toplevelOf(r)===i)return!0;placementMethod(t,n,n.close,`close`).call(r)}return placementMethod(t,n,n.present,`present`).call(r,e),!0}function watchPortalRoot(e,t,n){t.portalWatch?.widget!==e&&(t.portalWatch&&retractPortalWatch(t),t.portalWatch={widget:e,id:e.connect(`notify::root`,()=>{t.attached=placeAgainst(e,t,n)})})}function retractPortalWatch(e){let t=e.portalWatch;t&&(e.portalWatch=null,t.widget.disconnect(t.id))}function retractPortal(e,t){retractPortalWatch(e),e.widget&&placementMethod(e,t,t.close,`close`).call(e.widget)}function presentToplevel(e,t){let n=e.widget;if(!n)return!1;let r=placementMethod(e,t,t.present,`present`);return placementMethod(e,t,t.close,`close`),e.props.visible!==!1&&r.call(n),!0}function closeToplevel(e,t){e.widget&&placementMethod(e,t,t.close,`close`).call(e.widget)}function detachToplevel(e){let t=e.widget;t&&t.set_visible(!1)}function placeOutsideParent(e,t,n){switch(n.kind){case`portal`:return presentPortal(e,t,n);case`toplevel`:return presentToplevel(t,n);default:return unhandledPlacement(n)}}function detachOutsideParent(e,t){switch(t.kind){case`portal`:return retractPortal(e,t);case`toplevel`:return detachToplevel(e);default:return unhandledPlacement(t)}}function closeOutsideParent(e,t){switch(t.kind){case`portal`:return retractPortal(e,t);case`toplevel`:return closeToplevel(e,t);default:return unhandledPlacement(t)}}function classPlacementKind(e,t){return i.type_is_a(e,a.Root.$gtype)?`toplevel`:typeof t==`function`&&t.length===1?`portal`:null}function nodePlacementKind(e){let t=e.constructor?.$gtype;return t?classPlacementKind(t,e.present):null}function refuseUnparentable(e,n){if(n.descriptor.placement!==void 0)return;let r=n.widget;if(!r)return;let i=nodePlacementKind(r);if(i)throw t.unparentableChild(e.descriptor.gtype,n.descriptor.gtype,i,i===`toplevel`?`${n.descriptor.gtype} implements Gtk.Root, so it IS a toplevel and cannot have a parent`:`${n.descriptor.gtype}.present() takes a parent, so it is presented AGAINST one and never placed into one`)}function insertChild(n){try{placeChild(n)}catch(r){throw r instanceof e?r:t.rejectedChild(n.parent.descriptor.gtype,n.child.descriptor.gtype,r.message)}syncPerLineCap(n.parent)}function placeChild(e){let{parent:n,child:r}=e,i=n.descriptor.children,a=n.widget,o=addressOf(r);switch(i.kind){case`none`:throw t.unclaimedChild(n.descriptor.gtype,r.descriptor.gtype);case`uncurated`:throw t.uncuratedPlacement(n.descriptor.gtype,r.descriptor.gtype);case`single`:a[i.set](o);return;case`indexed`:a[i.insert](o,e.index);return;case`coords`:appendChild(n,r,a);return;case`ordered`:if(i.after){a[i.after](o,e.prevWidget??null);return}case`slotted`:case`keyed`:appendChild(n,r,a),rotateTail(n,r,e.following,a);return;default:return unhandledPolicy(i)}}function appendChild(e,n,r){let i=e.descriptor.children,a=addressOf(n);switch(i.kind){case`uncurated`:throw t.uncuratedPlacement(e.descriptor.gtype,n.descriptor.gtype);case`ordered`:r[i.append](a);return;case`slotted`:{let o=n.slot??i.defaultSlot,s=i.slots[o];if(!s)throw t.unknownSlot(e.descriptor.gtype,o,Object.keys(i.slots));r[s](a);return}case`keyed`:{let e=n.layout?.[i.nameFrom]??n.slot,t=n.layout?.title;i.titled?r[i.add](a,e??null,t??e??``):r[i.add](a);return}case`coords`:{let e=n.layout??{};r[i.attach](a,e.column??0,e.row??0,e.columnSpan??1,e.rowSpan??1);return}default:throw t.unclaimedChild(e.descriptor.gtype,n.descriptor.gtype)}}function rotateTail(e,t,n,r){let i=e.descriptor.children,a=n;if(i.kind===`slotted`){if(setterSlotOf(e,t))return;let slotOf=e=>e.slot??i.defaultSlot,r=slotOf(t);a=n.filter(e=>slotOf(e)===r)}for(let t of a)detachChild(e,t,r);for(let t of a)appendChild(e,t,r)}function detachChild(e,n,r){let i=e.descriptor.children,a=n.wrapper??n.widget;if(a)switch(i.kind){case`none`:case`uncurated`:return;case`single`:clearIfCurrent(r,i.set,a);return;case`slotted`:{let o=setterSlotOf(e,n);if(o){clearIfCurrent(r,o,a);return}let s=n.slot??i.defaultSlot;if(!i.remove)throw t.slotNeedsRemove(e.descriptor.gtype,s,i.slots[s]??`?`);r[i.remove](a);return}case`keyed`:{let e=i.hideBeforeRemove===!0&&a.get_visible();e&&writeVisible(a,!1),r[i.remove](a),e&&writeVisible(a,!0);return}case`ordered`:case`indexed`:case`coords`:r[i.remove](a);return;default:return unhandledPolicy(i)}}function writeVisible(e,t){n(null);try{e.set_visible(t)}finally{r()}}function clearIfCurrent(e,t,n){let r=slotOccupant(e,t);(r===void 0||r===n)&&e[t](null)}function removeChild(e,t){let n=outsideParentOf(t.descriptor);if(n)return detachOutsideParent(t,n);let r=e.widget;r&&t.attached&&(detachChild(e,t,r),syncPerLineCap(e))}function syncPerLineCap(e){let t=e.descriptor.children;if(t.kind!==`indexed`||t.perLineCap===void 0||e.props[t.perLineCap]!==void 0)return;let i=e.widget;if(!i)return;let a=0;for(let e=i.get_first_child();e!==null;e=e.get_next_sibling())a+=1;n(null);try{i.set_property(t.perLineCap,Math.min(65535,Math.max(1,a)))}finally{r()}}function reorderMode(e){switch(e.kind){case`uncurated`:return`n/a`;case`ordered`:return e.reorder;case`indexed`:return`native`;case`slotted`:return adderSlots(e).length>0?`remove-all`:`n/a`;case`keyed`:return`remove-all`;case`coords`:case`single`:case`none`:return`n/a`;default:return unhandledPolicy(e)}}export{adderSlots,addressOf,classPlacementKind,closeOutsideParent,closeToplevel,detachOutsideParent,detachToplevel,insertChild,isPortal,isUnparented,makeDetachedContainer,makeWrapper,nodePlacementKind,outsideParentOf,placeOutsideParent,placementOf,portalOf,presentPortal,presentToplevel,refuseUnparentable,removeChild,reorderMode,retractPortal,setterSlotOf,setterSlots,slotOccupant,unhandledPlacement,unhandledPolicy};
1
+ import"./_virtual/_rolldown/runtime.js";import{GtkHostError as e,err as t}from"./errors.js";import{beginHostWrite as n,endHostWrite as r}from"./signals.js";import i from"gi://GObject?version=2.0";import a from"gi://Gtk?version=4.0";function addressOf(e){let n=e.wrapper??e.widget;if(!n)throw t.notAWidget(e.descriptor.gtype);return n}function slotPropertyOf(e){return e.startsWith(`set_`)?e.slice(4).replace(/_/g,`-`):null}function slotNames(e){if(e.kind===`single`){let t=slotPropertyOf(e.set);return t===null?[]:[t]}if(e.kind!==`slotted`)return[];let t=[];for(let[n,r]of Object.entries(e.slots)){t.push(n);let e=slotPropertyOf(r);e!==null&&e!==n&&t.push(e)}return t}function slottedSlot(e,n,r){if(n==null){if(e.defaultSlot in e.slots)return e.defaultSlot;throw t.unknownSlot(r,e.defaultSlot,slotNames(e))}if(n in e.slots)return n;for(let[t,r]of Object.entries(e.slots))if(slotPropertyOf(r)===n)return t;throw t.unknownSlot(r,n,slotNames(e))}function refuseUnknownSlot(e,n){let r=n.slot;if(r==null)return;let i=e.descriptor.children;if(i.kind===`slotted`){slottedSlot(i,r,e.descriptor.gtype);return}if(i.kind!==`keyed`&&!(i.kind===`single`&&slotPropertyOf(i.set)===r))throw t.unknownSlot(e.descriptor.gtype,r,slotNames(i))}function makeWrapper(e,t,n){let r=e.children,i=r.kind===`indexed`?r.wrap:r.kind===`slotted`?r.wrapSlots?.[slottedSlot(r,n,e.gtype)]??null:null;if(!i)return null;if(i===`list-box-row`){if(t instanceof a.ListBoxRow)return null;let e=new a.ListBoxRow;return e.set_child(t),e}if(t instanceof a.FlowBoxChild)return null;let o=new a.FlowBoxChild;return o.set_child(t),o}const makeDetachedContainer=()=>new a.Box;function unhandledPolicy(e){throw Error(`unhandled child policy: ${JSON.stringify(e)}`)}function setterSlotOf(e,t){let n=e.descriptor.children;if(n.kind===`single`)return n.set;if(n.kind!==`slotted`)return null;let r=n.slots[slottedSlot(n,t.slot,e.descriptor.gtype)];return r?.startsWith(`set_`)===!0?r:null}function adderSlots(e){return e.kind===`slotted`?Object.entries(e.slots).filter(([,e])=>!e.startsWith(`set_`)).map(([e])=>e):[]}function setterSlots(e){return e.kind===`single`?[e.set]:e.kind===`slotted`?Object.values(e.slots).filter(e=>e.startsWith(`set_`)):[]}function slotOccupant(e,t){let n=e,r=t.replace(/^set_/,`get_`);if(typeof n[r]==`function`)return n[r]()??null}const o={kind:`parented`},placementOf=e=>e.placement??o;function outsideParentOf(e){let t=placementOf(e);switch(t.kind){case`parented`:return null;case`portal`:case`toplevel`:return t;default:return unhandledPlacement(t)}}function portalOf(e){let t=outsideParentOf(e);return t?.kind===`portal`?t:null}function unhandledPlacement(e){throw Error(`unhandled node placement: ${JSON.stringify(e)}`)}const isPortal=e=>portalOf(e.descriptor)!==null,isUnparented=e=>outsideParentOf(e.descriptor)!==null;function placementMethod(e,n,r,i){let a=e.widget?.[r];if(typeof a!=`function`)throw t.placementMethodMissing(e.descriptor.gtype,n.kind,r,i);return a}const toplevelOf=e=>{let t=e.get_root();return t instanceof a.Window?t:null};function presentPortal(e,t,n){let r=e.widget;return r?(placementMethod(t,n,n.present,`present`),placementMethod(t,n,n.close,`close`),watchPortalRoot(r,t,n),placeAgainst(r,t,n)):!1}function placeAgainst(e,t,n){let r=t.widget;if(!r)return!1;let i=toplevelOf(e);if(!i)return placementMethod(t,n,n.close,`close`).call(r),!1;if(r.get_parent()){if(toplevelOf(r)===i)return!0;placementMethod(t,n,n.close,`close`).call(r)}return placementMethod(t,n,n.present,`present`).call(r,e),!0}function watchPortalRoot(e,t,n){t.portalWatch?.widget!==e&&(t.portalWatch&&retractPortalWatch(t),t.portalWatch={widget:e,id:e.connect(`notify::root`,()=>{t.attached=placeAgainst(e,t,n)})})}function retractPortalWatch(e){let t=e.portalWatch;t&&(e.portalWatch=null,t.widget.disconnect(t.id))}function retractPortal(e,t){retractPortalWatch(e),e.widget&&placementMethod(e,t,t.close,`close`).call(e.widget)}function presentToplevel(e,t){let n=e.widget;if(!n)return!1;let r=placementMethod(e,t,t.present,`present`);return placementMethod(e,t,t.close,`close`),e.props.visible!==!1&&r.call(n),!0}function closeToplevel(e,t){e.widget&&placementMethod(e,t,t.close,`close`).call(e.widget)}function detachToplevel(e){let t=e.widget;t&&t.set_visible(!1)}function placeOutsideParent(e,t,n){switch(n.kind){case`portal`:return presentPortal(e,t,n);case`toplevel`:return presentToplevel(t,n);default:return unhandledPlacement(n)}}function detachOutsideParent(e,t){switch(t.kind){case`portal`:return retractPortal(e,t);case`toplevel`:return detachToplevel(e);default:return unhandledPlacement(t)}}function closeOutsideParent(e,t){switch(t.kind){case`portal`:return retractPortal(e,t);case`toplevel`:return closeToplevel(e,t);default:return unhandledPlacement(t)}}function classPlacementKind(e,t){return i.type_is_a(e,a.Root.$gtype)?`toplevel`:typeof t==`function`&&t.length===1?`portal`:null}function nodePlacementKind(e){let t=e.constructor?.$gtype;return t?classPlacementKind(t,e.present):null}function refuseUnparentable(e,n){if(n.descriptor.placement!==void 0)return;let r=n.widget;if(!r)return;let i=nodePlacementKind(r);if(i)throw t.unparentableChild(e.descriptor.gtype,n.descriptor.gtype,i,i===`toplevel`?`${n.descriptor.gtype} implements Gtk.Root, so it IS a toplevel and cannot have a parent`:`${n.descriptor.gtype}.present() takes a parent, so it is presented AGAINST one and never placed into one`)}function insertChild(n){try{placeChild(n)}catch(r){throw r instanceof e?r:t.rejectedChild(n.parent.descriptor.gtype,n.child.descriptor.gtype,r.message)}syncPerLineCap(n.parent)}function placeChild(e){let{parent:n,child:r}=e,i=n.descriptor.children,a=n.widget,o=addressOf(r);switch(i.kind){case`none`:throw t.unclaimedChild(n.descriptor.gtype,r.descriptor.gtype);case`uncurated`:throw t.uncuratedPlacement(n.descriptor.gtype,r.descriptor.gtype);case`single`:a[i.set](o);return;case`indexed`:a[i.insert](o,e.index);return;case`coords`:appendChild(n,r,a);return;case`ordered`:if(i.after){a[i.after](o,e.prevWidget??null);return}case`slotted`:case`keyed`:appendChild(n,r,a),rotateTail(n,r,e.following,a);return;default:return unhandledPolicy(i)}}function appendChild(e,n,r){let i=e.descriptor.children,a=addressOf(n);switch(i.kind){case`uncurated`:throw t.uncuratedPlacement(e.descriptor.gtype,n.descriptor.gtype);case`ordered`:r[i.append](a);return;case`slotted`:{let t=slottedSlot(i,n.slot,e.descriptor.gtype);r[i.slots[t]](a);return}case`keyed`:{let e=n.layout?.[i.nameFrom]??n.slot,t=n.layout?.title;i.titled?r[i.add](a,e??null,t??e??``):r[i.add](a);return}case`coords`:{let e=n.layout??{};r[i.attach](a,e.column??0,e.row??0,e.columnSpan??1,e.rowSpan??1);return}default:throw t.unclaimedChild(e.descriptor.gtype,n.descriptor.gtype)}}function rotateTail(e,t,n,r){let i=e.descriptor.children,a=n;if(i.kind===`slotted`){if(setterSlotOf(e,t))return;let slotOf=t=>slottedSlot(i,t.slot,e.descriptor.gtype),r=slotOf(t);a=n.filter(e=>slotOf(e)===r)}for(let t of a)detachChild(e,t,r);for(let t of a)appendChild(e,t,r)}function detachChild(e,n,r){let i=e.descriptor.children,a=n.wrapper??n.widget;if(a)switch(i.kind){case`none`:case`uncurated`:return;case`single`:clearIfCurrent(r,i.set,a);return;case`slotted`:{let o=setterSlotOf(e,n);if(o){clearIfCurrent(r,o,a);return}let s=slottedSlot(i,n.slot,e.descriptor.gtype);if(!i.remove)throw t.slotNeedsRemove(e.descriptor.gtype,s,i.slots[s]??`?`);r[i.remove](a);return}case`keyed`:{let e=i.hideBeforeRemove===!0&&a.get_visible();e&&writeVisible(a,!1),r[i.remove](a),e&&writeVisible(a,!0);return}case`ordered`:case`indexed`:case`coords`:r[i.remove](a);return;default:return unhandledPolicy(i)}}function writeVisible(e,t){n(null);try{e.set_visible(t)}finally{r()}}function clearIfCurrent(e,t,n){let r=slotOccupant(e,t);(r===void 0||r===n)&&e[t](null)}function removeChild(e,t){let n=outsideParentOf(t.descriptor);if(n)return detachOutsideParent(t,n);let r=e.widget;r&&t.attached&&(detachChild(e,t,r),syncPerLineCap(e))}function syncPerLineCap(e){let t=e.descriptor.children;if(t.kind!==`indexed`||t.perLineCap===void 0||e.props[t.perLineCap]!==void 0)return;let i=e.widget;if(!i)return;let a=0;for(let e=i.get_first_child();e!==null;e=e.get_next_sibling())a+=1;n(null);try{i.set_property(t.perLineCap,Math.min(65535,Math.max(1,a)))}finally{r()}}function reorderMode(e){switch(e.kind){case`uncurated`:return`n/a`;case`ordered`:return e.reorder;case`indexed`:return`native`;case`slotted`:return adderSlots(e).length>0?`remove-all`:`n/a`;case`keyed`:return`remove-all`;case`coords`:case`single`:case`none`:return`n/a`;default:return unhandledPolicy(e)}}export{adderSlots,addressOf,classPlacementKind,closeOutsideParent,closeToplevel,detachOutsideParent,detachToplevel,insertChild,isPortal,isUnparented,makeDetachedContainer,makeWrapper,nodePlacementKind,outsideParentOf,placeOutsideParent,placementOf,portalOf,presentPortal,presentToplevel,refuseUnknownSlot,refuseUnparentable,removeChild,reorderMode,retractPortal,setterSlotOf,setterSlots,slotNames,slotOccupant,slotPropertyOf,slottedSlot,unhandledPlacement,unhandledPolicy};
package/lib/esm/props.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{err as e}from"./errors.js";import{buildStringList as t,isPortableListModel as n}from"./list-model.js";import{buildAdjustment as r,isPortableAdjustment as i}from"./adjustment.js";import{buildGioMenu as a,isPortableMenu as o}from"./menu.js";import s from"gi://GObject?version=2.0";import c from"gi://Gtk?version=4.0";import l from"gi://Adw?version=1";import u from"gi://Gdk?version=4.0";import d from"gi://Gio?version=2.0";import f from"gi://Pango?version=1.0";const p=[[`Gtk`,c],[`Adw`,l],[`Gdk`,u],[`Pango`,f],[`G`,s]];function toPropertyName(e){return e.includes(`-`)?e:e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase()}function withoutKeys(e,t){if(!e)return;let n;for(let r of Object.keys(e))t.has(r)||((n??={})[r]=e[r]);return n}const m=new Map;function paramSpecs(e,t){let n=m.get(t);if(n)return n;n=new Map;for(let t of e.list_properties())n.set(t.get_name(),t);return m.set(t,n),n}const isFlag=(e,t)=>(e&t)!==0,isWritable=e=>isFlag(e.flags,s.ParamFlags.WRITABLE),isConstructOnly=e=>isFlag(e.flags,s.ParamFlags.CONSTRUCT_ONLY);function constructOnlyNames(e,t){let n=[];for(let[r,i]of paramSpecs(e,t))isConstructOnly(i)&&isWritable(i)&&n.push(r);return n}function resolveEnumValue(e,t){for(let[n,r]of p){if(!e.startsWith(n))continue;let i=r[e.slice(n.length)];if(!i)continue;let a=i[t.toUpperCase().replace(/-/g,`_`)];return typeof a==`number`?{resolved:!0,value:a}:{resolved:!0}}return{resolved:!1}}const lookupEnumNick=(e,t)=>resolveEnumValue(e,t).value;function enumMembers(e){for(let[t,n]of p){if(!e.startsWith(t))continue;let r=n[e.slice(t.length)];if(r)return Object.keys(r).filter(e=>e!==`$gtype`&&typeof r[e]==`number`)}}const kindOf=e=>Array.isArray(e)?`an array`:`a ${typeof e}`;function coerce(l,u,f){if(u==null)return u;let p=l.value_type;if(s.type_is_a(p,d.MenuModel.$gtype)&&o(u))return a(u);if(s.type_is_a(p,d.ListModel.$gtype)&&!(u instanceof s.Object)){if(!n(u))throw e.badListModel(f,l.get_name(),kindOf(u));if(!s.type_is_a(c.StringList.$gtype,p))throw e.listModelMismatch(f,l.get_name(),s.type_name(p));return t(u)}if(s.type_is_a(p,c.Adjustment.$gtype)&&!(u instanceof s.Object)){if(!i(u))throw e.badAdjustment(f,l.get_name(),kindOf(u));return r(u)}if(s.type_is_a(p,s.TYPE_ENUM)&&typeof u==`string`){let t=s.type_name(p),n=resolveEnumValue(t,u);if(n.value!==void 0)return n.value;throw n.resolved?e.badEnum(f,l.get_name(),u,t):e.unresolvableEnum(t)}if(s.type_is_a(p,s.TYPE_FLAGS)&&typeof u==`string`)throw e.badFlags(f,l.get_name(),u,s.type_name(p));if(s.type_is_a(p,s.TYPE_BOOLEAN)){if(typeof u==`boolean`)return u;if(u===`true`)return!0;if(u===`false`)return!1;if(typeof u==`string`)throw e.badBoolean(f,l.get_name(),u);return!!u}if(s.type_is_a(p,s.TYPE_STRING)){if(typeof u==`string`)return u;if(typeof u==`number`||typeof u==`boolean`)return String(u);throw e.badString(f,l.get_name(),typeof u)}return(s.type_is_a(p,s.TYPE_INT)||s.type_is_a(p,s.TYPE_UINT)||s.type_is_a(p,s.TYPE_INT64)||s.type_is_a(p,s.TYPE_UINT64))&&typeof u==`number`?Math.trunc(u):u}const h=[s.TYPE_BOOLEAN,s.TYPE_STRING,s.TYPE_INT,s.TYPE_UINT,s.TYPE_INT64,s.TYPE_UINT64,s.TYPE_DOUBLE,s.TYPE_FLOAT],isScalarSpec=e=>s.type_is_a(e.value_type,s.TYPE_ENUM)||h.some(t=>s.type_is_a(e.value_type,t)),toAccessorName=e=>e.replace(/-([a-z0-9])/g,(e,t)=>t.toUpperCase()),g=new Map;function constructedDefaults(e){let t=g.get(e.gtype);if(t)return t;let n=new Map;g.set(e.gtype,n);let r=e.ctor(),i;try{let t={};for(let n of e.requiresProps??[])t[n]=``;i=new r(t)}catch{return n}for(let[t,a]of paramSpecs(r,e.gtype)){if(!isWritable(a)||isConstructOnly(a)||!isFlag(a.flags,s.ParamFlags.READABLE)||isFlag(a.flags,s.ParamFlags.DEPRECATED)||!isScalarSpec(a))continue;let e=toAccessorName(t);e in i&&n.set(t,i[e])}return i instanceof c.Window&&i.destroy(),n}function removedValue(e,t){let n=constructedDefaults(e),r=t.get_name();return n.has(r)?n.get(r):t.get_default_value()}function requireSpec(t,n,r){let i=t.get(r);if(!i)throw e.unknownProp(n,r);if(!isWritable(i))throw e.readOnlyProp(n,r);return i}export{coerce,constructOnlyNames,enumMembers,isConstructOnly,isWritable,lookupEnumNick,paramSpecs,removedValue,requireSpec,toPropertyName,withoutKeys};
1
+ import"./_virtual/_rolldown/runtime.js";import{err as e}from"./errors.js";import{buildAdjustment as t,isPortableAdjustment as n}from"./adjustment.js";import{buildStringList as r,isPortableListModel as i}from"./list-model.js";import{buildGioMenu as a,isPortableMenu as o}from"./menu.js";import s from"gi://GObject?version=2.0";import c from"gi://Gtk?version=4.0";import l from"gi://Adw?version=1";import u from"gi://Gdk?version=4.0";import d from"gi://Gio?version=2.0";import f from"gi://Pango?version=1.0";const p=[[`Gtk`,c],[`Adw`,l],[`Gdk`,u],[`Pango`,f],[`G`,d],[`G`,s]];function toPropertyName(e){return e.includes(`-`)?e:e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase()}function withoutKeys(e,t){if(!e)return;let n;for(let r of Object.keys(e))t.has(r)||((n??={})[r]=e[r]);return n}const m=new Map;function paramSpecs(e,t){let n=m.get(t);if(n)return n;n=new Map;for(let t of e.list_properties())n.set(t.get_name(),t);return m.set(t,n),n}const isFlag=(e,t)=>(e&t)!==0,isWritable=e=>isFlag(e.flags,s.ParamFlags.WRITABLE),isConstructOnly=e=>isFlag(e.flags,s.ParamFlags.CONSTRUCT_ONLY);function constructOnlyNames(e,t){let n=[];for(let[r,i]of paramSpecs(e,t))isConstructOnly(i)&&isWritable(i)&&n.push(r);return n}function giTypeObject(e){for(let[t,n]of p){if(!e.startsWith(t))continue;let r=n[e.slice(t.length)];if(!r||typeof r!=`object`)continue;let i=r.$gtype;if(!(!i||s.type_name(i)!==e))return r}}function gtypeOfName(e){return s.type_from_name(e)||giTypeObject(e)?.$gtype}let h;const isWholeNumber=e=>/^[+-]?(?:0[xX][0-9a-fA-F]+|[0-9]+)$/.test(e.trim()),startsNumeric=e=>/^[+-]?[0-9]/.test(e.trim());function memberNickValue(e,t){let n=giTypeObject(s.type_name(e))?.[t.trim().toUpperCase().replace(/-/g,`_`)];return typeof n==`number`?n:void 0}function parseNickText(e,t){if(!isWholeNumber(t)){let n=t.split(`|`);if(n.some(startsNumeric))return n.length===1?memberNickValue(e,t):void 0}h??=new c.Builder;try{let[n,r]=h.value_from_string_type(e,t);return n&&typeof r==`number`?r:void 0}catch{return}}const hasBlankMember=e=>e.split(`|`).some(e=>e.trim().length===0),lookupEnumNick=(e,t)=>{let n=gtypeOfName(e);return n===void 0?void 0:parseNickText(n,t)};function enumMembers(e){let t=giTypeObject(e);if(t)return Object.keys(t).filter(e=>e!==`$gtype`&&typeof t[e]==`number`)}const kindOf=e=>Array.isArray(e)?`an array`:`a ${typeof e}`;function coerce(l,u,f){if(u==null)return u;let p=l.value_type;if(s.type_is_a(p,d.MenuModel.$gtype)&&o(u))return a(u);if(s.type_is_a(p,d.ListModel.$gtype)&&!(u instanceof s.Object)){if(!i(u))throw e.badListModel(f,l.get_name(),kindOf(u));if(!s.type_is_a(c.StringList.$gtype,p))throw e.listModelMismatch(f,l.get_name(),s.type_name(p));return r(u)}if(s.type_is_a(p,c.Adjustment.$gtype)&&!(u instanceof s.Object)){if(!n(u))throw e.badAdjustment(f,l.get_name(),kindOf(u));return t(u)}if(s.type_is_a(p,s.TYPE_ENUM)&&typeof u==`string`){let t=parseNickText(p,u);if(t!==void 0)return t;throw e.badEnum(f,l.get_name(),u,s.type_name(p))}if(s.type_is_a(p,s.TYPE_FLAGS)&&typeof u==`string`){let t=s.type_name(p);if(hasBlankMember(u))throw e.blankFlags(f,l.get_name(),u,t);let n=parseNickText(p,u);if(n!==void 0)return n;throw e.badFlags(f,l.get_name(),u,t)}if(s.type_is_a(p,s.TYPE_BOOLEAN)){if(typeof u==`boolean`)return u;if(u===`true`)return!0;if(u===`false`)return!1;if(typeof u==`string`)throw e.badBoolean(f,l.get_name(),u);return!!u}if(s.type_is_a(p,s.TYPE_STRING)){if(typeof u==`string`)return u;if(typeof u==`number`||typeof u==`boolean`)return String(u);throw e.badString(f,l.get_name(),typeof u)}return(s.type_is_a(p,s.TYPE_INT)||s.type_is_a(p,s.TYPE_UINT)||s.type_is_a(p,s.TYPE_INT64)||s.type_is_a(p,s.TYPE_UINT64))&&typeof u==`number`?Math.trunc(u):u}const g=[s.TYPE_BOOLEAN,s.TYPE_STRING,s.TYPE_INT,s.TYPE_UINT,s.TYPE_INT64,s.TYPE_UINT64,s.TYPE_DOUBLE,s.TYPE_FLOAT],isScalarSpec=e=>s.type_is_a(e.value_type,s.TYPE_ENUM)||g.some(t=>s.type_is_a(e.value_type,t)),toAccessorName=e=>e.replace(/-([a-z0-9])/g,(e,t)=>t.toUpperCase()),_=new Map;function constructedDefaults(e){let t=_.get(e.gtype);if(t)return t;let n=new Map;_.set(e.gtype,n);let r=e.ctor(),i;try{let t={};for(let n of e.requiresProps??[])t[n]=``;i=new r(t)}catch{return n}for(let[t,a]of paramSpecs(r,e.gtype)){if(!isWritable(a)||isConstructOnly(a)||!isFlag(a.flags,s.ParamFlags.READABLE)||isFlag(a.flags,s.ParamFlags.DEPRECATED)||!isScalarSpec(a))continue;let e=toAccessorName(t);e in i&&n.set(t,i[e])}return i instanceof c.Window&&i.destroy(),n}function removedValue(e,t){let n=constructedDefaults(e),r=t.get_name();return n.has(r)?n.get(r):t.get_default_value()}function requireSpec(t,n,r){let i=t.get(r);if(!i)throw e.unknownProp(n,r);if(!isWritable(i))throw e.readOnlyProp(n,r);return i}export{coerce,constructOnlyNames,enumMembers,isConstructOnly,isWritable,lookupEnumNick,paramSpecs,removedValue,requireSpec,toPropertyName,withoutKeys};
@@ -0,0 +1,56 @@
1
+ import GObject from 'gi://GObject?version=2.0';
2
+ import type { AriaTable } from './types.js';
3
+ /** What `accessibility={{ … }}` carries. Keys are ARIA names; `null` clears a slot. */
4
+ export type AccessibilityInput = Readonly<Record<string, unknown>>;
5
+ interface AriaWrite {
6
+ readonly table: AriaTable;
7
+ readonly member: number;
8
+ readonly value: GObject.Value;
9
+ }
10
+ interface AriaReset {
11
+ readonly table: AriaTable;
12
+ readonly member: number;
13
+ }
14
+ /**
15
+ * Everything the three GTK calls need, resolved and refused BEFORE the first one runs.
16
+ *
17
+ * Built whole, then applied, for the same reason `setProp` validates before recording:
18
+ * a refusal half-way through would leave the widget carrying some of the authored
19
+ * accessibility and the element carrying all of it, and the next patch would compute its
20
+ * resets against a state that never existed.
21
+ */
22
+ export interface AccessibilityPlan {
23
+ readonly writes: readonly AriaWrite[];
24
+ readonly resets: readonly AriaReset[];
25
+ }
26
+ /**
27
+ * Resolve an authored accessibility object against the one it replaces.
28
+ *
29
+ * Total: every name is looked up, every value is built, and anything GTK would take
30
+ * silently and wrongly throws here instead. Nothing touches a widget.
31
+ */
32
+ export declare function planAccessibility(tag: string, previous: AccessibilityInput | null, next: AccessibilityInput | null): AccessibilityPlan;
33
+ /**
34
+ * Run a plan against a widget, one `update_*` call per table.
35
+ *
36
+ * BATCHED PER TABLE because that is the shape of the call: `gtk_accessible_update_state`
37
+ * takes parallel arrays and applies them together, so three names in one table are one
38
+ * call and one notification rather than three.
39
+ *
40
+ * The method names are DERIVED from the table name (`GtkAccessibleState` -> `update_state`),
41
+ * which is why `girs-vocabulary.mts` refuses a table it does not know rather than emitting
42
+ * its names: a derived call into a method GTK never installed is a `TypeError` in the middle
43
+ * of a render. `generated.spec.ts` holds all six derived names against the installed GTK.
44
+ */
45
+ export declare function applyAccessibilityPlan(widget: GObject.Object, plan: AccessibilityPlan): void;
46
+ /**
47
+ * Whether a class can carry accessibility at all.
48
+ *
49
+ * Asked of the CLASS, before the widget exists, so `<gtk-string-list accessibility={…}>`
50
+ * is refused at the call that authored it rather than at materialisation. Not every row of
51
+ * the generated table is a widget — the list carriers are `GObject`s that hold one — and
52
+ * `Gtk.StringList` has no `update_property` at all (measured), which would otherwise be a
53
+ * `TypeError` naming a method instead of a tag.
54
+ */
55
+ export declare const isAccessibleClass: (klass: GObject.ObjectClass) => boolean;
56
+ export {};
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -2,6 +2,7 @@ import type Gio from '@girs/gio-2.0';
2
2
  import type GObject from '@girs/gobject-2.0';
3
3
  import type Gtk from '@girs/gtk-4.0';
4
4
  import type { AdwAdjustmentInput, AdwListModelInput, AdwMenuInput } from '@gjsify/adwaita-core';
5
+ import type { AccessibilityAttributes } from './generated/accessibility.js';
5
6
  import type { HostNode } from './types.js';
6
7
  /**
7
8
  * A `notify::` handler.
@@ -61,6 +62,18 @@ export type WithOnce<T> = T & {
61
62
  export interface SlotAttribute {
62
63
  slot?: string | null;
63
64
  }
65
+ /**
66
+ * GTK's ARIA surface, on every element of every dialect. Read by `setAccessibility()`.
67
+ *
68
+ * ONE OBJECT, not 53 flat `aria*` props, and the four reasons are in `setAccessibility`'s
69
+ * own header — the load-bearing one being that TypeScript exempts a hyphenated JSX
70
+ * attribute from excess-property checking while a key in a fresh object literal is
71
+ * checked. `AccessibilityAttributes` is GENERATED, because the names and their value
72
+ * types are GTK's and are stated nowhere a ParamSpec can be read from.
73
+ */
74
+ export interface AccessibilityAttribute {
75
+ accessibility?: AccessibilityAttributes | null;
76
+ }
64
77
  /**
65
78
  * The `on:<raw-signal-name>` escape hatch, typed.
66
79
  *
@@ -87,7 +100,7 @@ export interface RawSignalAttributes {
87
100
  * `T` is the widget's own instance type, so `ref={(el) => …}` infers `el` as
88
101
  * `Gtk.Box` rather than the `unknown` a DOM renderer settles for.
89
102
  */
90
- export interface JsxAttributes<T> extends SlotAttribute, RawSignalAttributes {
103
+ export interface JsxAttributes<T> extends AccessibilityAttribute, SlotAttribute, RawSignalAttributes {
91
104
  children?: ElementChild;
92
105
  ref?: T | ((el: T) => void) | undefined;
93
106
  }
@@ -100,7 +113,7 @@ export interface JsxAttributes<T> extends SlotAttribute, RawSignalAttributes {
100
113
  * leave the property unusable, so the Vue surface adds only what Vue does not —
101
114
  * and `children` is a SLOT in Vue, never a prop.
102
115
  */
103
- export interface VueAttributes extends SlotAttribute, RawSignalAttributes {
116
+ export interface VueAttributes extends AccessibilityAttribute, SlotAttribute, RawSignalAttributes {
104
117
  }
105
118
  /**
106
119
  * The properties whose GObject type is a `GMenuModel`, in both spellings.
@@ -0,0 +1,31 @@
1
+ import type Gtk from '@girs/gtk-4.0';
2
+ /**
3
+ * Give this process an in-process accessibility backend, before anything asks for one.
4
+ *
5
+ * OVERWRITE is deliberate: CI sets `GTK_A11Y=none` explicitly, and honouring it would
6
+ * keep the vectors measuring an absent layer rather than the code under test.
7
+ *
8
+ * AND THE ORDER IS LOAD-BEARING, which is why this belongs at a test ENTRY POINT and
9
+ * not beside a `Gtk.init()`. GTK reads the variable lazily but exactly ONCE, at the
10
+ * first `get_at_context()`, and caches the answer — measured on gtk 4.22.5 starting
11
+ * from `GTK_A11Y=none`: set after `Gtk.init()` and before any widget is asked for its
12
+ * context, `test` takes; set after ONE widget has been asked, the answer is `null`
13
+ * forever. A module body runs after every `import` above it, so an entry point is
14
+ * early enough only for as long as nothing it imports touches an AT context while
15
+ * being evaluated. {@link withAtContext} is what NAMES the day that stops being true.
16
+ */
17
+ export declare function installAccessibilityBackend(): void;
18
+ /**
19
+ * The widget, or a refusal that says why an ARIA assertion about it cannot mean anything.
20
+ *
21
+ * A THROW rather than an `expect`, because the SENTENCE is the whole value here. Without
22
+ * it the symptom is `Expected: true (boolean) / Actual: false (boolean)`, six times over,
23
+ * on three OS legs at once — and that shape reads as a marshalling defect in whichever
24
+ * runtime those legs happen to share. It is not one; it is this.
25
+ *
26
+ * It also guards the assertions that expect FALSE, and those are the ones that make this
27
+ * a gate rather than a nicety: with no AT context they pass VACUOUSLY. A reset vector, a
28
+ * "nothing was authored here" vector — every one of them is green against a layer that
29
+ * was never there.
30
+ */
31
+ export declare function withAtContext<T extends Gtk.Accessible>(widget: T): T;