@gjsify/gtk-host 0.52.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -6
- package/lib/esm/conformance/index.js +1 -1
- package/lib/esm/errors.js +1 -1
- package/lib/esm/fonts.js +1 -1
- package/lib/esm/host.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/props.js +1 -1
- package/lib/esm/registry.js +1 -1
- package/lib/types/adapters/react.d.ts +24 -39
- package/lib/types/attrs.d.ts +37 -49
- package/lib/types/errors.d.ts +19 -0
- package/lib/types/fonts.d.ts +40 -31
- package/lib/types/host.d.ts +56 -78
- package/lib/types/index.d.ts +2 -2
- package/lib/types/policies.d.ts +159 -202
- package/lib/types/props.d.ts +30 -21
- package/lib/types/react-jsx-runtime.d.ts +1 -1
- package/lib/types/registry.d.ts +54 -0
- package/lib/types/testing/gate.d.mts +3 -3
- package/lib/types/types.d.ts +87 -82
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -783,17 +783,16 @@ root.render(createElement('GtkBox', null, createElement('GtkLabel', { label: 'hi
|
|
|
783
783
|
|
|
784
784
|
```
|
|
785
785
|
--define 'process.env.NODE_ENV="production"'
|
|
786
|
-
--exclude-globals navigator
|
|
787
786
|
```
|
|
788
787
|
|
|
789
788
|
`react-reconciler/index.js` picks its bundle from `process.env.NODE_ENV`, and the
|
|
790
789
|
development one reaches for `document`, `HTMLCanvasElement` and `Path2D`, which
|
|
791
790
|
makes `--globals auto` inject the GTK-backed DOM registers and pull `gi://Gdk`,
|
|
792
|
-
`GdkPixbuf`, `Pango` and `PangoCairo` into a bundle that needs none of them.
|
|
793
|
-
the
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
791
|
+
`GdkPixbuf`, `Pango` and `PangoCairo` into a bundle that needs none of them. With
|
|
792
|
+
the define the bundle loads with no `document`, and a vector asserts exactly that.
|
|
793
|
+
The production `scheduler` still reads `navigator.scheduling` behind a `typeof`
|
|
794
|
+
guard; that reference now injects Node's DOM-free `navigator` from
|
|
795
|
+
`@gjsify/node-globals`, so it no longer needs `--exclude-globals navigator`.
|
|
797
796
|
|
|
798
797
|
`react` and `react-reconciler` are OPTIONAL peer dependencies, like `solid-js` and
|
|
799
798
|
`@vue/runtime-core`.
|
|
@@ -838,6 +837,54 @@ host's own `coerce()` path. A member the installed library lacks is accepted onl
|
|
|
838
837
|
if the GIR says it arrived in a newer release — `GtkApplicationWindow::save-state`
|
|
839
838
|
is GTK 4.24 and the check runs on 4.22.4.
|
|
840
839
|
|
|
840
|
+
### A class the running GTK does not have
|
|
841
|
+
|
|
842
|
+
The table is generated from **one platform's GIR**, and a platform does not build every
|
|
843
|
+
class that GIR describes: GTK does not build its Unix print stack on Windows, so
|
|
844
|
+
`GtkPrintUnixDialog` and `GtkPageSetupUnixDialog` are rows whose class no Windows
|
|
845
|
+
`Gtk-4.0.typelib` registers (#1446 — six assertions of this suite failed on the first
|
|
846
|
+
GTK-bearing Windows leg, all of them this). The rows **stay**, for two measured
|
|
847
|
+
reasons. The GIR says they exist in that release, and the generator reads one GIR pool
|
|
848
|
+
with no second platform to compare against — a platform claim derived from a NAME
|
|
849
|
+
(`*Unix*`) breaks precisely when it matters, on the next absent class nobody spelled
|
|
850
|
+
that way, and a surface should not assert what it has not measured. And the two rows
|
|
851
|
+
are correct on the two platforms that do build them.
|
|
852
|
+
|
|
853
|
+
What the table must never do is hand a caller a class that resolved to `undefined`.
|
|
854
|
+
`classOf(descriptor)` is the one place that asks the only question answerable here — does
|
|
855
|
+
the **running** typelib have this class — and `requireClass(descriptor)` is that answer as
|
|
856
|
+
a named refusal (`err.absentClass`, code `absent-class`). Every read of a row's class
|
|
857
|
+
goes through it: `materialize`, `setProp`, `setEventHandler`, `setAccessibility`, the two
|
|
858
|
+
text-sink paths and the construction probe. So an omitted class is refused **by name at
|
|
859
|
+
the call that needed it**, instead of dying as
|
|
860
|
+
`Cannot read properties of undefined (reading 'list_properties')` or `… (reading '$gtype')`
|
|
861
|
+
— the two messages that arrived as six failures naming two classes between them.
|
|
862
|
+
|
|
863
|
+
A test that can only run where the defect is never runs, so the absent-class path is
|
|
864
|
+
**simulated** in `generated.spec.ts`: a descriptor whose `ctor()` answers `undefined` —
|
|
865
|
+
which is literally what `Gtk.PrintUnixDialog` is on a host that does not build it — driven
|
|
866
|
+
through every one of those paths, each expected to refuse with the same code and the
|
|
867
|
+
row's name. The sweeps that walk the whole table ask `classOf`/`hasClass` and treat an
|
|
868
|
+
absent row as *not a row*; `descriptorProblems()` says nothing about a class it cannot
|
|
869
|
+
resolve, and `explains every class the installed library does not have` is where an
|
|
870
|
+
absence is weighed against the library version **and printed by name** — the half that was
|
|
871
|
+
missing, and the reason those six took a hand to attribute.
|
|
872
|
+
|
|
873
|
+
The type surfaces (`generated/props.ts`) keep both dialogs, deliberately: they describe
|
|
874
|
+
the GIR's release, and `gjsify tsc` cannot check a type surface against an installed
|
|
875
|
+
typelib (rule 5 of the section above). A renderer on a platform that lacks the class meets
|
|
876
|
+
the runtime refusal at the call, not a compile error.
|
|
877
|
+
|
|
878
|
+
**The obvious oracle is wrong, and that is measured.** `GObject.type_from_name` is the
|
|
879
|
+
one-call version of "is this class installed" and it answers in the direction that costs
|
|
880
|
+
a *working* row: on gjs 1.88.1 / Homebrew GTK 4.24.0 `type_from_name('GtkPrintUnixDialog')`
|
|
881
|
+
answers **0** while `Gtk.PrintUnixDialog` is present and constructs — a typelib registers a
|
|
882
|
+
class when the namespace member is first **read**, not when the typelib loads. So a table
|
|
883
|
+
filtered by `type_from_name` drops two rows that are really there, on the platform that has
|
|
884
|
+
them. A row's own `ctor()` *is* that read, which is why it answers correctly in both
|
|
885
|
+
directions; an oracle over the whole table has to force the registration of every class it
|
|
886
|
+
walks, where a row is only ever asked about when something is about to use it.
|
|
887
|
+
|
|
841
888
|
### A base that leaves the namespace
|
|
842
889
|
|
|
843
890
|
The generator reads `@girs/<ns>/vocabulary` (ADR 0029) for Gtk and Adw — the only two that
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{adderSlots as
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{classOf as e}from"../registry.js";import{adderSlots as t,addressOf as n,classPlacementKind as r,isUnparented as i,placementOf as a,unhandledPlacement as o,unhandledPolicy as s}from"../policies.js";import{installAccessibilityBackend as c,withAtContext as l}from"./at-context.js";import{describeLogRecord as u,installDiagnosticsGate as d,isEnvironmentDiagnostic as f}from"./diagnostics.js";import{descendants as p,dumpTree as m,findDescendant as h,gtkChildTypes as g,gtkChildren as _}from"./tree.js";import{windowChromeCensus as v,windowChromeProblems as y}from"./window-chrome.js";import{buildSharedTree as b}from"./shared-tree-builder.js";import{BUILTIN_DESCRIPTORS as x}from"../descriptors/index.js";import S 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 s(e)}}function placementMethodsOf(e){switch(e.kind){case`parented`:return[];case`portal`:case`toplevel`:return[e.present,e.close];default:return o(e)}}function presentArityOf(e){switch(e.kind){case`parented`:return null;case`portal`:return 1;case`toplevel`:return 0;default:return o(e)}}function descriptorProblems(t=x){let n=[];for(let i of t){let t;try{t=e(i)}catch(e){n.push({gtype:i.gtype,problem:`ctor() threw: ${e.message}`});continue}if(!t)continue;let o=S.type_name(t.$gtype);o!==i.gtype&&n.push({gtype:i.gtype,problem:`ctor() is ${o}, not ${i.gtype}`});for(let e of methodsOf(i.children))typeof t.prototype[e]!=`function`&&n.push({gtype:i.gtype,problem:`declares children.${e}(), which ${o} does not have`});let s=a(i);for(let e of placementMethodsOf(s))typeof t.prototype[e]!=`function`&&n.push({gtype:i.gtype,problem:`declares placement.${e}(), which ${o} does not have`});let c=presentArityOf(s);if(c!==null&&s.kind!==`parented`){let e=t.prototype[s.present];typeof e==`function`&&e.length!==c&&n.push({gtype:i.gtype,problem:`placement.${s.present}() takes ${e.length} argument(s) on ${o}, and a ${s.kind} is presented with exactly ${c}`})}let l=t.prototype.present,u=r(t.$gtype,l);if(u&&s.kind===`parented`&&typeof l==`function`&&n.push({gtype:i.gtype,problem:u===`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', … }`}),i.textSink){let e=t.list_properties().find(e=>e.get_name()===i.textSink);e?(e.flags&S.ParamFlags.WRITABLE)===0?n.push({gtype:i.gtype,problem:`declares a READ-ONLY textSink "${i.textSink}"`}):S.type_is_a(e.value_type,S.TYPE_STRING)||n.push({gtype:i.gtype,problem:`declares textSink "${i.textSink}", which is ${S.type_name(e.value_type)}, not a string`}):n.push({gtype:i.gtype,problem:`declares textSink "${i.textSink}", which ${o} does not have`})}if(i.children.kind===`indexed`&&i.children.perLineCap!==void 0){let e=i.children.perLineCap,r=t.list_properties().find(t=>t.get_name()===e);r?(r.flags&S.ParamFlags.WRITABLE)===0?n.push({gtype:i.gtype,problem:`declares a READ-ONLY perLineCap "${e}"`}):S.type_is_a(r.value_type,S.TYPE_UINT)||n.push({gtype:i.gtype,problem:`declares perLineCap "${e}", which is ${S.type_name(r.value_type)}, not a count`}):n.push({gtype:i.gtype,problem:`declares perLineCap "${e}", which ${o} does not have`})}n.push(...policyProblems(i,t,o))}return n}function policyProblems(e,n,r){let i=[],a=n.prototype,o=e.children,requireGetter=(t,n)=>{let o=t.replace(/^set_/,`get_`);typeof a[o]!=`function`&&i.push({gtype:e.gtype,problem:`${n} uses ${t}() 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 t of Object.keys(o.wrapSlots??{}))t in o.slots||i.push({gtype:e.gtype,problem:`wrapSlots names "${t}", which is not one of ${Object.keys(o.slots).join(`, `)}`});o.defaultSlot in o.slots||i.push({gtype:e.gtype,problem:`defaultSlot "${o.defaultSlot}" is not one of ${Object.keys(o.slots).join(`, `)}`});let n=t(o);n.length>0&&!o.remove&&i.push({gtype:e.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:e.gtype,problem:`claims reorder: 'native' with no "after" method — reorderMode() would tell an adapter the wrong thing`}),o.kind===`keyed`){let t=a[o.add],n=o.titled?3:1;typeof t==`function`&&t.length!==n&&i.push({gtype:e.gtype,problem:`titled: ${o.titled} implies ${o.add}() takes ${n} argument(s), but ${r}'s takes ${t.length}`})}return i}function addressesOf(e){let t=[];for(let r=e.first;r;r=r.next)r.kind===`element`&&r.widget&&!i(r)&&t.push(n(r));return t}export{addressesOf,b as buildSharedTree,p as descendants,u as describeLogRecord,descriptorProblems,m as dumpTree,h as findDescendant,g as gtkChildTypes,_ as gtkChildren,c as installAccessibilityBackend,d as installDiagnosticsGate,f as isEnvironmentDiagnostic,methodsOf,placementMethodsOf,presentArityOf,v as windowChromeCensus,y as windowChromeProblems,l as withAtContext};
|
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.`),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};
|
|
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.`),absentClass:e=>new GtkHostError(`absent-class`,`<${e}> is in the widget table and the running GTK has no class for it. The table is generated from one GIR, on one host, and a platform omits what it does not build — GTK does not build its Unix print dialogs on Windows, so no typelib there registers them. Use a widget this GTK really has (the portable print dialog is GtkPrintDialog, not GtkPrintUnixDialog), and expect the same refusal for any class a future platform drops.`),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};
|
package/lib/esm/fonts.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{isFontFace as e,resolveFontSources as t}from"./font-dir.js";import{describeFontFamilyMatch as n,matchFontFamilies as r,matchFontFamily as i}from"./font-families.js";import{ADWAITA_UI_FONT_FAMILY as a,GNOME_UI_FONT_POINT_SIZE as o,UI_FONT_POLICIES as s,planUiFont as c,planUiFontPolicy as l}from"./ui-font.js";import u from"gi://Gtk?version=4.0";import d from"gi://Gio?version=2.0";import f from"gi://GLib?version=2.0";import p from"gi://PangoCairo?version=1.0";
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{isFontFace as e,resolveFontSources as t}from"./font-dir.js";import{describeFontFamilyMatch as n,matchFontFamilies as r,matchFontFamily as i}from"./font-families.js";import{ADWAITA_UI_FONT_FAMILY as a,GNOME_UI_FONT_POINT_SIZE as o,UI_FONT_POLICIES as s,planUiFont as c,planUiFontPolicy as l}from"./ui-font.js";import u from"gi://Gtk?version=4.0";import d from"gi://Gio?version=2.0";import f from"gi://GLib?version=2.0";import p from"gi://PangoCairo?version=1.0";import{CAIRO_FONT_TYPE_FT as m,fontErrorMessage as h,fontMapFamilies as g,isUnsupportedByFontMap as _,registerFontFaces as v}from"@gjsify/utils/font-map";function initFonts(e={}){let i=t({...e,env:{GJSIFY_FONT_DIR:f.getenv(`GJSIFY_FONT_DIR`)??void 0,GJSIFY_GTK_RUNTIME_FONT_DIR:f.getenv(`GJSIFY_GTK_RUNTIME_FONT_DIR`)??void 0}}),a=i.find(e=>e.origin===`app`)?.dir,o=[],s=[],c=[],l=[],u=[],m=e.expectedFamilies??[];if(i.length===0&&m.length===0)return{dir:a,sources:o,uiFont:void 0,registered:s,declined:c,unreachable:l,failed:u,families:[],matches:[],fontconfigFallback:!1};let h=[],_=p.FontMap.get_default(),y=i.map(e=>({source:e,registered:[],declined:[],unreachable:[],failed:[]})),b=!1;for(let e of y){let t=[];collectFaces(d.File.new_for_path(e.source.dir),t,e.failed);let n=v(t.sort(),_);(h.length===0||n.fontconfigFallback)&&(h=n.before),n.fontconfigFallback&&(b=!0),n.map!==void 0&&(_=n.map),e.registered.push(...n.registered),e.declined.push(...n.declined),e.unreachable.push(...n.unreachable),e.failed.push(...n.failed)}for(let e of y)s.push(...e.registered),c.push(...e.declined),l.push(...e.unreachable),u.push(...e.failed),o.push({...e.source,registered:e.registered,declined:e.declined,unreachable:e.unreachable,failed:e.failed});let x=g(_),S=i.length===0?[]:x.filter(e=>!h.includes(e)).sort(),C=r(m,x);captureUiFontBaseline();let w=e.uiFont===void 0?void 0:applyUiFontPolicy(e.uiFont);for(let e of u)console.warn(`initFonts: ${e.path} could not be read as an application font (${e.message}). Text asking for a family this application ships will render in a substituted one.`);for(let e of l)console.warn(`initFonts: ${e} is registered and its family is on the font map, but text asking for it will still render substituted: the font map had already resolved that family to the fallback and the cached answer cannot be invalidated. Call initFonts() before any text is laid out.`);for(let e of C)e.kind!==`exact`&&console.warn(`initFonts: ${n(e)}`);return{dir:a,sources:o,uiFont:w,registered:s,declined:c,unreachable:l,failed:u,families:S,matches:C,fontconfigFallback:b}}let y=!1,b;function captureUiFontBaseline(){if(y)return b;let e=u.Settings.get_default();if(e!==null)return b=e.gtk_font_name??void 0,y=!0,b}function uiFontBaseline(){return captureUiFontBaseline()}function applyUiFontPolicy(e){let t=typeof e==`string`?{policy:e}:e,n=t.settings===void 0?u.Settings.get_default():t.settings;if(n===null)return console.warn("applyUiFontPolicy: no Gtk.Settings — the toolkit is not initialised yet, so the policy was NOT applied. Call this after Gtk.init() (or from an application's `startup`), which is still before any window is built."),{next:void 0,kind:`uninitialised`,family:void 0,size:void 0};let r=captureUiFontBaseline(),i=l({...t,family:t.family??resolvedAdwaitaFamily(t.policy),current:n.gtk_font_name??void 0,baseline:r});return i.next===void 0||(n.gtk_font_name=i.next),i}function resolvedAdwaitaFamily(e){if(e!==`adwaita`)return;let t=adwaitaUiFontAvailability();if(t.match.family!==void 0)return t.match.family;console.warn(`applyUiFontPolicy: "${t.family}" is ${t.match.kind} on this font map, so asking for it will render in a substituted family. Register the runtime bundle's faces with initFonts() first, and check adwaitaUiFontAvailability() before offering this policy.`)}function adwaitaUiFontAvailability(e=a){let t=i(e,g(p.FontMap.get_default()));return{family:e,match:t,available:t.kind!==`absent`}}function collectFaces(t,n,r){try{let i=t.enumerate_children(`standard::name,standard::type`,d.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,null);for(let t=i.next_file(null);t!==null;t=i.next_file(null)){let a=i.get_child(t),o=a.get_path();o!==null&&(t.get_file_type()===d.FileType.DIRECTORY?collectFaces(a,n,r):e(t.get_name())&&n.push(o))}}catch(e){r.push({path:t.get_path()??``,message:h(e)})}}export{a as ADWAITA_UI_FONT_FAMILY,m as CAIRO_FONT_TYPE_FT,o as GNOME_UI_FONT_POINT_SIZE,s as UI_FONT_POLICIES,adwaitaUiFontAvailability,applyUiFontPolicy,n as describeFontFamilyMatch,initFonts,_ as isUnsupportedByFontMap,r as matchFontFamilies,i as matchFontFamily,c as planUiFont,l as planUiFontPolicy,t as resolveFontSources,uiFontBaseline};
|
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{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};
|
|
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{lookupWidget as r,nearestRegistered as i,requireClass as a}from"./registry.js";import{coerce as o,isConstructOnly as s,paramSpecs as c,removedValue as l,requireSpec as u,toPropertyName as d}from"./props.js";import{applyAccessibilityPlan as f,isAccessibleClass as p,planAccessibility as m}from"./accessibility.js";import{beginHostWrite as h,clearHandlers as g,endHostWrite as _,isEventProp as v,setHandler as y,toSignalName as b}from"./signals.js";import{addressOf as x,closeOutsideParent as S,detachOutsideParent as C,insertChild as w,isUnparented as T,makeDetachedContainer as E,makeWrapper as D,outsideParentOf as O,placeOutsideParent as k,refuseUnknownSlot as A,refuseUnparentable as j,removeChild as M,setterSlotOf as N,setterSlots as P,slotOccupant as F}from"./policies.js";import I from"gi://GObject?version=2.0";function createElement(e,t){let n={kind:`element`,descriptor:r(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?O(e.descriptor):null;t&&S(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=a(e.descriptor),r=c(n,e.descriptor.gtype),i={};for(let[t,n]of Object.entries(e.props))i[t]=o(u(r,e.descriptor.gtype,t),n,e.descriptor.gtype);h(null);try{e.widget=new n(i)}finally{_()}try{replayInto(e)}catch(t){g(e);for(let t of childSnapshot(e))t.kind===`element`&&t.attached&&(M(e,t),t.attached=!1);throw releaseWidget(e),t}return e.widget}function replayInto(e){for(let[t,n]of e.listeners)y(e,t,n);e.accessibility&&f(e.widget,m(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,r,i){if(v(t))return setEventHandler(e,t,r);if(t===`slot`)return setSlot(e,r);if(t===`accessibility`)return setAccessibility(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 f=d(t),p=u(c(a(e.descriptor),e.descriptor.gtype),e.descriptor.gtype,f),m=r==null,g=m?l(e.descriptor,p):o(p,r,e.descriptor.gtype);e.widget!==null&&takesAccessorRoute(g)&&!s(p)&&requireAccessor(e,e.widget,f);let y=f in e.props?e.props[f]:void 0;if(m?delete e.props[f]:e.props[f]=r,e.widget){if(s(p))return rebuild(e,f,y);h(e.widget);try{n(e.widget,accessorName(f),g)||writeProperty(e.widget,f,g)}finally{_()}}}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?y(e,t,n):n&&assertSignalExists(e,t),n?e.listeners.set(t,n):e.listeners.delete(t)}function assertSignalExists(e,n){let r=b(n,e.descriptor.eventAliases).split(`::`)[0],i=a(e.descriptor).$gtype;if(I.signal_lookup(r,i)===0)throw t.unknownSignal(e.descriptor.gtype,n,r)}function setAccessibility(e,n){let r=n??null,i=m(e.descriptor.gtype,e.accessibility,r);if(r!==null&&!p(a(e.descriptor)))throw t.notAccessible(e.descriptor.gtype);e.widget&&f(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){M(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){g(e);for(let t of childSnapshot(e))t.kind===`element`&&(M(e,t),t.attached=!1);r&&!O(e.descriptor)&&M(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&&!T(t)&&N(e,t)&&(yield t)}const holdsElementInSetterSlot=e=>!setterSlotChildren(e).next().done;function writeTextSink(e,n){let r=e.descriptor.textSink;if(!r)throw t.textNotAccepted(e.descriptor.gtype,n);materialize(e);let i=e.descriptor.children,s=i.kind===`single`?i.set:null;if(s&&!holdsOursInSlot(e,null)&&appOccupant(e.widget,e.descriptor,s))throw t.occupiedSlot(e.descriptor.gtype,`text`,s);let l=u(c(a(e.descriptor),e.descriptor.gtype),e.descriptor.gtype,r);h(e.widget);try{e.widget.set_property(r,o(l,n,e.descriptor.gtype))}finally{_()}e.props[r]=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=O(t.descriptor);if(n){t.attached=k(e,t,n);return}j(e,t),A(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||T(n)||(i=x(n),a+=1)}let o=[];for(let n of siblingsFrom(t.next,e))n.kind===`element`&&n.attached&&!T(n)&&o.push(n);w({parent:e,child:t,prevWidget:i,index:a,following:o}),t.attached=!0}function refuseOccupiedSlot(e,n){let r=N(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&&!T(n))return!0;return!1}function ensureWrapper(n,r){if(r.wrapper)return;let i;try{i=D(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?I.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)||F(e.widget,n.set))return;let r=t.replace(/-([a-z])/g,(e,t)=>t.toUpperCase()),i=e.props[t]??e.props[r];if(typeof i!=`string`||i===``)return;let s=u(c(a(e.descriptor),e.descriptor.gtype),e.descriptor.gtype,t);h(e.widget);try{e.widget.set_property(t,o(s,i,e.descriptor.gtype))}finally{_()}}function remove(e){let t=e.parent;if(!t&&e.kind===`element`){let t=O(e.descriptor);t&&(C(e,t),e.attached=!1)}t&&e.kind===`element`&&(M(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){g(e),e.listeners.clear()}function destroy(e){e.kind===`element`&&(destroyChildren(e),g(e),e.listeners.clear());let t=e.kind===`element`?O(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(E());function adopt(e){let n=e.constructor.$gtype,r=i(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=P(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=F(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=>I.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{
|
|
1
|
+
import{GtkHostError as e}from"./errors.js";import{assertInjective as t,tagOf as n}from"./tags.js";import{classOf as r,clearRegistry as i,hasClass as a,hasWidget as o,lookupWidget as s,nearestRegistered as c,registerWidget as l,registerWidgets as u,registeredTags as d,requireClass as f}from"./registry.js";import{constructOnlyNames as p,gtypeOfName as m,isConstructOnly as h,isWritable as g,lookupEnumNick as _,paramSpecs as v,toPropertyName as y}from"./props.js";import{isEventProp as b,toSignalName as x}from"./signals.js";import{addressOf as S,isPortal as C,placementOf as w,portalOf as T,reorderMode as E}from"./policies.js";import{adopt as D,createAnchor as O,createDetachedContainer as k,createElement as A,createText as j,destroy as M,destroyChildren as N,disconnectHandlers as P,firstChild as F,insert as I,isHostElement as L,isText as R,materialize as z,mountRoot as B,nextSibling as V,parentNode as H,prevSibling as U,remove as W,setElementText as G,setEventHandler as K,setProp as q,setSlot as J,setText as Y,widgetOf as X}from"./host.js";import{GENERATED_PROVENANCE as Z,GENERATED_WIDGETS as Q}from"./generated/widgets.js";import{GTK_DESCRIPTORS as $}from"./descriptors/gtk.js";import{ADW_DESCRIPTORS as ee}from"./descriptors/adw.js";import{BUILTIN_DESCRIPTORS as te,CURATED_DESCRIPTORS as ne,mergeGenerated as re,registerBuiltinWidgets as ie,tableProvenance as ae}from"./descriptors/index.js";import"./types.js";import{blankReason as oe,checkRendered as se,probeEnabled as ce,runHostProbe as le,runHostProbeApp as ue,shotEvidence as de}from"./probe.js";export{ee as ADW_DESCRIPTORS,te as BUILTIN_DESCRIPTORS,ne as CURATED_DESCRIPTORS,Z as GENERATED_PROVENANCE,Q as GENERATED_WIDGETS,$ as GTK_DESCRIPTORS,e as GtkHostError,S as addressOf,D as adopt,t as assertInjective,oe as blankReason,se as checkRendered,r as classOf,i as clearRegistry,p as constructOnlyNames,O as createAnchor,k as createDetachedContainer,A as createElement,j as createText,M as destroy,N as destroyChildren,P as disconnectHandlers,F as firstChild,m as gtypeOfName,a as hasClass,o as hasWidget,I as insert,h as isConstructOnly,b as isEventProp,L as isHostElement,C as isPortal,R as isText,g as isWritable,_ as lookupEnumNick,s as lookupWidget,z as materialize,re as mergeGenerated,B as mountRoot,c as nearestRegistered,V as nextSibling,v as paramSpecs,H as parentNode,w as placementOf,T as portalOf,U as prevSibling,ce as probeEnabled,ie as registerBuiltinWidgets,l as registerWidget,u as registerWidgets,d as registeredTags,W as remove,E as reorderMode,f as requireClass,le as runHostProbe,ue as runHostProbeApp,G as setElementText,K as setEventHandler,q as setProp,J as setSlot,Y as setText,de as shotEvidence,ae as tableProvenance,n as tagOf,y as toPropertyName,x as toSignalName,X as widgetOf};
|
package/lib/esm/props.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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
|
|
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{requireClass as s}from"./registry.js";import c from"gi://GObject?version=2.0";import l from"gi://Gtk?version=4.0";import u from"gi://Adw?version=1";import d from"gi://Gdk?version=4.0";import f from"gi://Gio?version=2.0";import p from"gi://Pango?version=1.0";const m=[[`Gtk`,l],[`Adw`,u],[`Gdk`,d],[`Pango`,p],[`G`,f],[`G`,c]];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 h=new Map;function paramSpecs(e,t){let n=h.get(t);if(n)return n;n=new Map;for(let t of e.list_properties())n.set(t.get_name(),t);return h.set(t,n),n}const isFlag=(e,t)=>(e&t)!==0,isWritable=e=>isFlag(e.flags,c.ParamFlags.WRITABLE),isConstructOnly=e=>isFlag(e.flags,c.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 m){if(!e.startsWith(t))continue;let r=n[e.slice(t.length)],i=r?.$gtype;if(!(!i||c.type_name(i)!==e))return r}}function gtypeOfName(e){return c.type_from_name(e)||giTypeObject(e)?.$gtype}let g;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(c.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}g??=new l.Builder;try{let[n,r]=g.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)},isEnumish=e=>c.type_is_a(e,c.TYPE_ENUM)||c.type_is_a(e,c.TYPE_FLAGS);function enumMembers(e){let t=giTypeObject(e),n=t?.$gtype;if(!(!n||!isEnumish(n)))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(s,u,d){if(u==null)return u;let p=s.value_type;if(c.type_is_a(p,f.MenuModel.$gtype)&&o(u))return a(u);if(c.type_is_a(p,f.ListModel.$gtype)&&!(u instanceof c.Object)){if(!i(u))throw e.badListModel(d,s.get_name(),kindOf(u));if(!c.type_is_a(l.StringList.$gtype,p))throw e.listModelMismatch(d,s.get_name(),c.type_name(p));return r(u)}if(c.type_is_a(p,l.Adjustment.$gtype)&&!(u instanceof c.Object)){if(!n(u))throw e.badAdjustment(d,s.get_name(),kindOf(u));return t(u)}if(c.type_is_a(p,c.TYPE_ENUM)&&typeof u==`string`){let t=parseNickText(p,u);if(t!==void 0)return t;throw e.badEnum(d,s.get_name(),u,c.type_name(p))}if(c.type_is_a(p,c.TYPE_FLAGS)&&typeof u==`string`){let t=c.type_name(p);if(hasBlankMember(u))throw e.blankFlags(d,s.get_name(),u,t);let n=parseNickText(p,u);if(n!==void 0)return n;throw e.badFlags(d,s.get_name(),u,t)}if(c.type_is_a(p,c.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(d,s.get_name(),u);return!!u}if(c.type_is_a(p,c.TYPE_STRING)){if(typeof u==`string`)return u;if(typeof u==`number`||typeof u==`boolean`)return String(u);throw e.badString(d,s.get_name(),typeof u)}return(c.type_is_a(p,c.TYPE_INT)||c.type_is_a(p,c.TYPE_UINT)||c.type_is_a(p,c.TYPE_INT64)||c.type_is_a(p,c.TYPE_UINT64))&&typeof u==`number`?Math.trunc(u):u}const _=[c.TYPE_BOOLEAN,c.TYPE_STRING,c.TYPE_INT,c.TYPE_UINT,c.TYPE_INT64,c.TYPE_UINT64,c.TYPE_DOUBLE,c.TYPE_FLOAT],isScalarSpec=e=>c.type_is_a(e.value_type,c.TYPE_ENUM)||_.some(t=>c.type_is_a(e.value_type,t)),toAccessorName=e=>e.replace(/-([a-z0-9])/g,(e,t)=>t.toUpperCase()),v=new Map;function constructedDefaults(e){let t=v.get(e.gtype);if(t)return t;let n=new Map;v.set(e.gtype,n);let r=s(e),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,c.ParamFlags.READABLE)||isFlag(a.flags,c.ParamFlags.DEPRECATED)||!isScalarSpec(a))continue;let e=toAccessorName(t);e in i&&n.set(t,i[e])}return i instanceof l.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,gtypeOfName,isConstructOnly,isWritable,lookupEnumNick,paramSpecs,removedValue,requireSpec,toPropertyName,withoutKeys};
|
package/lib/esm/registry.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{err as e}from"./errors.js";import{tagOf as t}from"./tags.js";import n from"gi://GObject?version=2.0";const r=new Map,i=new Map;function registerWidget(e){r.set(e.gtype,e);let n=t(e.gtype);n!==e.gtype&&i.set(n,e)}function registerWidgets(e){for(let t of e)registerWidget(t)}function lookupWidget(t){let n=r.get(t)??i.get(t);if(!n)throw e.unknownTag(t);return n}const hasWidget=e=>r.has(e)||i.has(e)
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{err as e}from"./errors.js";import{tagOf as t}from"./tags.js";import n from"gi://GObject?version=2.0";const r=new Map,i=new Map;function registerWidget(e){r.set(e.gtype,e);let n=t(e.gtype);n!==e.gtype&&i.set(n,e)}function registerWidgets(e){for(let t of e)registerWidget(t)}function lookupWidget(t){let n=r.get(t)??i.get(t);if(!n)throw e.unknownTag(t);return n}const hasWidget=e=>r.has(e)||i.has(e);function classOf(e){return e.ctor()??null}const hasClass=e=>classOf(e)!==null;function requireClass(t){let n=classOf(t);if(!n)throw e.absentClass(t.gtype);return n}const registeredTags=()=>[...r.keys()].sort();function nearestRegistered(e){for(let t=e;t;t=n.type_parent(t)){let e=n.type_name(t);if(!e)break;let i=r.get(e);if(i)return i}}function clearRegistry(){r.clear(),i.clear()}export{classOf,clearRegistry,hasClass,hasWidget,lookupWidget,nearestRegistered,registerWidget,registerWidgets,registeredTags,requireClass};
|
|
@@ -7,12 +7,10 @@ export type ReactProps = Record<string, unknown>;
|
|
|
7
7
|
/**
|
|
8
8
|
* The HostConfig, exported because it IS the contract.
|
|
9
9
|
*
|
|
10
|
-
* `react.spec.ts` builds a second reconciler over a Proxy of this object to read
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* configured reconciler (a `LegacyRoot`, a different event priority) without
|
|
15
|
-
* restating the mapping.
|
|
10
|
+
* `react.spec.ts` builds a second reconciler over a Proxy of this object to read the member set the
|
|
11
|
+
* INSTALLED `react-reconciler` asks for, so a version that starts asking for something new fails a
|
|
12
|
+
* test instead of returning `undefined` in a commit. It is also the seam for a consumer who needs
|
|
13
|
+
* a differently configured reconciler (a `LegacyRoot`, a different event priority).
|
|
16
14
|
*/
|
|
17
15
|
export declare const gtkHostConfig: {
|
|
18
16
|
supportsMutation: boolean;
|
|
@@ -31,15 +29,14 @@ export declare const gtkHostConfig: {
|
|
|
31
29
|
/**
|
|
32
30
|
* `false`, always — one text path instead of two.
|
|
33
31
|
*
|
|
34
|
-
* `true` would tell React to skip text instances for this element and leave
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* `
|
|
38
|
-
* `true` would move that decision into the adapter, where it would be a
|
|
32
|
+
* `true` would tell React to skip text instances for this element and leave the string in
|
|
33
|
+
* `props.children` for the adapter to write. The host already owns that translation: a text NODE
|
|
34
|
+
* is concatenated into the descriptor's `textSink`, and a widget without one refuses text BY
|
|
35
|
+
* TAG NAME. Answering `true` would move that decision into the adapter, where it would be a
|
|
39
36
|
* widget-knowledge test — the one thing ADR 0027 § 7 forbids an adapter.
|
|
40
37
|
*
|
|
41
|
-
* It also keeps `resetTextContent` unreachable: React sets the `ContentReset`
|
|
42
|
-
*
|
|
38
|
+
* It also keeps `resetTextContent` unreachable: React sets the `ContentReset` flag only when
|
|
39
|
+
* `shouldSetTextContent` was true for the PREVIOUS props.
|
|
43
40
|
*/
|
|
44
41
|
shouldSetTextContent: () => boolean;
|
|
45
42
|
getRootHostContext: () => object;
|
|
@@ -60,14 +57,11 @@ export declare const gtkHostConfig: {
|
|
|
60
57
|
/**
|
|
61
58
|
* The priority an update gets when React is not already inside a lane.
|
|
62
59
|
*
|
|
63
|
-
* React DOM derives this from the DOM event being handled (a click is
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* so it lands when `scheduler` next runs, i.e. on the next GLib main-loop
|
|
69
|
-
* iteration. `flushSync` is the escape hatch, and the spec pumps the main
|
|
70
|
-
* context to prove the scheduled path works at all under GJS.
|
|
60
|
+
* React DOM derives this from the DOM event being handled (a click is discrete, a scroll
|
|
61
|
+
* continuous). A GTK signal handler is not a DOM event and there is no ambient event to read, so
|
|
62
|
+
* every update is a default-lane one — the same answer `react-art` and `react-nil` give.
|
|
63
|
+
* Consequence, stated because it is load-bearing: a `setState` from a GTK handler is CONCURRENT,
|
|
64
|
+
* so it lands when `scheduler` next runs, i.e. on the next GLib main-loop iteration.
|
|
71
65
|
*/
|
|
72
66
|
resolveUpdatePriority: () => number;
|
|
73
67
|
shouldAttemptEagerTransition: () => boolean;
|
|
@@ -81,30 +75,21 @@ export declare const gtkHostConfig: {
|
|
|
81
75
|
removeChild: (_parent: HostElement, child: HostNode) => void;
|
|
82
76
|
removeChildFromContainer: (_container: HostElement, child: HostNode) => void;
|
|
83
77
|
/**
|
|
84
|
-
* React clears the root before its FIRST commit
|
|
85
|
-
*
|
|
78
|
+
* React clears the root before its FIRST commit, and the application's own chrome must survive it.
|
|
79
|
+
* In the DOM that discards leftover markup. Here the container is a widget the application
|
|
80
|
+
* built and filled, so this clears what the HOST put there (the shadow children) and never
|
|
81
|
+
* `el.foreign`, which `adopt` recorded precisely so placement can offset past it.
|
|
86
82
|
*
|
|
87
|
-
* `
|
|
88
|
-
*
|
|
89
|
-
* container. In the DOM that discards leftover markup. Here the container is a
|
|
90
|
-
* widget the application built and filled, so this clears what the HOST put
|
|
91
|
-
* there (the shadow children) and never `el.foreign`, which `adopt` recorded
|
|
92
|
-
* precisely so placement can offset past it.
|
|
93
|
-
*
|
|
94
|
-
* `destroy` rather than `remove`, for the same reason `removeChild` uses it:
|
|
95
|
-
* GJS blocks JS callbacks during GC, so a detached node keeps its handlers
|
|
96
|
-
* for the life of the process.
|
|
83
|
+
* `destroy` rather than `remove`, for the same reason `removeChild` uses it: GJS blocks JS
|
|
84
|
+
* callbacks during GC, so a detached node keeps its handlers for the life of the process.
|
|
97
85
|
*/
|
|
98
86
|
clearContainer: (container: HostElement) => void;
|
|
99
87
|
/**
|
|
100
88
|
* Diff AND apply — one phase, because React 19 deleted the other one.
|
|
101
89
|
*
|
|
102
|
-
* The argument list is the change with teeth: React
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* removed from the FRONT, so an adapter that kept the old signature would read
|
|
106
|
-
* the type string as its payload and iterate a string — which is why this is
|
|
107
|
-
* spelled out rather than left to positional luck.
|
|
90
|
+
* The argument list is the change with teeth: React 19 removed the `updatePayload` slot from the
|
|
91
|
+
* FRONT, so an adapter that kept the old signature would read the type string as its payload
|
|
92
|
+
* and iterate a string.
|
|
108
93
|
*/
|
|
109
94
|
commitUpdate: (instance: HostElement, _type: string, prevProps: ReactProps, nextProps: ReactProps) => void;
|
|
110
95
|
commitTextUpdate: (textInstance: HostText, _oldText: string, newText: string) => void;
|
package/lib/types/attrs.d.ts
CHANGED
|
@@ -7,31 +7,28 @@ import type { HostNode } from './types.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* A `notify::` handler.
|
|
9
9
|
*
|
|
10
|
-
* The host strips the emitting object
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* nothing to do with the GIR it read.
|
|
10
|
+
* The host strips the emitting object, so what reaches the callback is the ParamSpec alone. Declared
|
|
11
|
+
* HERE rather than in the generated file because it is the same for every property in GTK — and a
|
|
12
|
+
* generator that emitted it would have to import GObject for a type that has nothing to do with
|
|
13
|
+
* the GIR it read.
|
|
15
14
|
*/
|
|
16
15
|
export type NotifyHandler = (pspec: GObject.ParamSpec) => void;
|
|
17
16
|
declare const outParam: unique symbol;
|
|
18
17
|
/**
|
|
19
18
|
* A signal parameter GIR declares `out`/`inout` with `caller-allocates="0"`.
|
|
20
19
|
*
|
|
21
|
-
* GJS still passes an argument in that position, and what it holds is whatever
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* `
|
|
25
|
-
*
|
|
20
|
+
* GJS still passes an argument in that position, and what it holds is whatever was in the memory
|
|
21
|
+
* the marshaller allocated: measured on gjs 1.88.1 / GTK 4.22.4, a handler on
|
|
22
|
+
* `Gtk.SpinButton::input` receives `new_value` as `6.9526682391035e-310`, and one on
|
|
23
|
+
* `Gtk.Editable::insert-text` receives `position` as `1711500784`. Both arrive as ordinary numbers.
|
|
24
|
+
* Nothing warns.
|
|
26
25
|
*
|
|
27
|
-
* So the slot is DECLARED — dropping it would silently shift every parameter
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* naming the position, which is the only place a reader would have looked.
|
|
26
|
+
* So the slot is DECLARED — dropping it would silently shift every parameter after it — and given
|
|
27
|
+
* a type nothing can be read out of, and nothing but itself assigns to. Annotating the parameter
|
|
28
|
+
* `number` is then a compile error naming the position.
|
|
31
29
|
*
|
|
32
|
-
* `caller-allocates="1"` is a different thing and keeps its real type: there the
|
|
33
|
-
*
|
|
34
|
-
* is handed a `Gdk.Rectangle`.
|
|
30
|
+
* `caller-allocates="1"` is a different thing and keeps its real type: there the callee is handed
|
|
31
|
+
* a live object to FILL, as `Gtk.Overlay::get-child-position` is handed a `Gdk.Rectangle`.
|
|
35
32
|
*/
|
|
36
33
|
export type OutParam = {
|
|
37
34
|
readonly [outParam]: never;
|
|
@@ -39,10 +36,9 @@ export type OutParam = {
|
|
|
39
36
|
/**
|
|
40
37
|
* What may appear as a child, mirroring Solid's own `JSX.Element`.
|
|
41
38
|
*
|
|
42
|
-
* The shape is copied from `solid-js/types/jsx.d.ts` because a renderer's element
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* not. Substituting our host node for the DOM's `Node` is the only change.
|
|
39
|
+
* The shape is copied from `solid-js/types/jsx.d.ts` because a renderer's element union is not a free
|
|
40
|
+
* choice: a string, a number and a boolean are all legal children there, an array of children is
|
|
41
|
+
* legal recursively, and a FUNCTION is not.
|
|
46
42
|
*/
|
|
47
43
|
export type ElementChild = HostNode | ElementChildren | string | number | boolean | null | undefined;
|
|
48
44
|
export interface ElementChildren extends Array<ElementChild> {
|
|
@@ -50,10 +46,9 @@ export interface ElementChildren extends Array<ElementChild> {
|
|
|
50
46
|
/**
|
|
51
47
|
* Add the `.once` spelling of every event prop, without generating 2× the members.
|
|
52
48
|
*
|
|
53
|
-
* `signals.ts` accepts `onClickedOnce` for every `onClicked`, including every
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* declaration merging.
|
|
49
|
+
* `signals.ts` accepts `onClickedOnce` for every `onClicked`, including every `onNotifyFooOnce`,
|
|
50
|
+
* which would be another ~1000 generated members. A mapped type derives them from the interface
|
|
51
|
+
* instead — including the ones a consumer adds by declaration merging.
|
|
57
52
|
*/
|
|
58
53
|
export type WithOnce<T> = T & {
|
|
59
54
|
[K in keyof T & string as K extends `on${string}` ? `${K}Once` : never]?: T[K];
|
|
@@ -65,11 +60,11 @@ export interface SlotAttribute {
|
|
|
65
60
|
/**
|
|
66
61
|
* GTK's ARIA surface, on every element of every dialect. Read by `setAccessibility()`.
|
|
67
62
|
*
|
|
68
|
-
* ONE OBJECT, not 53 flat `aria*` props, and the four reasons are in `setAccessibility`'s
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
63
|
+
* ONE OBJECT, not 53 flat `aria*` props, and the four reasons are in `setAccessibility`'s own
|
|
64
|
+
* header — the load-bearing one being that TypeScript exempts a hyphenated JSX attribute from
|
|
65
|
+
* excess-property checking while a key in a fresh object literal is checked.
|
|
66
|
+
* `AccessibilityAttributes` is GENERATED, because the names and their value types are GTK's and are
|
|
67
|
+
* stated nowhere a ParamSpec can be read from.
|
|
73
68
|
*/
|
|
74
69
|
export interface AccessibilityAttribute {
|
|
75
70
|
accessibility?: AccessibilityAttributes | null;
|
|
@@ -77,12 +72,10 @@ export interface AccessibilityAttribute {
|
|
|
77
72
|
/**
|
|
78
73
|
* The `on:<raw-signal-name>` escape hatch, typed.
|
|
79
74
|
*
|
|
80
|
-
* `parseEventProp` takes `on:` + a signal name verbatim, which is how a signal
|
|
81
|
-
*
|
|
82
|
-
* is
|
|
83
|
-
*
|
|
84
|
-
* An inline arrow's parameter arrives as `never` here, which is the price of an
|
|
85
|
-
* escape hatch that carries no signal-specific knowledge.
|
|
75
|
+
* `parseEventProp` takes `on:` + a signal name verbatim, which is how a signal whose name resists
|
|
76
|
+
* the camelCase derivation gets bound at all. The handler type is deliberately the widest one that
|
|
77
|
+
* is not `any`: parameters of `never` accept a handler declared with any parameters, so nothing a
|
|
78
|
+
* consumer writes is refused.
|
|
86
79
|
*/
|
|
87
80
|
export interface RawSignalAttributes {
|
|
88
81
|
[key: `on:${string}`]: ((...args: never[]) => unknown) | undefined;
|
|
@@ -107,25 +100,20 @@ export interface JsxAttributes<T> extends AccessibilityAttribute, SlotAttribute,
|
|
|
107
100
|
/**
|
|
108
101
|
* Per-element attributes for Vue.
|
|
109
102
|
*
|
|
110
|
-
* Deliberately NOT `JsxAttributes`: Vue supplies `ref` and `key` itself through
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* leave the property unusable, so the Vue surface adds only what Vue does not —
|
|
114
|
-
* and `children` is a SLOT in Vue, never a prop.
|
|
103
|
+
* Deliberately NOT `JsxAttributes`: Vue supplies `ref` and `key` itself through `VNodeProps`, which
|
|
104
|
+
* every registered component's props are intersected with. Declaring our own `ref` would intersect
|
|
105
|
+
* two different `ref` types and could leave the property unusable.
|
|
115
106
|
*/
|
|
116
107
|
export interface VueAttributes extends AccessibilityAttribute, SlotAttribute, RawSignalAttributes {
|
|
117
108
|
}
|
|
118
109
|
/**
|
|
119
110
|
* The properties whose GObject type is a `GMenuModel`, in both spellings.
|
|
120
111
|
*
|
|
121
|
-
* A NAME LIST, not a type test, and the reason is measured
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* buttons, the popover menu and the menu bar; `extra-menu` on the text widgets;
|
|
127
|
-
* `secondary-menu` on `AdwToolbarView`'s header bar), and `type-tests/` holds the
|
|
128
|
-
* widening against real markup in both dialects.
|
|
112
|
+
* A NAME LIST, not a type test, and the reason is measured: the obvious `Gio.MenuModel extends
|
|
113
|
+
* NonNullable<T[K]> ? …` also matches every property typed as a wider GObject — `Gio.MenuModel
|
|
114
|
+
* extends GObject.Object` is TRUE — so the widening would leak onto properties that take an
|
|
115
|
+
* entirely different object. The names below are the whole set on the shipped table, and
|
|
116
|
+
* `type-tests/` holds the widening against real markup in both dialects.
|
|
129
117
|
*/
|
|
130
118
|
type MenuModelProp = 'menuModel' | 'menu-model' | 'extraMenu' | 'extra-menu' | 'secondaryMenu' | 'secondary-menu';
|
|
131
119
|
/**
|
package/lib/types/errors.d.ts
CHANGED
|
@@ -16,6 +16,25 @@ export declare class GtkHostError extends Error {
|
|
|
16
16
|
}
|
|
17
17
|
export declare const err: {
|
|
18
18
|
unknownTag: (tag: string) => GtkHostError;
|
|
19
|
+
/**
|
|
20
|
+
* A row of the table naming a class the RUNNING typelib does not carry.
|
|
21
|
+
*
|
|
22
|
+
* The one absence a version cannot explain. The table is generated from one
|
|
23
|
+
* platform's GIR, and a platform does not BUILD every class GTK describes:
|
|
24
|
+
* the Unix print stack is `#ifdef`-ed out on Windows, so its two dialogs are
|
|
25
|
+
* in the GIR and in no `Gtk-4.0.typelib` that a Windows build produces. The
|
|
26
|
+
* generated half is a claim about a library release, not about this host, so
|
|
27
|
+
* the row is right and the class is not here — and `GtkPageSetupUnixDialog`
|
|
28
|
+
* is NOT the whole shape of the failure, because the next absent class is not
|
|
29
|
+
* spelled "Unix" either.
|
|
30
|
+
*
|
|
31
|
+
* So nothing in this host dereferences a row's class before asking: the
|
|
32
|
+
* refusal names the tag instead of letting `undefined.list_properties()` or
|
|
33
|
+
* `undefined.$gtype` report a defect against whatever row the caller happened
|
|
34
|
+
* to be walking. Same shape as `unknownTag` — a tag this process cannot
|
|
35
|
+
* honour is refused BY NAME, because GTK's own failure mode here is silence.
|
|
36
|
+
*/
|
|
37
|
+
absentClass: (gtype: string) => GtkHostError;
|
|
19
38
|
missingConstructProp: (tag: string, prop: string) => GtkHostError;
|
|
20
39
|
unknownProp: (tag: string, prop: string) => GtkHostError;
|
|
21
40
|
readOnlyProp: (tag: string, prop: string) => GtkHostError;
|