@gjsify/adwaita-nativescript 0.64.12-next.281 → 0.64.13-next.283

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 (33) hide show
  1. package/lib/esm/builder/index.js +1 -1
  2. package/lib/esm/namespace/gdk.js +1 -1
  3. package/lib/esm/namespace/gobject.js +1 -1
  4. package/lib/esm/widgets/adw-action-row.js +1 -1
  5. package/lib/esm/widgets/adw-combo-row.js +1 -1
  6. package/lib/esm/widgets/adw-split-button.js +1 -1
  7. package/lib/esm/widgets/gtk-drop-down.js +1 -1
  8. package/lib/esm/widgets/gtk-label.js +2 -2
  9. package/lib/esm/widgets/gtk-window.js +1 -1
  10. package/lib/esm/widgets/label-markup.js +1 -0
  11. package/lib/esm/widgets/signals.js +1 -1
  12. package/lib/esm/window-host.js +1 -1
  13. package/lib/esm/window-source.android.js +1 -1
  14. package/lib/esm/window-source.ios.js +1 -1
  15. package/lib/esm/window-source.js +1 -1
  16. package/lib/types/builder/index.d.ts +4 -2
  17. package/lib/types/default-translate.spec.d.ts +1 -0
  18. package/lib/types/label-markup.spec.d.ts +1 -0
  19. package/lib/types/namespace/gdk.d.ts +1 -1
  20. package/lib/types/testing/ns-core.d.mts +91 -1
  21. package/lib/types/widgets/adw-banner.d.ts +2 -2
  22. package/lib/types/widgets/adw-combo-row.d.ts +32 -8
  23. package/lib/types/widgets/construct-props.d.ts +22 -16
  24. package/lib/types/widgets/gtk-drop-down.d.ts +29 -6
  25. package/lib/types/widgets/gtk-label.d.ts +29 -8
  26. package/lib/types/widgets/gtk-window.d.ts +8 -1
  27. package/lib/types/widgets/label-markup.d.ts +43 -0
  28. package/lib/types/widgets/signals.d.ts +42 -5
  29. package/lib/types/window-source.android.d.ts +1 -1
  30. package/lib/types/window-source.d.ts +7 -2
  31. package/lib/types/window-source.ios.d.ts +1 -1
  32. package/package.json +13 -13
  33. package/src/testing/ns-core.mts +176 -1
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{capabilities as e}from"../capabilities.js";import{observeWindowSize as t}from"../widgets/breakpoint.js";import{gtypeNameOf as n,gtypeNameOfInstance as r}from"../widgets/gtype-name.js";import{declaredBuilderReferences as i,declaredBuilderSlots as a}from"../widgets/builder-slots.js";import{gtkPropertyRefusal as o,hasGtkProperty as s,readGtkProperty as c,writeGtkProperty as l}from"../widgets/shadowed-properties.js";import{emittedSignalsOf as u}from"../widgets/signals.js";import{authoredParamValue as d}from"./param-values.js";import{registerTemplateClass as f,templateClassFor as p}from"./template-classes.js";import{adw_exports as m}from"../namespace/adw.js";import{gtk_exports as h}from"../namespace/gtk.js";import{createBreakpointDriver as g,menuAssignments as _,parseBreakpointCondition as v}from"@gjsify/adwaita-core";import{assertTreeConstructs as y}from"@gjsify/adwaita-core/conformance";import{propertyOf as b}from"@gjsify/adwaita-core/tags";import{View as x}from"@nativescript/core";const S=[{prefix:`adw`,library:`Adw`,namespace:m},{prefix:`gtk`,library:`Gtk`,namespace:h}];function registerBarrel(e,t,n){let r=S.find(t=>t.prefix===e);if(r!==void 0&&r.library!==t)throw Error(`The prefix '${e}' already names \`${r.library}\`; it cannot also name \`${t}\`.`);r===void 0?S.push({prefix:e,library:t,namespace:n}):r.namespace=n}const C={GtkPopoverMenuBar:`Android has no menu-bar surface, and a row of PopupMenus would be a design choice, not GTK's widget (ADR 0097 § 2). Use a GtkMenuButton or a GtkPopoverMenu.`};function elementFor(e){let t=C[e];if(t!==void 0)throw Error(`\`${e}\` is refused on this port: ${t}`);let r=[...S].sort((e,t)=>t.library.length-e.library.length);for(let{prefix:t,library:i,namespace:a}of r){if(!e.startsWith(i))continue;let r=e.slice(i.length),o=a[r];if(typeof o!=`function`)throw Error(`Module '~/${t}' has no member for element '${t}:${r}' — the name \`${e}\` is authored in the shared corpus and this dialect cannot spell it. Give the widget a namespace member (ADR 0034 clause 2), or ledger the block as divergent.`);if(n(o)!==e)throw Error(`'${t}:${r}' resolves to class \`${n(o)}\`, not \`${e}\`. The corpus is authored in GIR class names and ADR 0034 clause 1 says a widget carries that name, so a barrel member bound to another class would build the wrong widget at exit 0.`);return{xmlName:`${t}:${r}`,ctor:o}}throw Error(`\`${e}\` starts with no library this dialect has a barrel for (${S.map(e=>e.prefix).join(`, `)}).`)}function elementOf(e){return e.extern===!0?{xmlName:`app:${e.tag}`,ctor:p(e.tag)}:elementFor(e.tag)}function translated(e,t,n){return n===void 0||e===void 0||typeof t!=`string`?t:e(t,n.context)}function build(e,t={}){refuseSiblings(e,`build`);let n=buildTree(e,t).root;if(!(n instanceof x))throw Error(`\`${e.tag}\` is not a widget, so a tree cannot root at it: there is nothing to show.`);return n}function buildDialog(e,t={}){refuseSiblings(e,`buildDialog`);let n=buildTree(e,t).root;if(n instanceof x||typeof n.present!=`function`)throw Error(`\`${e.tag}\` is not a dialog: it has no \`present()\`, so use \`build\` for it.`);return n}function buildWithSiblings(e,t={}){let n=buildTree(e,t,!0);if(!(n.root instanceof x))throw Error(`\`${e.tag}\` is not a widget, so a tree cannot root at it: there is nothing to show.`);return{root:n.root,siblings:n.siblings,objects:n.objects}}function buildInto(e,t,n={}){let r=elementOf(t);if(!(e instanceof r.ctor))throw Error(`\`buildInto\` was handed a ${e.constructor.name}, and the tree's root is \`${t.tag}\`: a template builds into an instance of the class it extends (<${r.xmlName}>).`);return buildTree(t,n,!0,e).objects}function refuseSiblings(e,t){if((e.siblings?.length??0)!==0)throw Error(`\`${e.tag}\` carries ${e.siblings.length} sibling object(s), and \`${t}\` returns one object so they would be built and lost. Use \`buildWithSiblings\`, which hands them back by id.`)}function buildTree(n,r,i=!1,a){y(`adwaita-nativescript`,e,n,Object.keys(T));let o={ids:new Map,pending:[],binds:[],breakpointHosts:[],observeSize:r.observeSize??t,menus:n.menus,scope:r.scope,template:r.template,translate:r.translate,values:i?new Map:void 0},s=buildNode(n,o,a),c=new Map;for(let e of n.siblings??[]){if(e.id===void 0)throw Error(`the sibling \`${e.tag}\` has no id, so nothing could ever ask for it: give it one in the .blp.`);c.set(e.id,buildNode(e,o))}for(let{view:e,element:t,prop:n,id:r}of o.pending){let i=o.ids.get(r);if(i===void 0)throw Error(`<${t.xmlName} ${n}="${r}"> names no object: nothing in this tree has the id '${r}', so \`${n}\` would be handed the string instead of the widget it refers to.`);l(e,n,i)}for(let e of o.binds)bindProperty(e,o);for(let e of o.breakpointHosts)bindBreakpoints(e,o);return{root:s,siblings:c,objects:new Map([...o.ids,...o.values??[]])}}function bindProperty(e,t){let{target:n,element:r,property:i,source:a,sourceProperty:d,flags:f}=e,p=`<${r.xmlName}> \`${i}: bind ${a}.${d}\``,m=t.template,h=a===`template`&&m!==void 0?m.instance:t.ids.get(a);if(h===void 0)throw Error(`${p} names no object: nothing in this tree has the id '${a}'.`);if(f.length>0&&m===void 0)throw Error(`${p} carries ${f.join(`, `)}: adwaita-nativescript binds the plain form only until each flag is verified against GObject.`);let g=b(d),_=b(i),v=u(h.constructor),y=`notify::${d}`;if(!s(h,g)||!v.includes(y))throw Error(`${p}: ${h.constructor.name} does not emit '${y}', so the target would follow the source once and never again. It emits: ${v.join(`, `)||`none`}.`);if(!s(n,_)){let e=o(n,_);throw Error(`${p}: the target has no property '${_}'.${e===null?``:` ${e}`}`)}if(m!==void 0){bindThroughEngine(m,{...e,from:h,where:p,notification:y});return}let follow=()=>l(n,_,c(h,g));follow(),h.connect(y,follow)}function engineFlags(e,t){for(let n of e)if(n!==`bidirectional`&&n!==`inverted`&&n!==`no-sync-create`)throw Error(`${t} carries the unknown flag '${n}'.`);let n=e.includes(`no-sync-create`)?[]:[`sync-create`];return e.includes(`bidirectional`)&&n.push(`bidirectional`),e.includes(`inverted`)&&n.push(`invert-boolean`),n}function viaProperties(e){let key=e=>typeof e==`string`?b(e):e;return new Proxy(e,{get(e,t){let n=typeof t==`string`&&s(e,key(t))?c(e,key(t)):Reflect.get(e,key(t));return typeof n==`function`?n.bind(e):n},set(e,t,n){return typeof t==`string`?(l(e,b(t),n),!0):Reflect.set(e,t,n)}})}function bindThroughEngine(e,t){let{target:n,from:r,property:i,sourceProperty:a,flags:o,where:s}=t,c=engineFlags(o,s),l=u(n.constructor);if(c.includes(`bidirectional`)&&!l.includes(`notify::${i}`))throw Error(`${s}: bidirectional, but ${n.constructor.name} does not emit 'notify::${i}', so the source would never follow the target back. It emits: ${l.join(`, `)||`none`}.`);e.bind(viaProperties(r),a,viaProperties(n),i,c)}function bindBreakpoints({view:e,element:t,node:n},r){if(!(e instanceof x))throw Error(`<${t.xmlName}> is not a view, so it has no size for a breakpoint to read.`);wireBreakpoints(t.xmlName,e,n.breakpoints??[],r.ids,r.observeSize,r.translate)}function applyBreakpoints(e,n,i,a={}){wireBreakpoints(r(e),e,n,new Map(Object.entries(i)),a.observeSize??t,a.translate)}function wireBreakpoints(e,t,n,r,i,a){let u=g(n.map(t=>{if(v(t.condition)===null)throw Error(`<${e}> \`condition ("${t.condition}")\` is not an Adwaita breakpoint condition.`);return{condition:t.condition,setters:t.setters.map(t=>{let n=r.get(t.object),i=`<${e}> breakpoint setter \`${t.object}.${t.property}\``;if(n===void 0)throw Error(`${i} names no object: nothing in this tree has the id '${t.object}'.`);if(!s(n,b(t.property))){let e=o(n,b(t.property));throw Error(`${i}: the target declares no '${b(t.property)}'.`+(e===null?``:` ${e}`))}let c=translated(a,t.value,t.translatable),l=d(n,b(t.property),c,i);return{object:n,property:t.property,value:{authored:l===null?String(c):l.value}}})}}),{read:(e,t)=>({original:c(e,b(t))}),write(e,t,n){let r=n;l(e,b(t),`authored`in r?r.authored:r.original)}});i(t,e=>u.evaluate(e))}function buildNode(e,t,n){let r=elementOf(e),i=n??new r.ctor,a=i instanceof x?buildView(e,r,i,t):buildValue(e,r,i,t);bindSignals(a,r,e,t);for(let[n,i]of Object.entries(e.bindings??{}))t.binds.push({target:a,element:r,property:n,source:i.source,sourceProperty:i.property,flags:i.flags??[]});e.breakpoints!==void 0&&t.breakpointHosts.push({view:a,element:r,node:e});for(let n of e.children??[]){let i=a;if(typeof i._addChildFromBuilder!=`function`)throw Error(`<${r.xmlName}> takes no XML child: \`${e.tag}\` has no \`_addChildFromBuilder\`, so the corpus nests a node this element cannot hold.`);let o=buildNode(n,t);applyLayout(n,o,r,e.tag),i._addChildFromBuilder(builderNameFor(r,e.tag,n),o)}return a}function bindSignals(e,t,n,r){if(n.signals===void 0)return;let i=u(t.ctor),a=e;for(let e of n.signals){let n=e.detail===void 0?e.name:`${e.name}::${e.detail}`;if(typeof a.connect!=`function`||!i.includes(n))throw Error(`<${t.xmlName}> declares no signal '${n}', so the handler '${e.handler}' would never run. It emits: ${i.join(`, `)||`none`}.`);let o=(e.flags??[]).filter(e=>r.template===void 0||e!==`swapped`);if(e.object!==void 0||o.length>0)throw Error(`the handler '${e.handler}' for '${n}' uses ${e.object===void 0?``:`an object `}${(e.flags??[]).join(`, `)}: adwaita-nativescript binds plain handlers only until each of those is verified against GTK.`);if(r.template!==void 0){a.connect(n,r.template.handler(e.handler,{flags:e.flags}));continue}let s=r.scope?.[e.handler];if(typeof s!=`function`)throw Error(`the tree binds the handler '${e.handler}' for '${n}', and the scope ${r.scope===void 0?"was not given (pass `scope`)":`has no such function`}.`);a.connect(n,(...e)=>s.apply(r.scope,e))}}const w={row:`row`,column:`column`,"row-span":`rowSpan`,"column-span":`columnSpan`};function applyLayout(e,t,n,r){if(e.layout!==void 0){if(typeof n.ctor.prototype.attach!=`function`)throw Error(`<${elementOf(e).xmlName}> authored layout (${Object.keys(e.layout).join(`, `)}) under \`${r}\`, which has no \`attach\`: this port's only layout manager is the grid, so the placement would be dropped.`);if(!(t instanceof x))throw Error(`\`${e.tag}\` is not a view, so it has no cell to place.`);for(let[n,r]of Object.entries(e.layout)){let i=w[n];if(i===void 0)throw Error(`layout \`${n}\` on \`${e.tag}\` reaches nothing: a grid child takes ${Object.keys(w).join(`, `)}.`);if(typeof r!=`number`||!Number.isInteger(r))throw Error(`layout \`${n}: ${String(r)}\` on \`${e.tag}\` is not a whole number.`);t[i]=r}}}function unknownProperty(e,t,n,r,i,a){let s=o(a,r);return Error(s===null?`<${e.xmlName} ${n}="${String(i)}"> reaches nothing: \`${t}\` declares no '${r}'. NativeScript's builder assigns it anyway, as a dead own-property at exit 0, so the attribute door cannot report this and the tree would render without it.`:`<${e.xmlName} ${n}="${String(i)}"> reaches nothing on \`${t}\`: ${s}`)}function buildView(e,t,n,r){if(e.page!==void 0)throw Error(`<${t.xmlName}> is a page (${JSON.stringify(e.page)}), and adwaita-nativescript builds no pages: there is no NS widget yet for Gtk.Notebook, and Gtk.StackPage is not on this branch.`);if(e.id!==void 0){if(r.ids.has(e.id)||r.values?.has(e.id))throw Error(`Two nodes of this tree carry the id '${e.id}'; GtkBuilder refuses a duplicate id.`);r.ids.set(e.id,n),n.id=e.id}let a=i(t.ctor);for(let[i,a]of _(e,r.menus)){let r=b(i);if(!s(n,r))throw unknownProperty(t,e.tag,i,r,i,n);l(n,r,a)}for(let[i,o]of Object.entries(e.props??{})){if(i===`menu-model`)continue;let c=b(i);if(!s(n,c))throw unknownProperty(t,e.tag,i,c,o,n);if(a.includes(c)){r.pending.push({view:n,element:t,prop:c,id:String(o)});continue}let u=translated(r.translate,o,e.translatable?.[i]),f=d(n,c,u,`<${t.xmlName} ${i}="${String(u)}">`);l(n,c,f===null?String(u):f.value)}if(e.styleClasses!==void 0&&e.styleClasses.length>0){if(!(`styleClasses`in n))throw Error(`<${t.xmlName}> takes no style classes: \`${e.tag}\` declares no 'styleClasses', so [${e.styleClasses.join(`, `)}] would be dropped.`);n.styleClasses=e.styleClasses.join(` `)}if(applyAccessibility(n,e,r),e.extensions?.strings!==void 0)throw Error(`<${t.xmlName}> takes no string-list items: \`${e.tag}\` is a widget, and only a list model holds them, so [${e.extensions.strings.map(e=>e.value).join(`, `)}] would be dropped.`);return applyResponses(n,t,e,r),n}const T={label:`accessibilityLabel`,description:`accessibilityHint`};function applyAccessibility(e,t,n){for(let[r,i]of Object.entries(t.accessibility??{}))e[T[r]]=String(translated(n.translate,i.value,i.translatable))}function buildValue(e,t,n,r){if(e.id!==void 0&&r.values===void 0)throw Error(`<${t.xmlName} id="${e.id}"> reaches nothing: \`${e.tag}\` is not a view, and \`getViewById\` walks views, so code beside the \`.blp\` could never look it up. \`buildWithSiblings\` hands every object back by id.`);if(e.styleClasses!==void 0&&e.styleClasses.length>0)throw Error(`<${t.xmlName}> takes no style classes: \`${e.tag}\` is not a widget, so [${e.styleClasses.join(`, `)}] would be dropped.`);if(e.accessibility!==void 0)throw Error(`<${t.xmlName}> takes no accessibility: \`${e.tag}\` is not a widget, so ${Object.keys(e.accessibility).join(`, `)} would be dropped.`);let i={};for(let[a,o]of _(e,r.menus)){let r=b(a);if(!s(n,r))throw unknownProperty(t,e.tag,a,r,a,n);i[r]=o}for(let[a,o]of Object.entries(e.props??{})){if(a===`menu-model`)continue;let c=b(a);if(!s(n,c))throw unknownProperty(t,e.tag,a,c,o,n);i[c]=translated(r.translate,o,e.translatable?.[a])}let a=e.extensions?.strings;if(a!==void 0){if(typeof n.append!=`function`)throw Error(`<${t.xmlName}> takes no string-list items: \`${e.tag}\` has no \`append\`, so [${a.map(e=>e.value).join(`, `)}] would be dropped.`);i.strings=a.map(e=>String(translated(r.translate,e.value,e.translatable)))}let o=new t.ctor(i);if(applyResponses(o,t,e,r),e.id!==void 0&&r.values!==void 0){if(r.values.has(e.id)||r.ids.has(e.id))throw Error(`Two nodes of this tree carry the id '${e.id}'; GtkBuilder refuses a duplicate id.`);r.values.set(e.id,o)}return o}function applyResponses(e,t,n,r){let i=e,a=n.extensions?.responses;if(a!==void 0){if(typeof i.add_response!=`function`)throw Error(`<${t.xmlName}> takes no responses: \`${n.tag}\` has no \`add_response\`, so [${a.map(e=>e.id).join(`, `)}] would be dropped.`);for(let{id:e,label:t,appearance:n,enabled:o,translatable:s}of a)i.add_response(e,String(translated(r.translate,t,s)),{...n===void 0?{}:{appearance:n},...o===void 0?{}:{enabled:o}})}}function builderNameFor(e,t,n){let r=elementOf(n);if(n.slot===void 0)return r.xmlName;let i=n.slot,o=a(e.ctor);if(o===null||!o.includes(i))throw Error(`<${e.xmlName}.${i}> reaches nothing: \`${t}\` declares no such builder slot, so NativeScript would hand <${r.xmlName}> to its fallback placement instead — at exit 0, in a cell the tree never asked for. Known slots: ${o===null||o.length===0?`none`:o.join(`, `)}.`);return i}export{applyBreakpoints,build,buildDialog,buildInto,buildWithSiblings,elementFor,registerBarrel,f as registerTemplateClass};
1
+ import"../_virtual/_rolldown/runtime.js";import{capabilities as e}from"../capabilities.js";import{observeWindowSize as t}from"../widgets/breakpoint.js";import{gtypeNameOf as n,gtypeNameOfInstance as r}from"../widgets/gtype-name.js";import{declaredBuilderReferences as i,declaredBuilderSlots as a}from"../widgets/builder-slots.js";import{gtkPropertyRefusal as o,hasGtkProperty as s,readGtkProperty as c,writeGtkProperty as l}from"../widgets/shadowed-properties.js";import{emittedSignalsOf as u}from"../widgets/signals.js";import{authoredParamValue as d}from"./param-values.js";import{registerTemplateClass as f,templateClassFor as p}from"./template-classes.js";import{adw_exports as m}from"../namespace/adw.js";import{gtk_exports as h}from"../namespace/gtk.js";import{createBreakpointDriver as g,menuAssignments as _,parseBreakpointCondition as v,registeredDefaultTranslate as y}from"@gjsify/adwaita-core";import{assertTreeConstructs as b}from"@gjsify/adwaita-core/conformance";import{propertyOf as x}from"@gjsify/adwaita-core/tags";import{View as S}from"@nativescript/core";const C=[{prefix:`adw`,library:`Adw`,namespace:m},{prefix:`gtk`,library:`Gtk`,namespace:h}];function registerBarrel(e,t,n){let r=C.find(t=>t.prefix===e);if(r!==void 0&&r.library!==t)throw Error(`The prefix '${e}' already names \`${r.library}\`; it cannot also name \`${t}\`.`);r===void 0?C.push({prefix:e,library:t,namespace:n}):r.namespace=n}const w={GtkPopoverMenuBar:`Android has no menu-bar surface, and a row of PopupMenus would be a design choice, not GTK's widget (ADR 0097 § 2). Use a GtkMenuButton or a GtkPopoverMenu.`};function elementFor(e){let t=w[e];if(t!==void 0)throw Error(`\`${e}\` is refused on this port: ${t}`);let r=[...C].sort((e,t)=>t.library.length-e.library.length);for(let{prefix:t,library:i,namespace:a}of r){if(!e.startsWith(i))continue;let r=e.slice(i.length),o=a[r];if(typeof o!=`function`)throw Error(`Module '~/${t}' has no member for element '${t}:${r}' — the name \`${e}\` is authored in the shared corpus and this dialect cannot spell it. Give the widget a namespace member (ADR 0034 clause 2), or ledger the block as divergent.`);if(n(o)!==e)throw Error(`'${t}:${r}' resolves to class \`${n(o)}\`, not \`${e}\`. The corpus is authored in GIR class names and ADR 0034 clause 1 says a widget carries that name, so a barrel member bound to another class would build the wrong widget at exit 0.`);return{xmlName:`${t}:${r}`,ctor:o}}throw Error(`\`${e}\` starts with no library this dialect has a barrel for (${C.map(e=>e.prefix).join(`, `)}).`)}function elementOf(e){return e.extern===!0?{xmlName:`app:${e.tag}`,ctor:p(e.tag)}:elementFor(e.tag)}function translated(e,t,n){return n===void 0||e===void 0||typeof t!=`string`?t:e(t,n.context)}function build(e,t={}){refuseSiblings(e,`build`);let n=buildTree(e,t).root;if(!(n instanceof S))throw Error(`\`${e.tag}\` is not a widget, so a tree cannot root at it: there is nothing to show.`);return n}function buildDialog(e,t={}){refuseSiblings(e,`buildDialog`);let n=buildTree(e,t).root;if(n instanceof S||typeof n.present!=`function`)throw Error(`\`${e.tag}\` is not a dialog: it has no \`present()\`, so use \`build\` for it.`);return n}function buildWithSiblings(e,t={}){let n=buildTree(e,t,!0);if(!(n.root instanceof S))throw Error(`\`${e.tag}\` is not a widget, so a tree cannot root at it: there is nothing to show.`);return{root:n.root,siblings:n.siblings,objects:n.objects}}function buildInto(e,t,n={}){let r=elementOf(t);if(!(e instanceof r.ctor))throw Error(`\`buildInto\` was handed a ${e.constructor.name}, and the tree's root is \`${t.tag}\`: a template builds into an instance of the class it extends (<${r.xmlName}>).`);return buildTree(t,n,!0,e).objects}function refuseSiblings(e,t){if((e.siblings?.length??0)!==0)throw Error(`\`${e.tag}\` carries ${e.siblings.length} sibling object(s), and \`${t}\` returns one object so they would be built and lost. Use \`buildWithSiblings\`, which hands them back by id.`)}function buildTree(n,r,i=!1,a){b(`adwaita-nativescript`,e,n,Object.keys(E));let o={ids:new Map,pending:[],binds:[],breakpointHosts:[],observeSize:r.observeSize??t,menus:n.menus,scope:r.scope,template:r.template,translate:r.translate??y(),values:i?new Map:void 0},s=buildNode(n,o,a),c=new Map;for(let e of n.siblings??[]){if(e.id===void 0)throw Error(`the sibling \`${e.tag}\` has no id, so nothing could ever ask for it: give it one in the .blp.`);c.set(e.id,buildNode(e,o))}for(let{view:e,element:t,prop:n,id:r}of o.pending){let i=o.ids.get(r);if(i===void 0)throw Error(`<${t.xmlName} ${n}="${r}"> names no object: nothing in this tree has the id '${r}', so \`${n}\` would be handed the string instead of the widget it refers to.`);l(e,n,i)}for(let e of o.binds)bindProperty(e,o);for(let e of o.breakpointHosts)bindBreakpoints(e,o);return{root:s,siblings:c,objects:new Map([...o.ids,...o.values??[]])}}function bindProperty(e,t){let{target:n,element:r,property:i,source:a,sourceProperty:d,flags:f}=e,p=`<${r.xmlName}> \`${i}: bind ${a}.${d}\``,m=t.template,h=a===`template`&&m!==void 0?m.instance:t.ids.get(a);if(h===void 0)throw Error(`${p} names no object: nothing in this tree has the id '${a}'.`);if(f.length>0&&m===void 0)throw Error(`${p} carries ${f.join(`, `)}: adwaita-nativescript binds the plain form only until each flag is verified against GObject.`);let g=x(d),_=x(i),v=u(h.constructor),y=`notify::${d}`;if(!s(h,g)||!v.includes(y))throw Error(`${p}: ${h.constructor.name} does not emit '${y}', so the target would follow the source once and never again. It emits: ${v.join(`, `)||`none`}.`);if(!s(n,_)){let e=o(n,_);throw Error(`${p}: the target has no property '${_}'.${e===null?``:` ${e}`}`)}if(m!==void 0){bindThroughEngine(m,{...e,from:h,where:p,notification:y});return}let follow=()=>l(n,_,c(h,g));follow(),h.connect(y,follow)}function engineFlags(e,t){for(let n of e)if(n!==`bidirectional`&&n!==`inverted`&&n!==`no-sync-create`)throw Error(`${t} carries the unknown flag '${n}'.`);let n=e.includes(`no-sync-create`)?[]:[`sync-create`];return e.includes(`bidirectional`)&&n.push(`bidirectional`),e.includes(`inverted`)&&n.push(`invert-boolean`),n}function viaProperties(e){let key=e=>typeof e==`string`?x(e):e;return new Proxy(e,{get(e,t){let n=typeof t==`string`&&s(e,key(t))?c(e,key(t)):Reflect.get(e,key(t));return typeof n==`function`?n.bind(e):n},set(e,t,n){return typeof t==`string`?(l(e,x(t),n),!0):Reflect.set(e,t,n)}})}function bindThroughEngine(e,t){let{target:n,from:r,property:i,sourceProperty:a,flags:o,where:s}=t,c=engineFlags(o,s),l=u(n.constructor);if(c.includes(`bidirectional`)&&!l.includes(`notify::${i}`))throw Error(`${s}: bidirectional, but ${n.constructor.name} does not emit 'notify::${i}', so the source would never follow the target back. It emits: ${l.join(`, `)||`none`}.`);e.bind(viaProperties(r),a,viaProperties(n),i,c)}function bindBreakpoints({view:e,element:t,node:n},r){if(!(e instanceof S))throw Error(`<${t.xmlName}> is not a view, so it has no size for a breakpoint to read.`);wireBreakpoints(t.xmlName,e,n.breakpoints??[],r.ids,r.observeSize,r.translate)}function applyBreakpoints(e,n,i,a={}){wireBreakpoints(r(e),e,n,new Map(Object.entries(i)),a.observeSize??t,a.translate??y())}function wireBreakpoints(e,t,n,r,i,a){let u=g(n.map(t=>{if(v(t.condition)===null)throw Error(`<${e}> \`condition ("${t.condition}")\` is not an Adwaita breakpoint condition.`);return{condition:t.condition,setters:t.setters.map(t=>{let n=r.get(t.object),i=`<${e}> breakpoint setter \`${t.object}.${t.property}\``;if(n===void 0)throw Error(`${i} names no object: nothing in this tree has the id '${t.object}'.`);if(!s(n,x(t.property))){let e=o(n,x(t.property));throw Error(`${i}: the target declares no '${x(t.property)}'.`+(e===null?``:` ${e}`))}let c=translated(a,t.value,t.translatable),l=d(n,x(t.property),c,i);return{object:n,property:t.property,value:{authored:l===null?String(c):l.value}}})}}),{read:(e,t)=>({original:c(e,x(t))}),write(e,t,n){let r=n;l(e,x(t),`authored`in r?r.authored:r.original)}});i(t,e=>u.evaluate(e))}function buildNode(e,t,n){let r=elementOf(e),i=n??new r.ctor,a=i instanceof S?buildView(e,r,i,t):buildValue(e,r,i,t);bindSignals(a,r,e,t);for(let[n,i]of Object.entries(e.bindings??{}))t.binds.push({target:a,element:r,property:n,source:i.source,sourceProperty:i.property,flags:i.flags??[]});e.breakpoints!==void 0&&t.breakpointHosts.push({view:a,element:r,node:e});for(let n of e.children??[]){let i=a;if(typeof i._addChildFromBuilder!=`function`)throw Error(`<${r.xmlName}> takes no XML child: \`${e.tag}\` has no \`_addChildFromBuilder\`, so the corpus nests a node this element cannot hold.`);let o=buildNode(n,t);applyLayout(n,o,r,e.tag),i._addChildFromBuilder(builderNameFor(r,e.tag,n),o)}return a}function bindSignals(e,t,n,r){if(n.signals===void 0)return;let i=u(t.ctor),a=e;for(let e of n.signals){let n=e.detail===void 0?e.name:`${e.name}::${e.detail}`;if(typeof a.connect!=`function`||!i.includes(n))throw Error(`<${t.xmlName}> declares no signal '${n}', so the handler '${e.handler}' would never run. It emits: ${i.join(`, `)||`none`}.`);let o=(e.flags??[]).filter(e=>r.template===void 0||e!==`swapped`);if(e.object!==void 0||o.length>0)throw Error(`the handler '${e.handler}' for '${n}' uses ${e.object===void 0?``:`an object `}${(e.flags??[]).join(`, `)}: adwaita-nativescript binds plain handlers only until each of those is verified against GTK.`);if(r.template!==void 0){a.connect(n,r.template.handler(e.handler,{flags:e.flags}));continue}let s=r.scope?.[e.handler];if(typeof s!=`function`)throw Error(`the tree binds the handler '${e.handler}' for '${n}', and the scope ${r.scope===void 0?"was not given (pass `scope`)":`has no such function`}.`);a.connect(n,(...e)=>s.apply(r.scope,e))}}const T={row:`row`,column:`column`,"row-span":`rowSpan`,"column-span":`columnSpan`};function applyLayout(e,t,n,r){if(e.layout!==void 0){if(typeof n.ctor.prototype.attach!=`function`)throw Error(`<${elementOf(e).xmlName}> authored layout (${Object.keys(e.layout).join(`, `)}) under \`${r}\`, which has no \`attach\`: this port's only layout manager is the grid, so the placement would be dropped.`);if(!(t instanceof S))throw Error(`\`${e.tag}\` is not a view, so it has no cell to place.`);for(let[n,r]of Object.entries(e.layout)){let i=T[n];if(i===void 0)throw Error(`layout \`${n}\` on \`${e.tag}\` reaches nothing: a grid child takes ${Object.keys(T).join(`, `)}.`);if(typeof r!=`number`||!Number.isInteger(r))throw Error(`layout \`${n}: ${String(r)}\` on \`${e.tag}\` is not a whole number.`);t[i]=r}}}function unknownProperty(e,t,n,r,i,a){let s=o(a,r);return Error(s===null?`<${e.xmlName} ${n}="${String(i)}"> reaches nothing: \`${t}\` declares no '${r}'. NativeScript's builder assigns it anyway, as a dead own-property at exit 0, so the attribute door cannot report this and the tree would render without it.`:`<${e.xmlName} ${n}="${String(i)}"> reaches nothing on \`${t}\`: ${s}`)}function buildView(e,t,n,r){if(e.page!==void 0)throw Error(`<${t.xmlName}> is a page (${JSON.stringify(e.page)}), and adwaita-nativescript builds no pages: there is no NS widget yet for Gtk.Notebook, and Gtk.StackPage is not on this branch.`);if(e.id!==void 0){if(r.ids.has(e.id)||r.values?.has(e.id))throw Error(`Two nodes of this tree carry the id '${e.id}'; GtkBuilder refuses a duplicate id.`);r.ids.set(e.id,n),n.id=e.id}let a=i(t.ctor);for(let[i,a]of _(e,r.menus)){let r=x(i);if(!s(n,r))throw unknownProperty(t,e.tag,i,r,i,n);l(n,r,a)}for(let[i,o]of Object.entries(e.props??{})){if(i===`menu-model`)continue;let c=x(i);if(!s(n,c))throw unknownProperty(t,e.tag,i,c,o,n);if(a.includes(c)){r.pending.push({view:n,element:t,prop:c,id:String(o)});continue}let u=translated(r.translate,o,e.translatable?.[i]),f=d(n,c,u,`<${t.xmlName} ${i}="${String(u)}">`);l(n,c,f===null?String(u):f.value)}if(e.styleClasses!==void 0&&e.styleClasses.length>0){if(!(`styleClasses`in n))throw Error(`<${t.xmlName}> takes no style classes: \`${e.tag}\` declares no 'styleClasses', so [${e.styleClasses.join(`, `)}] would be dropped.`);n.styleClasses=e.styleClasses.join(` `)}if(applyAccessibility(n,e,r),e.extensions?.strings!==void 0)throw Error(`<${t.xmlName}> takes no string-list items: \`${e.tag}\` is a widget, and only a list model holds them, so [${e.extensions.strings.map(e=>e.value).join(`, `)}] would be dropped.`);return applyResponses(n,t,e,r),n}const E={label:`accessibilityLabel`,description:`accessibilityHint`};function applyAccessibility(e,t,n){for(let[r,i]of Object.entries(t.accessibility??{}))e[E[r]]=String(translated(n.translate,i.value,i.translatable))}function buildValue(e,t,n,r){if(e.id!==void 0&&r.values===void 0)throw Error(`<${t.xmlName} id="${e.id}"> reaches nothing: \`${e.tag}\` is not a view, and \`getViewById\` walks views, so code beside the \`.blp\` could never look it up. \`buildWithSiblings\` hands every object back by id.`);if(e.styleClasses!==void 0&&e.styleClasses.length>0)throw Error(`<${t.xmlName}> takes no style classes: \`${e.tag}\` is not a widget, so [${e.styleClasses.join(`, `)}] would be dropped.`);if(e.accessibility!==void 0)throw Error(`<${t.xmlName}> takes no accessibility: \`${e.tag}\` is not a widget, so ${Object.keys(e.accessibility).join(`, `)} would be dropped.`);let i={};for(let[a,o]of _(e,r.menus)){let r=x(a);if(!s(n,r))throw unknownProperty(t,e.tag,a,r,a,n);i[r]=o}for(let[a,o]of Object.entries(e.props??{})){if(a===`menu-model`)continue;let c=x(a);if(!s(n,c))throw unknownProperty(t,e.tag,a,c,o,n);i[c]=translated(r.translate,o,e.translatable?.[a])}let a=e.extensions?.strings;if(a!==void 0){if(typeof n.append!=`function`)throw Error(`<${t.xmlName}> takes no string-list items: \`${e.tag}\` has no \`append\`, so [${a.map(e=>e.value).join(`, `)}] would be dropped.`);i.strings=a.map(e=>String(translated(r.translate,e.value,e.translatable)))}let o=new t.ctor(i);if(applyResponses(o,t,e,r),e.id!==void 0&&r.values!==void 0){if(r.values.has(e.id)||r.ids.has(e.id))throw Error(`Two nodes of this tree carry the id '${e.id}'; GtkBuilder refuses a duplicate id.`);r.values.set(e.id,o)}return o}function applyResponses(e,t,n,r){let i=e,a=n.extensions?.responses;if(a!==void 0){if(typeof i.add_response!=`function`)throw Error(`<${t.xmlName}> takes no responses: \`${n.tag}\` has no \`add_response\`, so [${a.map(e=>e.id).join(`, `)}] would be dropped.`);for(let{id:e,label:t,appearance:n,enabled:o,translatable:s}of a)i.add_response(e,String(translated(r.translate,t,s)),{...n===void 0?{}:{appearance:n},...o===void 0?{}:{enabled:o}})}}function builderNameFor(e,t,n){let r=elementOf(n);if(n.slot===void 0)return r.xmlName;let i=n.slot,o=a(e.ctor);if(o===null||!o.includes(i))throw Error(`<${e.xmlName}.${i}> reaches nothing: \`${t}\` declares no such builder slot, so NativeScript would hand <${r.xmlName}> to its fallback placement instead — at exit 0, in a cell the tree never asked for. Known slots: ${o===null||o.length===0?`none`:o.join(`, `)}.`);return i}export{applyBreakpoints,build,buildDialog,buildInto,buildWithSiblings,elementFor,registerBarrel,f as registerTemplateClass};
@@ -1 +1 @@
1
- import{__exportAll as e}from"../_virtual/_rolldown/runtime.js";import{nativeClipboardHost as t}from"../clipboard-host.js";import{CURRENT_TIME as n,GDK_KEYS as r,RGBA as i,createGdk as a}from"@gjsify/adwaita-core";var o=e({AppLaunchContext:()=>f,CURRENT_TIME:()=>p,Clipboard:()=>l,ContentFormats:()=>d,ContentProvider:()=>u,Display:()=>c,KEY_Down:()=>E,KEY_Escape:()=>S,KEY_Left:()=>C,KEY_Return:()=>x,KEY_Right:()=>T,KEY_Up:()=>w,KEY_a:()=>h,KEY_d:()=>g,KEY_e:()=>_,KEY_q:()=>v,KEY_s:()=>y,KEY_space:()=>m,KEY_w:()=>b,RGBA:()=>i,gdk:()=>s});const s=a(t),c=s.Display,l=s.Clipboard,u=s.ContentProvider,d=s.ContentFormats,f=s.AppLaunchContext,p=n,{KEY_space:m,KEY_a:h,KEY_d:g,KEY_e:_,KEY_q:v,KEY_s:y,KEY_w:b,KEY_Return:x,KEY_Escape:S,KEY_Left:C,KEY_Up:w,KEY_Right:T,KEY_Down:E}=r;export{f as AppLaunchContext,p as CURRENT_TIME,l as Clipboard,d as ContentFormats,u as ContentProvider,c as Display,E as KEY_Down,S as KEY_Escape,C as KEY_Left,x as KEY_Return,T as KEY_Right,w as KEY_Up,h as KEY_a,g as KEY_d,_ as KEY_e,v as KEY_q,y as KEY_s,m as KEY_space,b as KEY_w,i as RGBA,s as gdk,o as gdk_exports};
1
+ import{__exportAll as e}from"../_virtual/_rolldown/runtime.js";import{nativeClipboardHost as t}from"../clipboard-host.js";import{CURRENT_TIME as n,GDK_KEYS as r,RGBA as i,createGdk as a}from"@gjsify/adwaita-core";var o=e({AppLaunchContext:()=>f,CURRENT_TIME:()=>p,Clipboard:()=>l,ContentFormats:()=>d,ContentProvider:()=>u,Display:()=>c,KEY_Back:()=>D,KEY_Down:()=>E,KEY_Escape:()=>S,KEY_Left:()=>C,KEY_Return:()=>x,KEY_Right:()=>T,KEY_Up:()=>w,KEY_a:()=>h,KEY_d:()=>g,KEY_e:()=>_,KEY_q:()=>v,KEY_s:()=>y,KEY_space:()=>m,KEY_w:()=>b,RGBA:()=>i,gdk:()=>s});const s=a(t),c=s.Display,l=s.Clipboard,u=s.ContentProvider,d=s.ContentFormats,f=s.AppLaunchContext,p=n,{KEY_space:m,KEY_a:h,KEY_d:g,KEY_e:_,KEY_q:v,KEY_s:y,KEY_w:b,KEY_Return:x,KEY_Escape:S,KEY_Left:C,KEY_Up:w,KEY_Right:T,KEY_Down:E,KEY_Back:D}=r;export{f as AppLaunchContext,p as CURRENT_TIME,l as Clipboard,d as ContentFormats,u as ContentProvider,c as Display,D as KEY_Back,E as KEY_Down,S as KEY_Escape,C as KEY_Left,x as KEY_Return,T as KEY_Right,w as KEY_Up,h as KEY_a,g as KEY_d,_ as KEY_e,v as KEY_q,y as KEY_s,m as KEY_space,b as KEY_w,i as RGBA,s as gdk,o as gdk_exports};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{ENGINE_TARGET as e}from"../engine-target.js";import{applyConstructProps as t}from"../widgets/construct-props.js";import{WIDGET_SIGNALS as n,watchMapping as r}from"../widgets/widget-mapping.js";import{emittedSignalsOf as i}from"../widgets/signals.js";import{registerTemplateClass as a}from"../builder/template-classes.js";import{nativePlatformHost as o}from"../platform-host.js";import{buildInto as s}from"../builder/index.js";import{gdk as c}from"./gdk.js";import{GObjectObject as l,connectInstance as u,constructRegistered as d,createGObject as f,disconnectInstance as p,emitInstance as m,engineForTarget as h,notifyInstance as g,registeredClassOf as _,widgetControllerMembers as v,widgetDisplayMembers as y}from"@gjsify/adwaita-core";function nearestRegistered(e){for(let t=e;typeof t==`function`;t=Object.getPrototypeOf(t))if(_(t)!==void 0)return t}function declareEmitted(e,t){let n=i(e),r=[...t.properties.map(e=>`notify::${e.name}`),...Object.keys(t.signals)];Object.defineProperty(e,"emittedSignals",{value:[...new Set([...n,...r])],enumerable:!1,configurable:!0,writable:!0})}function spliceLayer(e){let n=Object.getPrototypeOf(e),r=n.prototype.notify;class Registered extends n{constructor(n){if(super(),nearestRegistered(new.target)!==e)return;let r=d(this,n);t(this,r)}}let i={connect(e,t){return u(this,e,t)},disconnect(e){p(this,e)},emit(e,...t){m(this,e,...t)},notify(e){typeof e==`string`?g(this,e):r.call(this,e)}};for(let[e,t]of Object.entries({...y(c),...v(o)}))e in n.prototype||(i[e]=t);for(let[e,t]of Object.entries(i))Object.defineProperty(Registered.prototype,e,{value:t,writable:!0,configurable:!0,enumerable:!1});Object.setPrototypeOf(e,Registered),Object.setPrototypeOf(e.prototype,Registered.prototype)}const{engineName:b,Object:x,registerClass:S,ParamSpec:C,ParamFlags:w,Value:T,TYPE_STRING:E,TYPE_BOOLEAN:D,TYPE_INT:O,TYPE_UINT:k,TYPE_DOUBLE:A,GTypeName:j,GTypeFlags:M,interfaces:N,properties:P,signals:F,requires:I,__gtkTemplate__:L,__gtkCssName__:R,__gtkChildren__:z,__gtkInternalChildren__:B,type_ensure:V,signal_stop_emission_by_name:H}=f({name:`adwaita-nativescript`,dispatch(e,t,n){e.notify({eventName:t,object:e,args:n})},listen(e,t,i){let listener=t=>{i(e,t)},a=n.includes(t)?r(e):void 0;return e.addEventListener(t,listener),()=>{e.removeEventListener(t,listener),a?.()}},createFromTree(e,t,n){let r=s(n,e,{template:t});return{children:[],objects:Object.fromEntries(r)}},attach(e,t){},register(e,t){declareEmitted(e,t),!(e.prototype instanceof l)&&(spliceLayer(e),a(t.typeName,e))}},h(e));export{M as GTypeFlags,j as GTypeName,x as Object,w as ParamFlags,C as ParamSpec,D as TYPE_BOOLEAN,A as TYPE_DOUBLE,O as TYPE_INT,E as TYPE_STRING,k as TYPE_UINT,T as Value,z as __gtkChildren__,R as __gtkCssName__,B as __gtkInternalChildren__,L as __gtkTemplate__,b as engineName,N as interfaces,P as properties,S as registerClass,I as requires,H as signal_stop_emission_by_name,F as signals,V as type_ensure};
1
+ import"../_virtual/_rolldown/runtime.js";import{ENGINE_TARGET as e}from"../engine-target.js";import{applyConstructProps as t}from"../widgets/construct-props.js";import{WIDGET_SIGNALS as n,watchMapping as r}from"../widgets/widget-mapping.js";import{emittedSignalsOf as i}from"../widgets/signals.js";import{registerTemplateClass as a}from"../builder/template-classes.js";import{nativePlatformHost as o}from"../platform-host.js";import{buildInto as s}from"../builder/index.js";import{gdk as c}from"./gdk.js";import{GObjectObject as l,connectInstance as u,constructRegistered as d,createGObject as f,disconnectInstance as p,emitInstance as m,engineForTarget as h,notifyInstance as g,registeredClassOf as _,widgetControllerMembers as v,widgetDisplayMembers as y}from"@gjsify/adwaita-core";function nearestRegistered(e){for(let t=e;typeof t==`function`;t=Object.getPrototypeOf(t))if(_(t)!==void 0)return t}function declareEmitted(e,t){let n=i(e),r=[...t.properties.map(e=>`notify::${e.name}`),...Object.keys(t.signals)];Object.defineProperty(e,"emittedSignals",{value:[...new Set([...n,...r])],enumerable:!1,configurable:!0,writable:!0})}function spliceLayer(e){let n=Object.getPrototypeOf(e),r=n.prototype.notify;class Registered extends n{constructor(n){if(super(),nearestRegistered(new.target)!==e)return;let r=d(this,n);t(this,r)}}let i={connect(e,t){return u(this,e,t)},disconnect(e){p(this,e)},emit(e,...t){m(this,e,...t)},notify(e){typeof e==`string`?g(this,e):r.call(this,e)}};for(let[e,t]of Object.entries({...y(c),...v(o)}))e in n.prototype||(i[e]=t);for(let[e,t]of Object.entries(i))Object.defineProperty(Registered.prototype,e,{value:t,writable:!0,configurable:!0,enumerable:!1});Object.setPrototypeOf(e,Registered),Object.setPrototypeOf(e.prototype,Registered.prototype)}const{engineName:b,Object:x,registerClass:S,ParamSpec:C,ParamFlags:w,Value:T,TYPE_STRING:E,TYPE_BOOLEAN:D,TYPE_INT:O,TYPE_UINT:k,TYPE_DOUBLE:A,GTypeName:j,GTypeFlags:M,interfaces:N,properties:P,signals:F,requires:I,__gtkTemplate__:L,__gtkCssName__:R,__gtkChildren__:z,__gtkInternalChildren__:B,type_ensure:V,signal_stop_emission_by_name:H}=f({name:`adwaita-nativescript`,dispatch(e,t,n){e.notify({eventName:t,object:e,args:n})},listen(e,t,i){let listener=t=>{let n=t.accumulator;if(n===void 0){i(e,t);return}n.stopped||n.collect(i(e,t))},a=n.includes(t)?r(e):void 0;return e.addEventListener(t,listener),()=>{e.removeEventListener(t,listener),a?.()}},createFromTree(e,t,n){let r=s(n,e,{template:t});return{children:[],objects:Object.fromEntries(r)}},attach(e,t){},register(e,t){declareEmitted(e,t),!(e.prototype instanceof l)&&(spliceLayer(e),a(t.typeName,e))}},h(e));export{M as GTypeFlags,j as GTypeName,x as Object,w as ParamFlags,C as ParamSpec,D as TYPE_BOOLEAN,A as TYPE_DOUBLE,O as TYPE_INT,E as TYPE_STRING,k as TYPE_UINT,T as Value,z as __gtkChildren__,R as __gtkCssName__,B as __gtkInternalChildren__,L as __gtkTemplate__,b as engineName,N as interfaces,P as properties,S as registerClass,I as requires,H as signal_stop_emission_by_name,F as signals,V as type_ensure};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{builderSlotsOf as e,resolveBuilderSlot as t}from"./builder-slots.js";import{applyConstructProps as n}from"./construct-props.js";import{withSignals as r}from"./signals.js";import{GtkImage as i}from"./gtk-image.js";import{ActionRowState as a,isViewSensitive as o,rowLabelVisuals as s}from"./row-state.js";import{GridLayout as c,ItemSpec as l,Label as u,StackLayout as d}from"@nativescript/core";const f=`activated`,p=`notify::title`,m=`notify::subtitle`,h=`notify::icon-name`,g=`notify::activatable`,_=[`prefix`,`suffix`];var AdwActionRow=class extends r(c,{GTypeName:`AdwActionRow`,Properties:{title:{kind:`string`,default:``,blurb:`The title of the row`},subtitle:{kind:`string`,default:``,blurb:`The subtitle of the row`},"icon-name":{kind:`string`,default:``,blurb:`The icon name for this row`},activatable:{kind:`boolean`,default:!1,blurb:`Whether this row can be activated`}}}){static GTypeName=`AdwActionRow`;static builderSlots=e(_,`suffix`);isActionRow=!0;_textStack;_titleLabel;_subtitleLabel;_rowState=new a;_prefix=null;_iconImage=null;_suffix=null;constructor(e){super(),this.className=`adw-row adw-action-row`,this.addColumn(new l(1,`auto`)),this.addColumn(new l(1,`star`)),this.addColumn(new l(1,`auto`)),this.addRow(new l(1,`auto`));let t=new d;t.orientation=`vertical`,t.className=`adw-row-text`,c.setColumn(t,1);let r=new u;r.className=`adw-row-title`,r.textWrap=!0,t.addChild(r);let i=new u;i.className=`adw-row-subtitle`,i.textWrap=!0,t.addChild(i),this.addChild(t),this._textStack=t,this._titleLabel=r,this._subtitleLabel=i,this.connect(p,e=>e._applyLabels()),this.connect(m,e=>e._applyLabels()),this.connect(h,e=>e._applyIconName()),this.connect(g,e=>{e._rowState.setActivatable(e.activatable)}),this._applyLabels(),this.addEventListener(`tap`,()=>this.activate()),n(this,e)}add_prefix(e){this._prefix&&this.remove(this._prefix),e.className=`${e.className??``} adw-row-prefix`.trim(),c.setColumn(e,0),this.insertChild(e,0),this._prefix=e}get prefix(){return this._prefix}add_suffix(e){this._suffix&&this.remove(this._suffix),e.className=`${e.className??``} adw-row-suffix`.trim(),c.setColumn(e,2),this.addChild(e),this._suffix=e}remove(e){if(e===this._prefix)this._prefix=null;else if(e===this._suffix)this._suffix=null;else throw TypeError(`${this.constructor.name}.remove(): the view is neither this row's prefix nor its suffix. add_prefix()/add_suffix() are the only two slots remove() clears.`);this.removeChild(e),e===this._iconImage&&(this._iconImage=null,this.iconName=``)}get suffix(){return this._suffix}_addChildFromBuilder(e,n){t(e,_,`suffix`)===`prefix`?this.add_prefix(n):this.add_suffix(n)}get activatableWidget(){return this._rowState.activatableWidget}set activatableWidget(e){this._rowState.setActivatableWidget(e,o(e))&&e!==null&&(this.activatable=this._rowState.activatable)}syncActivatableWidgetSensitivity(){let e=this._rowState.activatableWidget;e&&this._rowState.setActivatableWidgetSensitive(o(e))&&(this.activatable=this._rowState.activatable)}activate(){if(!this.activatable)return;let e={eventName:f,object:this};this.notify(e)}_managesTitleVisibility=!0;_applyLabels(){let e=s({title:this.title,subtitle:this.subtitle});this._titleLabel.text=e.title,this._managesTitleVisibility&&(this._titleLabel.visibility=e.titleVisibility),this._subtitleLabel.text=e.subtitle,this._subtitleLabel.visibility=e.subtitleVisibility}_applyIconName(){let e=this.iconName;if(e===``){this._iconImage!==null&&this.remove(this._iconImage);return}this._iconImage===null&&(this._iconImage=new i,this.add_prefix(this._iconImage)),this._iconImage.iconName=e}};export{f as ACTIVATED,AdwActionRow,g as NOTIFY_ACTIVATABLE,h as NOTIFY_ICON_NAME,m as NOTIFY_SUBTITLE,p as NOTIFY_TITLE};
1
+ import"../_virtual/_rolldown/runtime.js";import{builderSlotsOf as e,resolveBuilderSlot as t}from"./builder-slots.js";import{applyConstructProps as n}from"./construct-props.js";import{withSignals as r}from"./signals.js";import{GtkImage as i}from"./gtk-image.js";import{ActionRowState as a,isViewSensitive as o,rowLabelVisuals as s}from"./row-state.js";import{adwSubtitleWriteNotifies as c}from"@gjsify/adwaita-core";import{GridLayout as l,ItemSpec as u,Label as d,StackLayout as f}from"@nativescript/core";const p=`activated`,m=`notify::title`,h=`notify::subtitle`,g=`notify::icon-name`,_=`notify::activatable`,v=[`prefix`,`suffix`];var AdwActionRow=class extends r(l,{GTypeName:`AdwActionRow`,Properties:{title:{kind:`string`,default:``,blurb:`The title of the row`},subtitle:{kind:`string`,default:``,blurb:`The subtitle of the row`,normalize:e=>e==null?``:String(e),changed:(e,t,n)=>c(String(t),n==null?null:String(e))},"icon-name":{kind:`string`,default:``,blurb:`The icon name for this row`},activatable:{kind:`boolean`,default:!1,blurb:`Whether this row can be activated`}}}){static GTypeName=`AdwActionRow`;static builderSlots=e(v,`suffix`);isActionRow=!0;_textStack;_titleLabel;_subtitleLabel;_rowState=new a;_prefix=null;_iconImage=null;_suffix=null;constructor(e){super(),this.className=`adw-row adw-action-row`,this.addColumn(new u(1,`auto`)),this.addColumn(new u(1,`star`)),this.addColumn(new u(1,`auto`)),this.addRow(new u(1,`auto`));let t=new f;t.orientation=`vertical`,t.className=`adw-row-text`,l.setColumn(t,1);let r=new d;r.className=`adw-row-title`,r.textWrap=!0,t.addChild(r);let i=new d;i.className=`adw-row-subtitle`,i.textWrap=!0,t.addChild(i),this.addChild(t),this._textStack=t,this._titleLabel=r,this._subtitleLabel=i,this.connect(m,e=>e._applyLabels()),this.connect(h,e=>e._applyLabels()),this.connect(g,e=>e._applyIconName()),this.connect(_,e=>{e._rowState.setActivatable(e.activatable)}),this._applyLabels(),this.addEventListener(`tap`,()=>this.activate()),n(this,e)}add_prefix(e){this._prefix&&this.remove(this._prefix),e.className=`${e.className??``} adw-row-prefix`.trim(),l.setColumn(e,0),this.insertChild(e,0),this._prefix=e}get prefix(){return this._prefix}add_suffix(e){this._suffix&&this.remove(this._suffix),e.className=`${e.className??``} adw-row-suffix`.trim(),l.setColumn(e,2),this.addChild(e),this._suffix=e}remove(e){if(e===this._prefix)this._prefix=null;else if(e===this._suffix)this._suffix=null;else throw TypeError(`${this.constructor.name}.remove(): the view is neither this row's prefix nor its suffix. add_prefix()/add_suffix() are the only two slots remove() clears.`);this.removeChild(e),e===this._iconImage&&(this._iconImage=null,this.iconName=``)}get suffix(){return this._suffix}_addChildFromBuilder(e,n){t(e,v,`suffix`)===`prefix`?this.add_prefix(n):this.add_suffix(n)}get activatableWidget(){return this._rowState.activatableWidget}set activatableWidget(e){this._rowState.setActivatableWidget(e,o(e))&&e!==null&&(this.activatable=this._rowState.activatable)}syncActivatableWidgetSensitivity(){let e=this._rowState.activatableWidget;e&&this._rowState.setActivatableWidgetSensitive(o(e))&&(this.activatable=this._rowState.activatable)}activate(){if(!this.activatable)return;let e={eventName:p,object:this};this.notify(e)}_managesTitleVisibility=!0;_applyLabels(){let e=s({title:this.title,subtitle:this.subtitle});this._titleLabel.text=e.title,this._managesTitleVisibility&&(this._titleLabel.visibility=e.titleVisibility),this._subtitleLabel.text=e.subtitle,this._subtitleLabel.visibility=e.subtitleVisibility}_applyIconName(){let e=this.iconName;if(e===``){this._iconImage!==null&&this.remove(this._iconImage);return}this._iconImage===null&&(this._iconImage=new i,this.add_prefix(this._iconImage)),this._iconImage.iconName=e}};export{p as ACTIVATED,AdwActionRow,_ as NOTIFY_ACTIVATABLE,g as NOTIFY_ICON_NAME,h as NOTIFY_SUBTITLE,m as NOTIFY_TITLE};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{builderSlotsOf as e,resolveBuilderSlot as t}from"./builder-slots.js";import{applyConstructProps as n}from"./construct-props.js";import{xmlNumber as r}from"./xml-values.js";import{GtkImage as i}from"./gtk-image.js";import{AdwActionRow as a}from"./adw-action-row.js";import{attachRowPressFeedback as o}from"./row-press.js";import{ComboState as s,ComboState as c,normalizeComboOptions as l,parseListModel as u}from"@gjsify/adwaita-core";import{Label as d,StackLayout as f,action as p}from"@nativescript/core";import{panDownSymbolic as m}from"@gjsify/adwaita-icons/ui";const h=`notify::selected`;var AdwComboRow=class extends a{static GTypeName=`AdwComboRow`;static builderSlots=e([...a.builderSlots,`model`],`suffix`);_valueLabel;_chevron;_state=new c;_pendingSelected=null;constructor(e){super(),this.className=`adw-row adw-action-row adw-combo-row`;let t=new f;t.orientation=`horizontal`,t.className=`adw-combo-suffix`;let r=new d;r.className=`adw-combo-value`,r.text=``;let a=new i;a.className=`adw-combo-chevron`,a.iconColor=`#9a9a9a`,a.pixelSize=16,a.iconName=m,t.addChild(r),t.addChild(a),this.add_suffix(t),this._valueLabel=r,this._chevron=a,this._state.subscribe(e=>{if(this._valueLabel.text=e.label,this._syncChooser(),e.interactive){let t={eventName:h,object:this,selected:e.selected,value:e.value};this.notify(t)}}),this.addEventListener(`tap`,()=>{this._openChooser()}),o(this),this._syncChooser(),n(this,e)}_syncChooser(){this._chevron.visibility=this._state.presentsChooser?`visible`:`collapse`}async _openChooser(){if(!this._state.presentsChooser)return;let e=this._state.model.map(e=>e.label),t=await p({title:this.title||void 0,cancelButtonText:`Cancel`,actions:e});this._state.select(e.indexOf(t))}get model(){return this._state.model}set model(e){if(this._state.setModel(typeof e==`string`?u(e):l(e)),this._pendingSelected!==null&&this._pendingSelected<this._state.model.length){let e=this._pendingSelected;this._pendingSelected=null,this._state.setSelectedIndex(e)}}set_model(e){this.model=e??[]}_addChildFromBuilder(e,n){if(t(e,[`model`],`edge`)===`model`){this.model=n;return}super._addChildFromBuilder(e,n)}get selected(){return this._state.selectedIndex}set selected(e){let t=r(e,this.selected);if(this._state.model.length===0){this._pendingSelected=t;return}this._state.setSelectedIndex(t)}get_selected(){return this.selected}set_selected(e){this.selected=e}get selectedValue(){return this._state.selectedValue}set selectedValue(e){this._state.setSelectedValue(e)}};export{AdwComboRow,s as ComboState,h as NOTIFY_SELECTED};
1
+ import"../_virtual/_rolldown/runtime.js";import{builderSlotsOf as e,resolveBuilderSlot as t}from"./builder-slots.js";import{applyConstructProps as n}from"./construct-props.js";import{xmlNumber as r}from"./xml-values.js";import{GtkImage as i}from"./gtk-image.js";import{AdwActionRow as a}from"./adw-action-row.js";import{attachRowPressFeedback as o}from"./row-press.js";import{ComboState as s,ComboState as c,GjsifyOptionList as l,readModelWrite as u}from"@gjsify/adwaita-core";import{Label as d,StackLayout as f,action as p}from"@nativescript/core";import{panDownSymbolic as m}from"@gjsify/adwaita-icons/ui";const h=`notify::selected`;var AdwComboRow=class extends a{static GTypeName=`AdwComboRow`;static builderSlots=e([...a.builderSlots,`model`],`suffix`);_valueLabel;_chevron;_state=new c;_authored=l.new(null);_pendingSelected=null;constructor(e){super(),this.className=`adw-row adw-action-row adw-combo-row`;let t=new f;t.orientation=`horizontal`,t.className=`adw-combo-suffix`;let r=new d;r.className=`adw-combo-value`,r.text=``;let a=new i;a.className=`adw-combo-chevron`,a.iconColor=`#9a9a9a`,a.pixelSize=16,a.iconName=m,t.addChild(r),t.addChild(a),this.add_suffix(t),this._valueLabel=r,this._chevron=a,this._state.subscribe(e=>{if(this._valueLabel.text=e.label,this._syncChooser(),e.interactive){let t={eventName:h,object:this,selected:e.selected,value:e.value};this.notify(t)}}),this.addEventListener(`tap`,()=>{this._openChooser()}),o(this),this._syncChooser(),n(this,e)}_syncChooser(){this._chevron.visibility=this._state.presentsChooser?`visible`:`collapse`}async _openChooser(){if(!this._state.presentsChooser)return;let e=this._state.options.map(e=>e.label),t=await p({title:this.title||void 0,cancelButtonText:`Cancel`,actions:e});this._state.select(e.indexOf(t))}get model(){return this._state.model}set model(e){if(this._state.setModel(u(e,this._authored)),this._pendingSelected!==null&&this._state.hasIndex(this._pendingSelected)){let e=this._pendingSelected;this._pendingSelected=null,this._state.setSelectedIndex(e)}}get options(){return this._state.options}set_model(e){this.model=e}get_model(){return this.model}_addChildFromBuilder(e,n){if(t(e,[`model`],`edge`)===`model`){this.model=n;return}super._addChildFromBuilder(e,n)}get selected(){return this._state.selectedIndex}set selected(e){let t=r(e,this.selected);if(this._state.count===0){this._pendingSelected=t;return}this._state.setSelectedIndex(t)}get_selected(){return this.selected}set_selected(e){this.selected=e}get selectedValue(){return this._state.selectedValue}set selectedValue(e){this._state.setSelectedValue(e)}get selectedItem(){return this._state.selectedItem}get_selected_item(){return this.selectedItem}};export{AdwComboRow,s as ComboState,h as NOTIFY_SELECTED};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{applyConstructProps as e}from"./construct-props.js";import{xmlBoolean as t}from"./xml-values.js";import{withSignals as n}from"./signals.js";import{GtkImage as r}from"./gtk-image.js";import{attachRowPressFeedback as i}from"./row-press.js";import{buttonContentClassName as a,buttonContentLabelText as o}from"./button-content.js";import{assertPopupMenuAssignable as s,refuseMenuString as c}from"./popup-menu.js";import{showMenuPopup as l}from"./popup-menu-view.js";import{splitButtonArrowSvg as u}from"./split-button.js";import{ArrowType as d}from"./gtk-enums.js";import{SPLIT_BUTTON_DISABLED_OPACITY as f,SplitButtonState as p}from"@gjsify/adwaita-core";import{GridLayout as m,ItemSpec as h,Label as g,StackLayout as _}from"@nativescript/core";const v=`notify::direction`,y=`menuTapped`,clearingSlot=(e,t)=>{e._contentGate=!0;try{t()}finally{e._contentGate=!1}};var AdwSplitButton=class extends n(m,{GTypeName:`AdwSplitButton`,Signals:{clicked:{},activate:{}},Properties:{label:{kind:`string`,default:null,blurb:`The label to show in the button`,normalize:(e,t)=>{let n=t;if(n._contentGate)return null;if(e==null)return n.label;let r=String(e);return r!==n.label&&n.iconName!==null&&clearingSlot(n,()=>n.iconName=null),r}},"icon-name":{kind:`string`,default:null,blurb:`The name of the icon used to automatically populate the button`,normalize:(e,t)=>{let n=t;if(n._contentGate)return null;if(e==null)return n.iconName;let r=String(e)===``?null:String(e);return n.label!==null&&clearingSlot(n,()=>n.label=null),r}},"use-underline":{kind:`boolean`,default:!1,blurb:`Whether an underline in the text indicates a mnemonic`},"can-shrink":{kind:`boolean`,default:!1,blurb:`Whether the button can be smaller than the natural size of its contents`},"dropdown-tooltip":{kind:`string`,default:``,blurb:`The tooltip of the dropdown button`}}}){static GTypeName=`AdwSplitButton`;static emittedSignals=[v];_actionPart;_actionLabel;_actionIcon;_dropdownPart;_chevron;_state=new p;_actions=null;_showingIcon=!1;_sensitive=!0;_contentGate=!1;constructor(t){super(),this.className=`adw-split-button`,this.addColumn(new h(1,`auto`)),this.addColumn(new h(1,`auto`)),this.addRow(new h(1,`auto`));let n=new _;n.orientation=`horizontal`,n.className=`adw-split-button-action`,n.horizontalAlignment=`center`,m.setColumn(n,0);let o=new g;o.className=`adw-split-button-label`,o.verticalAlignment=`middle`,n.addChild(o);let s=new r;s.className=`${s.className} adw-split-button-action-icon`.trim(),s.verticalAlignment=`middle`,this.addChild(n),this._actionPart=n,this._actionLabel=o,this._actionIcon=s;let c=new m;c.className=`adw-split-button-dropdown`,c.addColumn(new h(1,`star`)),c.addRow(new h(1,`star`)),m.setColumn(c,1);let l=new r;l.className=`${l.className} adw-split-button-chevron`.trim(),l.iconName=u(this._state.direction),l.horizontalAlignment=`center`,l.verticalAlignment=`middle`,c.addChild(l),this.addChild(c),this._dropdownPart=c,this._chevron=l,n.addEventListener(`tap`,()=>this._click()),this.connect(`activate`,e=>e._click()),c.addEventListener(`tap`,()=>{this._openMenu()}),i(n),i(c),this.connect(`notify::label`,e=>e._renderContent()),this.connect(`notify::icon-name`,e=>e._renderContent()),this.connect(`notify::use-underline`,e=>e._renderContent()),this.connect(`notify::can-shrink`,e=>{e._actionLabel.className=a(e._actionLabel.className,e.canShrink)}),this._state.subscribe(()=>this._render()),this._render(),e(this,t)}_openMenu(){if(!(!this._sensitive||this._state.open||!this._state.dropdownEnabled)){this._state.toggleMenu();try{l(this._dropdownPart,{model:this._state.menuModel??[],actions:this._actions,onActivated:(e,t)=>{let n=this._state.activateMenuItem(t);if(n===null)return;let r={eventName:y,object:this,item:n.label,id:n.id??n.label,path:t,action:n.action};this.notify(r)},onDismiss:()=>this._state.closeMenu()})}catch(e){throw this._state.closeMenu(),e}}}_click(){this._sensitive&&this.emit(`clicked`)}_renderContent(){let e=this.iconName!==null;e?this._actionIcon.iconName=this.iconName??``:this._actionLabel.text=o(this.label??``,this.useUnderline),e!==this._showingIcon&&(this._actionPart.removeChild(this._showingIcon?this._actionIcon:this._actionLabel),this._actionPart.addChild(e?this._actionIcon:this._actionLabel),this._showingIcon=e)}_render(){let{direction:e,dropdownEnabled:t}=this._state;this._chevron.iconName=u(e),this._dropdownPart.opacity=t?1:f,this.opacity=this._sensitive?1:f}get menuModel(){return this._state.menuModel??[]}set menuModel(e){c(e,`AdwSplitButton`),this._state.setMenuModel(e),s(this._state.menuModel??[])}get actions(){return this._actions}set actions(e){this._actions=e??null}get_direction(){return d[this._state.direction.toUpperCase()]}set_direction(e){let t=e,n=typeof t==`number`?t:/^\d+$/.test(String(t))?Number(t):d[String(t).toUpperCase()],r=Object.keys(d).find(e=>d[e]===n)?.toLowerCase();if(r===void 0)throw TypeError(`${String(t)} is not a valid value for enum argument direction (Gtk.ArrowType)`);this._state.setDirection(r)&&this.notify({eventName:v,object:this,value:this.get_direction()})}get sensitive(){return this._sensitive}set sensitive(e){let n=!!t(e,this._sensitive);n!==this._sensitive&&(this._sensitive=n,this._render())}get actionButton(){return this._actionPart}};export{AdwSplitButton,y as MENU_TAPPED,v as NOTIFY_DIRECTION};
1
+ import"../_virtual/_rolldown/runtime.js";import{applyConstructProps as e}from"./construct-props.js";import{xmlBoolean as t}from"./xml-values.js";import{withSignals as n}from"./signals.js";import{GtkImage as r}from"./gtk-image.js";import{attachRowPressFeedback as i}from"./row-press.js";import{buttonContentClassName as a,buttonContentLabelText as o}from"./button-content.js";import{assertPopupMenuAssignable as s,refuseMenuString as c}from"./popup-menu.js";import{showMenuPopup as l}from"./popup-menu-view.js";import{splitButtonArrowSvg as u}from"./split-button.js";import{ArrowType as d}from"./gtk-enums.js";import{SPLIT_BUTTON_DISABLED_OPACITY as f,SplitButtonState as p}from"@gjsify/adwaita-core";import{GridLayout as m,ItemSpec as h,Label as g,StackLayout as _}from"@nativescript/core";const v=`notify::direction`,y=`menuTapped`,clearOtherSlot=(e,t)=>{if(!(e._contentGate||e[t]===null)){e._contentGate=!0;try{e[t]=null}finally{e._contentGate=!1}}};var AdwSplitButton=class extends n(m,{GTypeName:`AdwSplitButton`,Signals:{clicked:{},activate:{}},Properties:{label:{kind:`string`,default:null,blurb:`The label to show in the button`,normalize:(e,t)=>{let n=t;return n._contentGate?null:e==null?n.label:String(e)},afterNotify:e=>clearOtherSlot(e,`iconName`)},"icon-name":{kind:`string`,default:null,blurb:`The name of the icon used to automatically populate the button`,normalize:(e,t)=>{let n=t;return n._contentGate?null:e==null?n.iconName:String(e)===``?null:String(e)},changed:(e,t,n)=>e!==t||n===``,afterNotify:e=>clearOtherSlot(e,`label`)},"use-underline":{kind:`boolean`,default:!1,blurb:`Whether an underline in the text indicates a mnemonic`},"can-shrink":{kind:`boolean`,default:!1,blurb:`Whether the button can be smaller than the natural size of its contents`},"dropdown-tooltip":{kind:`string`,default:``,blurb:`The tooltip of the dropdown button`}}}){static GTypeName=`AdwSplitButton`;static emittedSignals=[v];_actionPart;_actionLabel;_actionIcon;_dropdownPart;_chevron;_state=new p;_actions=null;_showingIcon=!1;_sensitive=!0;_contentGate=!1;constructor(t){super(),this.className=`adw-split-button`,this.addColumn(new h(1,`auto`)),this.addColumn(new h(1,`auto`)),this.addRow(new h(1,`auto`));let n=new _;n.orientation=`horizontal`,n.className=`adw-split-button-action`,n.horizontalAlignment=`center`,m.setColumn(n,0);let o=new g;o.className=`adw-split-button-label`,o.verticalAlignment=`middle`,n.addChild(o);let s=new r;s.className=`${s.className} adw-split-button-action-icon`.trim(),s.verticalAlignment=`middle`,this.addChild(n),this._actionPart=n,this._actionLabel=o,this._actionIcon=s;let c=new m;c.className=`adw-split-button-dropdown`,c.addColumn(new h(1,`star`)),c.addRow(new h(1,`star`)),m.setColumn(c,1);let l=new r;l.className=`${l.className} adw-split-button-chevron`.trim(),l.iconName=u(this._state.direction),l.horizontalAlignment=`center`,l.verticalAlignment=`middle`,c.addChild(l),this.addChild(c),this._dropdownPart=c,this._chevron=l,n.addEventListener(`tap`,()=>this._click()),this.connect(`activate`,e=>e._click()),c.addEventListener(`tap`,()=>{this._openMenu()}),i(n),i(c),this.connect(`notify::label`,e=>e._renderContent()),this.connect(`notify::icon-name`,e=>e._renderContent()),this.connect(`notify::use-underline`,e=>e._renderContent()),this.connect(`notify::can-shrink`,e=>{e._actionLabel.className=a(e._actionLabel.className,e.canShrink)}),this._state.subscribe(()=>this._render()),this._render(),e(this,t)}_openMenu(){if(!(!this._sensitive||this._state.open||!this._state.dropdownEnabled)){this._state.toggleMenu();try{l(this._dropdownPart,{model:this._state.menuModel??[],actions:this._actions,onActivated:(e,t)=>{let n=this._state.activateMenuItem(t);if(n===null)return;let r={eventName:y,object:this,item:n.label,id:n.id??n.label,path:t,action:n.action};this.notify(r)},onDismiss:()=>this._state.closeMenu()})}catch(e){throw this._state.closeMenu(),e}}}_click(){this._sensitive&&this.emit(`clicked`)}_renderContent(){let e=this.iconName!==null;e?this._actionIcon.iconName=this.iconName??``:this._actionLabel.text=o(this.label??``,this.useUnderline),e!==this._showingIcon&&(this._actionPart.removeChild(this._showingIcon?this._actionIcon:this._actionLabel),this._actionPart.addChild(e?this._actionIcon:this._actionLabel),this._showingIcon=e)}_render(){let{direction:e,dropdownEnabled:t}=this._state;this._chevron.iconName=u(e),this._dropdownPart.opacity=t?1:f,this.opacity=this._sensitive?1:f}get menuModel(){return this._state.menuModel??[]}set menuModel(e){c(e,`AdwSplitButton`),this._state.setMenuModel(e),s(this._state.menuModel??[])}get actions(){return this._actions}set actions(e){this._actions=e??null}get_direction(){return d[this._state.direction.toUpperCase()]}set_direction(e){let t=e,n=typeof t==`number`?t:/^\d+$/.test(String(t))?Number(t):d[String(t).toUpperCase()],r=Object.keys(d).find(e=>d[e]===n)?.toLowerCase();if(r===void 0)throw TypeError(`${String(t)} is not a valid value for enum argument direction (Gtk.ArrowType)`);this._state.setDirection(r)&&this.notify({eventName:v,object:this,value:this.get_direction()})}get sensitive(){return this._sensitive}set sensitive(e){let n=!!t(e,this._sensitive);n!==this._sensitive&&(this._sensitive=n,this._render())}get actionButton(){return this._actionPart}};export{AdwSplitButton,y as MENU_TAPPED,v as NOTIFY_DIRECTION};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{builderSlotsOf as e,resolveBuilderSlot as t}from"./builder-slots.js";import{applyConstructProps as n}from"./construct-props.js";import{xmlNumber as r}from"./xml-values.js";import{withSignals as i}from"./signals.js";import{GtkImage as a}from"./gtk-image.js";import{attachRowPressFeedback as o}from"./row-press.js";import{ComboState as s,normalizeComboOptions as c,parseListModel as l}from"@gjsify/adwaita-core";import{Label as u,StackLayout as d,action as f}from"@nativescript/core";import{panDownSymbolic as p}from"@gjsify/adwaita-icons/ui";const m=`notify::selected`,h=`notify::selected-item`;var GtkDropDown=class extends i(d){static GTypeName=`GtkDropDown`;static emittedSignals=[m,h];static builderSlots=e([`model`],`model`);_label;_chevron;_state=new s;_chooserTitle=``;constructor(e){super(),this.orientation=`horizontal`,this.className=`adw-drop-down`;let t=new u;t.className=`adw-drop-down-label`,t.text=``;let r=new a;r.className=`adw-drop-down-chevron`,r.iconName=p,this.addChild(t),this.addChild(r),this._label=t,this._chevron=r,this._state.subscribe(e=>{if(this._label.text=e.label,e.interactive)for(let t of[m,h]){let n={eventName:t,object:this,selected:e.selected,value:e.value,label:e.label};this.notify(n)}}),this.addEventListener(`tap`,()=>{this._openChooser()}),o(this),n(this,e)}async _openChooser(){if(this._state.count===0)return;let e=this._state.model.map(e=>e.label),t=await f({title:this._chooserTitle||void 0,cancelButtonText:`Cancel`,actions:e});this._state.select(e.indexOf(t))}get model(){return this._state.model}set model(e){this._state.setModel(typeof e==`string`?l(e):c(e))}_addChildFromBuilder(e,n){if(t(e,[`model`],`child`)!==`model`)throw Error(`Gtk.DropDown takes no child widget; <${e}> is placed nowhere.`);this.model=n}get selected(){return this._state.selectedIndex}set selected(e){let t=r(e,this.selected);this._state.setSelectedIndex(t)}get_selected(){return this.selected}set_selected(e){this.selected=e}get selectedValue(){return this._state.selectedValue}set selectedValue(e){this._state.setSelectedValue(e)}get selectedItem(){return this._state.model[this._state.selectedIndex]??null}get chooserTitle(){return this._chooserTitle}set chooserTitle(e){this._chooserTitle=e??``}};export{GtkDropDown,m as NOTIFY_SELECTED,h as NOTIFY_SELECTED_ITEM};
1
+ import"../_virtual/_rolldown/runtime.js";import{builderSlotsOf as e,resolveBuilderSlot as t}from"./builder-slots.js";import{applyConstructProps as n}from"./construct-props.js";import{xmlNumber as r}from"./xml-values.js";import{withSignals as i}from"./signals.js";import{GtkImage as a}from"./gtk-image.js";import{attachRowPressFeedback as o}from"./row-press.js";import{ComboState as s,GjsifyOptionList as c,readModelWrite as l}from"@gjsify/adwaita-core";import{Label as u,StackLayout as d,action as f}from"@nativescript/core";import{panDownSymbolic as p}from"@gjsify/adwaita-icons/ui";const m=`notify::selected`,h=`notify::selected-item`;var GtkDropDown=class extends i(d){static GTypeName=`GtkDropDown`;static emittedSignals=[m,h];static builderSlots=e([`model`],`model`);_label;_chevron;_state=new s;_authored=c.new(null);_chooserTitle=``;constructor(e){super(),this.orientation=`horizontal`,this.className=`adw-drop-down`;let t=new u;t.className=`adw-drop-down-label`,t.text=``;let r=new a;r.className=`adw-drop-down-chevron`,r.iconName=p,this.addChild(t),this.addChild(r),this._label=t,this._chevron=r,this._state.subscribe(e=>{if(this._label.text=e.label,e.interactive)for(let t of[m,h]){let n={eventName:t,object:this,selected:e.selected,value:e.value,label:e.label};this.notify(n)}}),this.addEventListener(`tap`,()=>{this._openChooser()}),o(this),n(this,e)}async _openChooser(){if(this._state.count===0)return;let e=this._state.options.map(e=>e.label),t=await f({title:this._chooserTitle||void 0,cancelButtonText:`Cancel`,actions:e});this._state.select(e.indexOf(t))}get model(){return this._state.model}set model(e){this._state.setModel(l(e,this._authored))}get options(){return this._state.options}set_model(e){this.model=e}get_model(){return this.model}_addChildFromBuilder(e,n){if(t(e,[`model`],`child`)!==`model`)throw Error(`Gtk.DropDown takes no child widget; <${e}> is placed nowhere.`);this.model=n}get selected(){return this._state.selectedIndex}set selected(e){let t=r(e,this.selected);this._state.setSelectedIndex(t)}get_selected(){return this.selected}set_selected(e){this.selected=e}get selectedValue(){return this._state.selectedValue}set selectedValue(e){this._state.setSelectedValue(e)}get selectedItem(){return this._state.selectedItem}get_selected_item(){return this.selectedItem}get chooserTitle(){return this._chooserTitle}set chooserTitle(e){this._chooserTitle=e??``}};export{GtkDropDown,m as NOTIFY_SELECTED,h as NOTIFY_SELECTED_ITEM};
@@ -1,2 +1,2 @@
1
- import"../_virtual/_rolldown/runtime.js";import{applyConstructProps as e}from"./construct-props.js";import{xmlBoolean as t,xmlNumber as n}from"./xml-values.js";import{androidApiLevel as r}from"./native-tooltip.js";import{withSignals as i}from"./signals.js";import{classNameWith as a,normalizeStyleClasses as o,withCssClass as s,withoutCssClass as c}from"./style-classes.js";import{DEFAULT_LABEL_LINES as l,DEFAULT_LABEL_XALIGN as u,LABEL_JUSTIFICATIONS as d,labelDisplayText as f,labelEffectiveLines as p,labelEllipsizeOverflowValue as m,normalizeLabelEllipsize as h,normalizeLabelLines as g,normalizeLabelXalign as _}from"@gjsify/adwaita-core";import{Label as v}from"@nativescript/core";const y=new Map([[0,`start`],[.5,`center`],[1,`end`]]),b={left:`start`,right:`end`,center:`center`,fill:`start`};function physical(e,t){return e===`center`?`center`:e===`start`===t?`right`:`left`}var GtkLabel=class extends i(v){static GTypeName=`GtkLabel`;_label=``;_useMarkup=!1;_useUnderline=!1;_ellipsize=`none`;_lines=-1;_styleClasses=[];_xalign=u;_xalignWritten=!1;_justify=`left`;_selectable=!1;constructor(t){super(),this.addEventListener(`loaded`,()=>{this._applySelectable(),this._applyJustificationMode()}),e(this,t)}get label(){return this._label}set label(e){this._label=e??``,this._render()}get useMarkup(){return this._useMarkup}set useMarkup(e){this._useMarkup=t(e,this._useMarkup),this._render()}get useUnderline(){return this._useUnderline}set useUnderline(e){this._useUnderline=t(e,this._useUnderline),this._render()}get wrap(){return this.textWrap}set wrap(e){let n=t(e,this.textWrap);this._applyAlignment({wrap:n}),this.textWrap=n}get ellipsize(){return this._ellipsize}set ellipsize(e){this._ellipsize=h(e),this.textOverflow=m(this._ellipsize),this._applyLines()}get lines(){return this._lines}set lines(e){this._lines=g(n(e,l)),this._applyLines()}get selectable(){return this._selectable}set selectable(e){this._selectable=t(e,this._selectable),this._applySelectable()}_applySelectable(){this.nativeViewProtected?.setTextIsSelectable?.(this._selectable)}_applyLines(){this.maxLines=p(this._lines,this._ellipsize)??0}get justify(){return this._justify}set justify(e){let t=d.includes(e)?e:d[n(e,-1)];if(t===void 0)throw TypeError(`'${String(e)}' is not a Gtk.Justification, so it cannot be 'justify'. The members are ${d.join(`, `)}, or their values 0 to 3.`);this._applyAlignment({justify:t})}get xalign(){return this._xalign}set xalign(e){let t=_(n(e,u));if(!y.has(t))throw TypeError(`Gtk.Label xalign ${t} has no NativeScript counterpart: textAlignment places text at the start, the centre or the end, so only 0, 0.5 and 1 render as written. Snapping it would show a different label than GTK does with no sign of the difference.`);this._applyAlignment({xalign:t})}_applyAlignment(e){let t=e.xalign??(this._xalignWritten?this._xalign:null),n=e.justify??this._justify,r=e.text??this.text??``,i=(e.wrap??this.textWrap)||r.includes(`
2
- `),a=b[n],o=t===null?null:y.get(t),s;if(o===null)s=n===`left`?null:a;else if(o===a||!i||n===`left`)s=o;else throw TypeError(`Gtk.Label justify ${n} beside xalign ${t} has no NativeScript counterpart on a label that can show several lines: GTK places the text block at its ${o} and aligns the lines inside it to their ${a}, and textAlignment is one alignment for both. An xalign on the justify edge, or a label without wrap and newline, renders exactly.`);if(e.xalign!==void 0&&(this._xalign=e.xalign,this._xalignWritten=!0),e.justify!==void 0&&(this._justify=e.justify),s===null){(e.xalign!==void 0||e.justify!==void 0)&&(this.textAlignment=`initial`);return}let c=physical(s,this.style?.direction===`rtl`);this.textAlignment=n===`fill`&&c===`left`?`justify`:c,this._applyJustificationMode()}_applyJustificationMode(){this.textAlignment===`justify`||r()<26||this.nativeViewProtected?.setJustificationMode?.(+(this._justify===`fill`))}get styleClasses(){return[...this._styleClasses]}set styleClasses(e){this._setClasses(o(e))}get_label(){return this.label}set_label(e){this.label=e}set_markup(e){this._label=e??``,this._useMarkup=!0,this._render()}get_text(){return this.text??``}add_css_class(e){this._setClasses(s(this._styleClasses,e))}remove_css_class(e){this._setClasses(c(this._styleClasses,e))}has_css_class(e){return this._styleClasses.includes((e??``).trim())}get_css_classes(){return[...this._styleClasses]}set_css_classes(e){this._setClasses(o([...e].join(` `)))}_setClasses(e){this._styleClasses=[...e],this.className=a(``,this._styleClasses)}_render(){let e=f(this._label,this._useMarkup,this._useUnderline);this._applyAlignment({text:e}),this.text=e}};export{GtkLabel};
1
+ import"../_virtual/_rolldown/runtime.js";import{applyConstructProps as e}from"./construct-props.js";import{xmlBoolean as t,xmlNumber as n}from"./xml-values.js";import{androidApiLevel as r}from"./native-tooltip.js";import{withSignals as i}from"./signals.js";import{nativePlatformHost as a}from"../platform-host.js";import{classNameWith as o,normalizeStyleClasses as s,withCssClass as c,withoutCssClass as l}from"./style-classes.js";import{labelMarkupFormattedString as u,labelMarkupNeedsSpans as d}from"./label-markup.js";import{DEFAULT_LABEL_LINES as f,DEFAULT_LABEL_XALIGN as p,HandledAccumulator as m,LABEL_JUSTIFICATIONS as h,createAppInfo as g,labelActivateLink as _,labelDisplayText as v,labelEffectiveLines as y,labelEllipsizeOverflowValue as b,labelHasLinks as x,labelLinkVisited as S,labelMarkupRender as C,normalizeLabelEllipsize as w,normalizeLabelLines as T,normalizeLabelXalign as E}from"@gjsify/adwaita-core";import{Label as D}from"@nativescript/core";const O=`activate-link`,k=g(a),A=new Map([[0,`start`],[.5,`center`],[1,`end`]]),j={left:`start`,right:`end`,center:`center`,fill:`start`};function physical(e,t){return e===`center`?`center`:e===`start`===t?`right`:`left`}var GtkLabel=class extends i(D){static GTypeName=`GtkLabel`;_label=``;_useMarkup=!1;_useUnderline=!1;_ellipsize=`none`;_lines=-1;_styleClasses=[];_xalign=p;_xalignWritten=!1;_justify=`left`;_selectable=!1;_links=[];constructor(t){super(),this.addEventListener(`loaded`,()=>{this._applySelectable(),this._applyJustificationMode()}),e(this,t)}get label(){return this._label}set label(e){this._label=e??``,this._render()}get useMarkup(){return this._useMarkup}set useMarkup(e){this._useMarkup=t(e,this._useMarkup),this._render()}get useUnderline(){return this._useUnderline}set useUnderline(e){this._useUnderline=t(e,this._useUnderline),this._render()}get wrap(){return this.textWrap}set wrap(e){let n=t(e,this.textWrap);this._applyAlignment({wrap:n}),this.textWrap=n}get ellipsize(){return this._ellipsize}set ellipsize(e){this._ellipsize=w(e),this.textOverflow=b(this._ellipsize),this._applyLines()}get lines(){return this._lines}set lines(e){this._lines=T(n(e,f)),this._applyLines()}get selectable(){return this._selectable}set selectable(e){this._selectable=t(e,this._selectable),this._applySelectable()}_applySelectable(){this.nativeViewProtected?.setTextIsSelectable?.(this._selectable)}_applyLines(){this.maxLines=y(this._lines,this._ellipsize)??0}get justify(){return this._justify}set justify(e){let t=h.includes(e)?e:h[n(e,-1)];if(t===void 0)throw TypeError(`'${String(e)}' is not a Gtk.Justification, so it cannot be 'justify'. The members are ${h.join(`, `)}, or their values 0 to 3.`);this._applyAlignment({justify:t})}get xalign(){return this._xalign}set xalign(e){let t=E(n(e,p));if(!A.has(t))throw TypeError(`Gtk.Label xalign ${t} has no NativeScript counterpart: textAlignment places text at the start, the centre or the end, so only 0, 0.5 and 1 render as written. Snapping it would show a different label than GTK does with no sign of the difference.`);this._applyAlignment({xalign:t})}_applyAlignment(e){let t=e.xalign??(this._xalignWritten?this._xalign:null),n=e.justify??this._justify,r=e.text??this.text??``,i=(e.wrap??this.textWrap)||r.includes(`
2
+ `),a=j[n],o=t===null?null:A.get(t),s;if(o===null)s=n===`left`?null:a;else if(o===a||!i||n===`left`)s=o;else throw TypeError(`Gtk.Label justify ${n} beside xalign ${t} has no NativeScript counterpart on a label that can show several lines: GTK places the text block at its ${o} and aligns the lines inside it to their ${a}, and textAlignment is one alignment for both. An xalign on the justify edge, or a label without wrap and newline, renders exactly.`);if(e.xalign!==void 0&&(this._xalign=e.xalign,this._xalignWritten=!0),e.justify!==void 0&&(this._justify=e.justify),s===null){(e.xalign!==void 0||e.justify!==void 0)&&(this.textAlignment=`initial`);return}let c=physical(s,this.style?.direction===`rtl`);this.textAlignment=n===`fill`&&c===`left`?`justify`:c,this._applyJustificationMode()}_applyJustificationMode(){this.textAlignment===`justify`||r()<26||this.nativeViewProtected?.setJustificationMode?.(+(this._justify===`fill`))}get styleClasses(){return[...this._styleClasses]}set styleClasses(e){this._setClasses(s(e))}get_label(){return this.label}set_label(e){this.label=e}set_markup(e){this._label=e??``,this._useMarkup=!0,this._render()}get_text(){return this.text??``}add_css_class(e){this._setClasses(c(this._styleClasses,e))}remove_css_class(e){this._setClasses(l(this._styleClasses,e))}has_css_class(e){return this._styleClasses.includes((e??``).trim())}get_css_classes(){return[...this._styleClasses]}set_css_classes(e){this._setClasses(s([...e].join(` `)))}_setClasses(e){this._styleClasses=[...e],this.className=o(``,this._styleClasses)}_render(){let e=this._useMarkup?C(this._label,this._links):null;this._links=e?.links??[];let t=v(this._label,this._useMarkup,this._useUnderline);this._applyAlignment({text:t});let n=x(this._links);if(n!==this._styleClasses.includes(`link`)&&this._setClasses(n?c(this._styleClasses,`link`):l(this._styleClasses,`link`)),e!==null&&d(e)){this.text=t,this.formattedText=u(e,this._useUnderline,this.style.fontSize,e=>this._activateLink(e));return}this.formattedText!==null&&this.formattedText!==void 0&&(this.formattedText=null),this.text=t}_activateLink(e){let t=this._links[e];t!==void 0&&_(t.href,{rooted:this.isLoaded,emit:()=>{let e=new m;return this.notify({eventName:O,object:this,uri:t.href,accumulator:e}),e.stopped},launch:e=>this.launch(e)})&&(this._links=S(this._links,e))}launch(e){try{k.launch_default_for_uri(e,null)}catch{}}};export{O as ACTIVATE_LINK,GtkLabel};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{applyConstructProps as e}from"./construct-props.js";import{xmlBoolean as t,xmlNumber as n}from"./xml-values.js";import{surfaceSize as r}from"./window-state.js";import{windowHost as i}from"../window-host.js";import{AdwBottomSheet as a}from"./adw-bottom-sheet.js";import{defineWindowApplication as o}from"./application.js";import{AdwSingleChildBase as s}from"./single-child-base.js";import{CloseRequestState as c,HandledAccumulator as l,WindowMemberState as u,stepDefaultSize as d}from"@gjsify/adwaita-core";const f=`notify::is-active`,p=`notify::maximized`,m=`notify::focus-widget`,h=`close-request`;var g=class GtkWindow extends s{static GTypeName=`GtkWindow`;_title=``;_defaultWidth=0;_defaultHeight=0;_members=new u(e=>{let t=e===`is-active`?f:p;this.notify({eventName:t,object:this,value:e===`is-active`?this.isActive:this.maximized})},{maximized:!0});_closeRequest=new c;_unwatchForeground=null;_unwatchBack=null;constructor(t){super(),e(this,t)}onLoaded(){super.onLoaded();let e=i();this._unwatchForeground?.(),this._unwatchForeground=e.watchForeground(e=>this._members.reportActive(e)),this._members.reportActive(e.isForeground()),this._unwatchBack?.(),this._unwatchBack=this._isToplevel()?e.watchBack(()=>this._handleBack()):null}onUnloaded(){this._unwatchForeground?.(),this._unwatchForeground=null,this._unwatchBack?.(),this._unwatchBack=null,this._members.reportActive(!1),super.onUnloaded()}get isActive(){return this._members.active}get is_active(){return this._members.active}get maximized(){return this._members.maximized}set maximized(e){t(e,!0)?this.maximize():this.unmaximize()}is_maximized(){return this.maximized}maximize(){}unmaximize(){throw Error(`GtkWindow.unmaximize is not supported on NativeScript: the window is the whole screen and the platform has no un-maximized state to go back to.`)}present(){}get focusWidget(){return this.get_focus()}get focus_widget(){return this.get_focus()}set focus_widget(e){this.set_focus(e)}get_focus(){let e=i();return findView(this,t=>e.isFocused(t))}set_focus(e){let t=i();if(e===null){let e=this.get_focus();e!==null&&t.clearFocus(e);return}if(findView(this,t=>t===e)===null)throw Error(`GtkWindow.set_focus: the widget is not a descendant of this window.`);t.requestFocus(e)}close(){let e=i();if(this.isLoaded&&!e.canFinish)throw Error(`GtkWindow.close is not supported on this platform: iOS has no public API to close the root window. Android finishes the foreground activity.`);this._requestClose()}_requestClose(){let e=i();this._closeRequest.close({realized:this.isLoaded,hideOnClose:!1,emit:()=>{let e=new l;return this.notify({eventName:h,object:this,accumulator:e}),e.stopped},hide:()=>{},destroy:()=>e.finish()})}_handleBack(){return this._consumeBack()||closeOpenBottomSheet(this)||popInnermostNavigation(this)||this._requestClose(),!0}_consumeBack(){return!1}_isToplevel(){for(let e=this.parent;e;e=e.parent)if(e instanceof GtkWindow)return!1;return!0}connect(e,t){if(e===`notify::focus-widget`)throw Error(`GtkWindow notify::focus-widget is not supported on NativeScript: focus the user moves is not observable here. Read get_focus() when you need it.`);return super.connect(e,t)}get title(){return this._title}set title(e){this._title=e??``}get defaultWidth(){return this._defaultWidth}set defaultWidth(e){this._defaultWidth=r(n(e,NaN),e,this._defaultWidth,`defaultWidth`)}get defaultHeight(){return this._defaultHeight}set defaultHeight(e){this._defaultHeight=r(n(e,NaN),e,this._defaultHeight,`defaultHeight`)}get_default_size(){return[this._defaultWidth,this._defaultHeight]}set_default_size(e,t){let n=d(this.get_default_size(),e,t);if(n!==null){this._defaultWidth=n.width,this._defaultHeight=n.height;for(let e of n.changed){let t=e===`default-width`?n.width:n.height;this.notify({eventName:`notify::${e}`,object:this,value:t})}}}};function findView(e,t){let n=null;return e.eachChildView(e=>t(e)?(n=e,!1):(n=findView(e,t),n===null)),n}function closeOpenBottomSheet(e){let t=!1;return e.eachChildView(e=>e.visibility===`visible`?closeOpenBottomSheet(e)?(t=!0,!1):e instanceof a&&e.open&&e.canClose?(e.open=!1,t=!0,!1):!0:!0),t}const popsOnBack=e=>typeof e.popFromShortcut==`function`;function popInnermostNavigation(e){let t=!1;return e.eachChildView(e=>e.visibility===`visible`&&(popInnermostNavigation(e)||popsOnBack(e)&&e.isLoaded&&e.popFromShortcut()===`stop`)?(t=!0,!1):!0),t}o(g.prototype);export{h as CLOSE_REQUEST,g as GtkWindow,m as NOTIFY_FOCUS_WIDGET,f as NOTIFY_IS_ACTIVE,p as NOTIFY_MAXIMIZED};
1
+ import"../_virtual/_rolldown/runtime.js";import{applyConstructProps as e}from"./construct-props.js";import{xmlBoolean as t,xmlNumber as n}from"./xml-values.js";import{surfaceSize as r}from"./window-state.js";import{windowHost as i}from"../window-host.js";import{AdwBottomSheet as a}from"./adw-bottom-sheet.js";import{defineWindowApplication as o}from"./application.js";import{AdwSingleChildBase as s}from"./single-child-base.js";import{CloseRequestState as c,GDK_KEYS as l,HandledAccumulator as u,WindowMemberState as d,deliverKeyToControllers as f,stepDefaultSize as p}from"@gjsify/adwaita-core";const m=`notify::is-active`,h=`notify::maximized`,g=`notify::focus-widget`,_=`close-request`;var v=class GtkWindow extends s{static GTypeName=`GtkWindow`;_title=``;_defaultWidth=0;_defaultHeight=0;_members=new d(e=>{let t=e===`is-active`?m:h;this.notify({eventName:t,object:this,value:e===`is-active`?this.isActive:this.maximized})},{maximized:!0});_closeRequest=new c;_unwatchForeground=null;_unwatchBack=null;constructor(t){super(),e(this,t)}onLoaded(){super.onLoaded();let e=i();this._unwatchForeground?.(),this._unwatchForeground=e.watchForeground(e=>this._members.reportActive(e)),this._members.reportActive(e.isForeground()),this._unwatchBack?.(),this._unwatchBack=this._isToplevel()?e.watchBack(()=>this._handleBack()):null}onUnloaded(){this._unwatchForeground?.(),this._unwatchForeground=null,this._unwatchBack?.(),this._unwatchBack=null,this._members.reportActive(!1),super.onUnloaded()}get isActive(){return this._members.active}get is_active(){return this._members.active}get maximized(){return this._members.maximized}set maximized(e){t(e,!0)?this.maximize():this.unmaximize()}is_maximized(){return this.maximized}maximize(){}unmaximize(){throw Error(`GtkWindow.unmaximize is not supported on NativeScript: the window is the whole screen and the platform has no un-maximized state to go back to.`)}present(){}get focusWidget(){return this.get_focus()}get focus_widget(){return this.get_focus()}set focus_widget(e){this.set_focus(e)}get_focus(){let e=i();return findView(this,t=>e.isFocused(t))}set_focus(e){let t=i();if(e===null){let e=this.get_focus();e!==null&&t.clearFocus(e);return}if(findView(this,t=>t===e)===null)throw Error(`GtkWindow.set_focus: the widget is not a descendant of this window.`);t.requestFocus(e)}close(){let e=i();if(this.isLoaded&&!e.canFinish)throw Error(`GtkWindow.close is not supported on this platform: iOS has no public API to close the root window. Android finishes the foreground activity.`);this._requestClose()}_requestClose(){let e=i();this._closeRequest.close({realized:this.isLoaded,hideOnClose:!1,emit:()=>{let e=new u;return this.notify({eventName:_,object:this,accumulator:e}),e.stopped},hide:()=>{},destroy:()=>e.finish()})}_handleBack(){return this._consumeBack()||closeOpenBottomSheet(this)||popInnermostNavigation(this)||this._deliverBackKey()||this._requestClose(),!0}_deliverBackKey(){return f(this,{key:`BrowserBack`,keycode:l.KEY_Back,state:0,pressed:!0})}_consumeBack(){return!1}_isToplevel(){for(let e=this.parent;e;e=e.parent)if(e instanceof GtkWindow)return!1;return!0}connect(e,t){if(e===`notify::focus-widget`)throw Error(`GtkWindow notify::focus-widget is not supported on NativeScript: focus the user moves is not observable here. Read get_focus() when you need it.`);return super.connect(e,t)}get title(){return this._title}set title(e){this._title=e??``}get defaultWidth(){return this._defaultWidth}set defaultWidth(e){this._defaultWidth=r(n(e,NaN),e,this._defaultWidth,`defaultWidth`)}get defaultHeight(){return this._defaultHeight}set defaultHeight(e){this._defaultHeight=r(n(e,NaN),e,this._defaultHeight,`defaultHeight`)}get_default_size(){return[this._defaultWidth,this._defaultHeight]}set_default_size(e,t){let n=p(this.get_default_size(),e,t);if(n!==null){this._defaultWidth=n.width,this._defaultHeight=n.height;for(let e of n.changed){let t=e===`default-width`?n.width:n.height;this.notify({eventName:`notify::${e}`,object:this,value:t})}}}};function findView(e,t){let n=null;return e.eachChildView(e=>t(e)?(n=e,!1):(n=findView(e,t),n===null)),n}function closeOpenBottomSheet(e){let t=!1;return e.eachChildView(e=>e.visibility===`visible`?closeOpenBottomSheet(e)?(t=!0,!1):e instanceof a&&e.open&&e.canClose?(e.open=!1,t=!0,!1):!0:!0),t}const popsOnBack=e=>typeof e.popFromShortcut==`function`;function popInnermostNavigation(e){let t=!1;return e.eachChildView(e=>e.visibility===`visible`&&(popInnermostNavigation(e)||popsOnBack(e)&&e.isLoaded&&e.popFromShortcut()===`stop`)?(t=!0,!1):!0),t}o(v.prototype);export{_ as CLOSE_REQUEST,v as GtkWindow,g as NOTIFY_FOCUS_WIDGET,m as NOTIFY_IS_ACTIVE,h as NOTIFY_MAXIMIZED};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{stripMnemonic as e}from"@gjsify/adwaita-core";import{FormattedString as t,Span as n}from"@nativescript/core";function decoration(e,t){let n=e.underline||t;if(n&&e.strikethrough)return`underline line-through`;if(n)return`underline`;if(e.strikethrough)return`line-through`}const r={thin:`100`,ultralight:`200`,light:`300`,normal:`normal`,medium:`500`,semibold:`600`,bold:`bold`,ultrabold:`800`,heavy:`900`},i=new Set([`100`,`200`,`300`,`400`,`500`,`600`,`700`,`800`,`900`]);function applySpanAttributes(e,t){for(let[n,a]of Object.entries(t))switch(n){case`font_family`:case`family`:e.fontFamily=a;break;case`font_style`:case`style`:(a===`normal`||a===`italic`)&&(e.fontStyle=a);break;case`font_weight`:case`weight`:{let t=r[a]??(i.has(a)?a:void 0);t!==void 0&&(e.fontWeight=t);break}case`underline`:a!==`none`&&(e.textDecoration=`underline`);break;case`strikethrough`:a!==`false`&&a!==`none`&&(e.textDecoration=`line-through`);break;default:break}}function labelMarkupSpan(t,r,i){let a=new n;a.text=r?e(t.text):t.text;for(let e of t.style.spans)applySpanAttributes(a,e);t.style.monospace&&(a.fontFamily=`monospace`),t.style.bold&&(a.fontWeight=`bold`),t.style.italic&&(a.fontStyle=`italic`);let o=decoration(t.style,t.link!==null);o!==void 0&&(a.textDecoration=o),t.style.script!==null&&(a.style.verticalAlignment=t.style.script);let s=t.style.sizeSteps;return s!==0&&i!==void 0&&(a.fontSize=i*(s>0?1.2:.8333333333333)**Math.abs(s)),a}function labelMarkupNeedsSpans(e){return e.links.length>0?!0:e.runs.some(e=>e.link!==null||styled(e.style))}function styled(e){return e.bold||e.italic||e.underline||e.strikethrough||e.monospace||e.script!==null||e.sizeSteps!==0||e.spans.length>0}function labelMarkupFormattedString(e,r,i,a){let o=new t;for(let t of e.runs){let e=labelMarkupSpan(t,r,i);if(t.link!==null){let r=t.link;e.addEventListener(n.linkTapEvent,()=>a(r))}o.spans.push(e)}return o}export{labelMarkupFormattedString,labelMarkupNeedsSpans,labelMarkupSpan};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{ENGINE_TARGET as e}from"../engine-target.js";import{camelProperty as t,readGtkProperty as n,writeGtkProperty as r}from"./shadowed-properties.js";import{WIDGET_SIGNALS as i,watchMapping as a}from"./widget-mapping.js";import{withGtkWidgetLayout as o}from"./widget-layout.js";import{engineForTarget as s}from"@gjsify/adwaita-core";function coerceDeclared(e,t,n,r){return t.normalize===void 0?readDeclaredValue(e,t.kind,n):t.normalize(n,r)}function readDeclaredValue(e,t,n){if(typeof n!=`string`||t===`string`)return n;let r=n.trim();if(t===`boolean`){let t=r.toLowerCase();if(t===`true`)return!0;if(t===`false`)return!1;throw TypeError(`Property '${e}' is a boolean; '${n}' is neither 'true' nor 'false'.`)}let i=r===``?NaN:Number(r);if(!Number.isFinite(i))throw TypeError(`Property '${e}' is a number; '${n}' is not one.`);return i}const c=new WeakMap;let l=1;const u=1073741824,d=new WeakMap,f=new WeakMap;function unknownHandler(e,t){return TypeError(`${e.constructor.name} has no handler with id ${t}. connect() hands out each id once and disconnect() takes it once; a second disconnect, or an id another widget returned, is refused here rather than left as a silent no-op.`)}const p=new WeakMap;function pureConnect(e,t,n){let r=l++,o=c.get(e);o===void 0&&(o=new Map,c.set(e,o));let s=i.includes(t)?a(e):void 0;return o.set(r,{eventName:t,listener:n,unwatch:s}),e.addEventListener(t,n),r}function pureDisconnect(e,t){let n=c.get(e)?.get(t);if(n===void 0)throw unknownHandler(e,t);e.removeEventListener(n.eventName,n.listener),n.unwatch?.(),c.get(e)?.delete(t)}function declaredConnect(e,t,n,r){let i=l++,a=p.get(e);return a===void 0&&p.set(e,a=new Map),a.set(i,{key:t,eventName:n,callback:r}),i}function declaredDisconnect(e,t){return p.get(e)?.delete(t)===!0}function emitDeclared(e,t,n){let r=p.get(e);if(r===void 0)return;let i=t.startsWith(`notify::`),a=[...r];for(let[o,s]of a){if(s.key!==t||r.get(o)!==s)continue;let a=i?{eventName:s.eventName,object:e}:{eventName:s.eventName,object:e,args:n};try{s.callback(e,a)}catch(t){console.error(`[${e.constructor.name}] unhandled exception in a '${s.eventName}' handler:`,t)}}}function refuseDeclaredEvent(e,t,n){let r=giKeyOf(resolvedFor(e.constructor),t);if(r===null)return;let i=r.startsWith(`notify::`),a=i?`a declared property's notification`:`a declared signal`,o=n===`notify`?i?`write the property, or emit it with notify('${r.slice(8)}')`:`emit it with emit('${r}', …)`:`subscribe with connect('${t}', (self, data) => …), whose id disconnect() takes`;throw TypeError(`${e.constructor.name}.${n}('${t}'): '${r}' is ${a} and GObject owns it — ${o}. On Android the emission belongs to the GObject and no NativeScript listener can see it, so ${n} would work off-device and be silent on it.`)}function spellingsOf(e){return[...new Set([e,e.replace(/-/g,`_`),t(e)])]}function emittedSignalsOf(e){let t=[];for(let n=e;typeof n==`function`;n=Object.getPrototypeOf(n))t.unshift(n);let n=new Set;for(let e of t)if(Object.hasOwn(e,`emittedSignals`))for(let t of e.emittedSignals)n.add(t);return[...n]}const m=new WeakMap,h=new WeakSet,g=new WeakSet,_=new WeakMap;function declarationsOf(e){let t=[];for(let n=e;typeof n==`function`;n=Object.getPrototypeOf(n)){let e=m.get(n);e!==void 0&&t.unshift(e)}return t}function resolvedFor(e){let t=_.get(e);if(t!==void 0)return t;let n=new Map,r=new Set,i={canonicalOf:n,declaredSignals:r,routeD:!1,giConnect:void 0,giDisconnect:void 0,giEmit:void 0},a=i;for(let t of declarationsOf(e)){for(let[e,r]of t.canonicalOf)n.set(e,r);for(let e of t.declaredSignals)r.add(e);t.routeD&&(a.routeD=!0),t.giConnect!==void 0&&(a.giConnect=t.giConnect),t.giDisconnect!==void 0&&(a.giDisconnect=t.giDisconnect),t.giEmit!==void 0&&(a.giEmit=t.giEmit)}return _.set(e,i),i}function giKeyOf(e,t){if(e.declaredSignals.has(t))return t;if(!t.startsWith(`notify::`))return null;let n=e.canonicalOf.get(t.slice(8));return n===void 0?null:`notify::${n}`}function declare(e,t,n){let r=new Map;for(let e of Object.keys(t?.Properties??{}))for(let t of spellingsOf(e))r.set(t,e);let i={meta:t,klass:e,prototype:e.prototype,canonicalOf:r,declaredSignals:new Set(Object.keys(t?.Signals??{})),routers:n,realized:!1,routeD:!1};return m.set(e,i),i}function declaredEmissionsOf(e){return[...Object.keys(e?.Signals??{}),...Object.keys(e?.Properties??{}).map(e=>`notify::${e}`)]}function realizeChain(e){if(!h.has(e)){h.add(e);for(let t of declarationsOf(e))realize(t)}}function realize(t){if(t.realized||(t.realized=!0,t.meta===void 0))return;let n=s(e);if(n?.supportsForeignParentClasses===!0){registerRouteD(t,n.registerForeignClass.bind(n));return}installPureJsProperties(t)}function registerRouteD(e,t){let{meta:n,prototype:r,routers:i}=e;if(i!==void 0&&(delete r.connect,delete r.disconnect,delete r.emit,delete r.notify),t(e.klass,n),wrapRouteDAccessors(e),i!==void 0){if(e.giConnect=r.connect,e.giDisconnect=r.disconnect,e.giEmit=r.emit,e.giConnect===void 0||e.giDisconnect===void 0||e.giEmit===void 0)throw Error(`Registering '${n.GTypeName}' over its NativeScript base installed no connect/disconnect/emit, so the widget would answer neither GObject nor this port. ADR 0105 refuses a silent fallback here: the subset is reachable only by calling usePureJsGObjectEngine() from '@gjsify/adwaita-core' before the port loads.`);for(let[e,t]of Object.entries(i))Object.defineProperty(r,e,{configurable:!0,writable:!0,enumerable:!1,value:t});refuseDeclaredNotifyPayload(r,r.notify)}e.routeD=!0}function refuseDeclaredNotifyPayload(e,t){let n=function notify(e,...n){if(typeof e==`object`&&e){let{eventName:t}=e;typeof t==`string`&&refuseDeclaredEvent(this,t,`notify`)}return t.call(this,e,...n)};g.add(n),Object.defineProperty(e,"notify",{configurable:!0,writable:!0,enumerable:!1,value:n})}function wrapRouteDAccessors(e){let{meta:t,prototype:n}=e;for(let[e,r]of Object.entries(t.Properties??{}))if(!(r.kind===`string`&&r.normalize===void 0))for(let i of spellingsOf(e)){let a=Object.getOwnPropertyDescriptor(n,i);if(a?.set===void 0)throw Error(`Registering '${t.GTypeName}' installed no setter for '${i}', so a string from XML would reach the GObject uncoerced. The host chain probably owns that name (see the class's \$foreignSkipped); rename the property.`);let o=a.set;Object.defineProperty(n,i,{...a,set(t){o.call(this,coerceDeclared(e,r,t,this))}})}}function installPureJsProperties(e){let{meta:t,prototype:n}=e;for(let[e,r]of Object.entries(t.Properties??{})){let t=defaultValueOf(r);for(let i of spellingsOf(e))i in n||Object.defineProperty(n,i,{configurable:!0,enumerable:!1,get(){let n=valuesOf(this);return n.has(e)||n.set(e,t),n.get(e)},set(t){let n=coerceDeclared(e,r,t,this),i=valuesOf(this);i.has(e)&&i.get(e)===n||(i.set(e,n),emitDeclared(this,`notify::${e}`,[]))}})}installPureNotify(e)}function installPureNotify(e){let{prototype:t}=e,n=t.notify;if(g.has(n))return;let r=function notify(e,...t){if(typeof e!=`string`){if(typeof e==`object`&&e){let{eventName:t}=e;typeof t==`string`&&refuseDeclaredEvent(this,t,`notify`)}return n.call(this,e,...t)}let{canonicalOf:r}=resolvedFor(this.constructor),i=r.get(e);if(i===void 0)throw TypeError(`${this.constructor.name} has no property '${e}' to notify. The declared ones are ${[...r.keys()].join(`, `)||`(none)`}; a NativeScript event is notified with its payload object, not with a name.`);emitDeclared(this,`notify::${i}`,[])};g.add(r),Object.defineProperty(t,"notify",{configurable:!0,writable:!0,enumerable:!1,value:r})}function withSignals(e,a){class WithSignals extends o(e){static emittedSignals=[...i,...declaredEmissionsOf(a)];constructor(...e){super(...e),realizeChain(new.target)}addEventListener(e,t,n,r){refuseDeclaredEvent(this,e,`addEventListener`),super.addEventListener(e,t,n,r)}removeEventListener(e,t,n){refuseDeclaredEvent(this,e,`removeEventListener`),super.removeEventListener(e,t,n)}connect(e,t){let n=resolvedFor(this.constructor),r=giKeyOf(n,e);if(n.routeD&&r!==null){let i=r.startsWith(`notify::`),a=n.giConnect.call(this,r,(n,...r)=>{let a=n;return t(n,i?{eventName:e,object:a}:{eventName:e,object:a,args:r})}),o=d.get(this);return o===void 0&&d.set(this,o=new Set),o.add(a),u+a}if(r!==null)return declaredConnect(this,r,e,t);let listener=e=>{let n=e.accumulator;if(n===void 0){t(this,e);return}n.stopped||n.collect(t(this,e))};return pureConnect(this,e,listener)}disconnect(e){if(e>=u){let t=e-u;if(d.get(this)?.delete(t)!==!0)throw unknownHandler(this,e);resolvedFor(this.constructor).giDisconnect.call(this,t);return}declaredDisconnect(this,e)||pureDisconnect(this,e)}emit(e,...t){let n=resolvedFor(this.constructor),r=giKeyOf(n,e);if(r!==null){n.routeD?n.giEmit.call(this,r,...t):emitDeclared(this,r,t);return}throw Error(`No signal '${e}' on object '${this.constructor.name}'. emit() is GObject's and takes a declared signal or a declared property's notify::<prop>; to dispatch a NativeScript event use notify({ eventName: '${e}', object: this }).`)}get_property(e){return n(this,t(e))}set_property(e,n){r(this,t(e),n)}}return declare(WithSignals,a,{connect:WithSignals.prototype.connect,disconnect:WithSignals.prototype.disconnect,emit:WithSignals.prototype.emit}),WithSignals}function withProperties(e,t){class WithProperties extends e{static emittedSignals=declaredEmissionsOf(t)}return declare(WithProperties,t,void 0),WithProperties}function valuesOf(e){let t=f.get(e);return t===void 0&&f.set(e,t=new Map),t}function defaultValueOf(e){return e.default===void 0?e.kind===`string`?``:e.kind===`boolean`?!1:0:e.default}export{emittedSignalsOf,readDeclaredValue,withProperties,withSignals};
1
+ import"../_virtual/_rolldown/runtime.js";import{ENGINE_TARGET as e}from"../engine-target.js";import{camelProperty as t,readGtkProperty as n,writeGtkProperty as r}from"./shadowed-properties.js";import{WIDGET_SIGNALS as i,watchMapping as a}from"./widget-mapping.js";import{withGtkWidgetLayout as o}from"./widget-layout.js";import{engineForTarget as s}from"@gjsify/adwaita-core";function coerceDeclared(e,t,n,r){return t.normalize===void 0?readDeclaredValue(e,t.kind,n):t.normalize(n,r)}function isDeclaredChange(e,t,n,r,i){return e.changed===void 0?n!==t:e.changed(t,n,r,i)}function readDeclaredValue(e,t,n){if(typeof n!=`string`||t===`string`)return n;let r=n.trim();if(t===`object`)throw TypeError(`Property '${e}' holds an object; '${n}' is a string.`);if(t===`boolean`){let t=r.toLowerCase();if(t===`true`)return!0;if(t===`false`)return!1;throw TypeError(`Property '${e}' is a boolean; '${n}' is neither 'true' nor 'false'.`)}let i=r===``?NaN:Number(r);if(!Number.isFinite(i))throw TypeError(`Property '${e}' is a number; '${n}' is not one.`);return i}const c=new WeakMap;let l=1;const u=1073741824,d=new WeakMap,f=new WeakMap;function unknownHandler(e,t){return TypeError(`${e.constructor.name} has no handler with id ${t}. connect() hands out each id once and disconnect() takes it once; a second disconnect, or an id another widget returned, is refused here rather than left as a silent no-op.`)}const p=new WeakMap;function pureConnect(e,t,n){let r=l++,o=c.get(e);o===void 0&&(o=new Map,c.set(e,o));let s=i.includes(t)?a(e):void 0;return o.set(r,{eventName:t,listener:n,unwatch:s}),e.addEventListener(t,n),r}function pureDisconnect(e,t){let n=c.get(e)?.get(t);if(n===void 0)throw unknownHandler(e,t);e.removeEventListener(n.eventName,n.listener),n.unwatch?.(),c.get(e)?.delete(t)}function declaredConnect(e,t,n,r){let i=l++,a=p.get(e);return a===void 0&&p.set(e,a=new Map),a.set(i,{key:t,eventName:n,callback:r}),i}function declaredDisconnect(e,t){return p.get(e)?.delete(t)===!0}function emitDeclared(e,t,n){let r=p.get(e);if(r===void 0)return;let i=t.startsWith(`notify::`),a=[...r];for(let[o,s]of a){if(s.key!==t||r.get(o)!==s)continue;let a=i?{eventName:s.eventName,object:e}:{eventName:s.eventName,object:e,args:n};try{s.callback(e,a)}catch(t){console.error(`[${e.constructor.name}] unhandled exception in a '${s.eventName}' handler:`,t)}}}function refuseDeclaredEvent(e,t,n){let r=giKeyOf(resolvedFor(e.constructor),t);if(r===null)return;let i=r.startsWith(`notify::`),a=i?`a declared property's notification`:`a declared signal`,o=n===`notify`?i?`write the property, or emit it with notify('${r.slice(8)}')`:`emit it with emit('${r}', …)`:`subscribe with connect('${t}', (self, data) => …), whose id disconnect() takes`;throw TypeError(`${e.constructor.name}.${n}('${t}'): '${r}' is ${a} and GObject owns it — ${o}. On Android the emission belongs to the GObject and no NativeScript listener can see it, so ${n} would work off-device and be silent on it.`)}function spellingsOf(e){return[...new Set([e,e.replace(/-/g,`_`),t(e)])]}function emittedSignalsOf(e){let t=[];for(let n=e;typeof n==`function`;n=Object.getPrototypeOf(n))t.unshift(n);let n=new Set;for(let e of t)if(Object.hasOwn(e,`emittedSignals`))for(let t of e.emittedSignals)n.add(t);return[...n]}const m=new WeakMap,h=new WeakSet,g=new WeakSet,_=new WeakMap;function declarationsOf(e){let t=[];for(let n=e;typeof n==`function`;n=Object.getPrototypeOf(n)){let e=m.get(n);e!==void 0&&t.unshift(e)}return t}function resolvedFor(e){let t=_.get(e);if(t!==void 0)return t;let n=new Map,r=new Set,i={canonicalOf:n,declaredSignals:r,routeD:!1,giConnect:void 0,giDisconnect:void 0,giEmit:void 0},a=i;for(let t of declarationsOf(e)){for(let[e,r]of t.canonicalOf)n.set(e,r);for(let e of t.declaredSignals)r.add(e);t.routeD&&(a.routeD=!0),t.giConnect!==void 0&&(a.giConnect=t.giConnect),t.giDisconnect!==void 0&&(a.giDisconnect=t.giDisconnect),t.giEmit!==void 0&&(a.giEmit=t.giEmit)}return _.set(e,i),i}function giKeyOf(e,t){if(e.declaredSignals.has(t))return t;if(!t.startsWith(`notify::`))return null;let n=e.canonicalOf.get(t.slice(8));return n===void 0?null:`notify::${n}`}function declare(e,t,n){let r=new Map;for(let e of Object.keys(t?.Properties??{}))for(let t of spellingsOf(e))r.set(t,e);let i={meta:t,klass:e,prototype:e.prototype,canonicalOf:r,declaredSignals:new Set(Object.keys(t?.Signals??{})),routers:n,realized:!1,routeD:!1};return m.set(e,i),i}function declaredEmissionsOf(e){return[...Object.keys(e?.Signals??{}),...Object.keys(e?.Properties??{}).map(e=>`notify::${e}`)]}function realizeChain(e){if(!h.has(e)){h.add(e);for(let t of declarationsOf(e))realize(t)}}function realize(t){if(t.realized||(t.realized=!0,t.meta===void 0))return;let n=s(e);if(n?.supportsForeignParentClasses===!0){registerRouteD(t,n.registerForeignClass.bind(n));return}installPureJsProperties(t)}function registerRouteD(e,t){let{meta:n,prototype:r,routers:i}=e;if(i!==void 0&&(delete r.connect,delete r.disconnect,delete r.emit,delete r.notify),t(e.klass,n),wrapRouteDAccessors(e),i!==void 0){if(e.giConnect=r.connect,e.giDisconnect=r.disconnect,e.giEmit=r.emit,e.giConnect===void 0||e.giDisconnect===void 0||e.giEmit===void 0)throw Error(`Registering '${n.GTypeName}' over its NativeScript base installed no connect/disconnect/emit, so the widget would answer neither GObject nor this port. ADR 0105 refuses a silent fallback here: the subset is reachable only by calling usePureJsGObjectEngine() from '@gjsify/adwaita-core' before the port loads.`);for(let[e,t]of Object.entries(i))Object.defineProperty(r,e,{configurable:!0,writable:!0,enumerable:!1,value:t});refuseDeclaredNotifyPayload(r,r.notify)}e.routeD=!0}function refuseDeclaredNotifyPayload(e,t){let n=function notify(e,...n){if(typeof e==`object`&&e){let{eventName:t}=e;typeof t==`string`&&refuseDeclaredEvent(this,t,`notify`)}return t.call(this,e,...n)};g.add(n),Object.defineProperty(e,"notify",{configurable:!0,writable:!0,enumerable:!1,value:n})}function wrapRouteDAccessors(e){let{meta:t,prototype:n}=e;for(let[e,r]of Object.entries(t.Properties??{}))if(!(r.kind===`string`&&r.normalize===void 0))for(let i of spellingsOf(e)){let a=Object.getOwnPropertyDescriptor(n,i);if(a?.set===void 0)throw Error(`Registering '${t.GTypeName}' installed no setter for '${i}', so a string from XML would reach the GObject uncoerced. The host chain probably owns that name (see the class's \$foreignSkipped); rename the property.`);let o=a.set;Object.defineProperty(n,i,{...a,set(t){o.call(this,coerceDeclared(e,r,t,this))}})}}function installPureJsProperties(e){let{meta:t,prototype:n}=e;for(let[e,r]of Object.entries(t.Properties??{})){let t=defaultValueOf(r);for(let i of spellingsOf(e))i in n||Object.defineProperty(n,i,{configurable:!0,enumerable:!1,get(){let n=valuesOf(this);return n.has(e)||n.set(e,t),n.get(e)},set(t){let n=coerceDeclared(e,r,t,this),i=valuesOf(this);i.has(e)&&!isDeclaredChange(r,n,i.get(e),t,this)||(i.set(e,n),emitDeclared(this,`notify::${e}`,[]),r.afterNotify?.(this))}})}installPureNotify(e)}function installPureNotify(e){let{prototype:t}=e,n=t.notify;if(g.has(n))return;let r=function notify(e,...t){if(typeof e!=`string`){if(typeof e==`object`&&e){let{eventName:t}=e;typeof t==`string`&&refuseDeclaredEvent(this,t,`notify`)}return n.call(this,e,...t)}let{canonicalOf:r}=resolvedFor(this.constructor),i=r.get(e);if(i===void 0)throw TypeError(`${this.constructor.name} has no property '${e}' to notify. The declared ones are ${[...r.keys()].join(`, `)||`(none)`}; a NativeScript event is notified with its payload object, not with a name.`);emitDeclared(this,`notify::${i}`,[])};g.add(r),Object.defineProperty(t,"notify",{configurable:!0,writable:!0,enumerable:!1,value:r})}function withSignals(e,a){class WithSignals extends o(e){static emittedSignals=[...i,...declaredEmissionsOf(a)];constructor(...e){super(...e),realizeChain(new.target)}addEventListener(e,t,n,r){refuseDeclaredEvent(this,e,`addEventListener`),super.addEventListener(e,t,n,r)}removeEventListener(e,t,n){refuseDeclaredEvent(this,e,`removeEventListener`),super.removeEventListener(e,t,n)}connect(e,t){let n=resolvedFor(this.constructor),r=giKeyOf(n,e);if(n.routeD&&r!==null){let i=r.startsWith(`notify::`),a=n.giConnect.call(this,r,(n,...r)=>{let a=n;return t(n,i?{eventName:e,object:a}:{eventName:e,object:a,args:r})}),o=d.get(this);return o===void 0&&d.set(this,o=new Set),o.add(a),u+a}if(r!==null)return declaredConnect(this,r,e,t);let listener=e=>{let n=e.accumulator;if(n===void 0){t(this,e);return}n.stopped||n.collect(t(this,e))};return pureConnect(this,e,listener)}disconnect(e){if(e>=u){let t=e-u;if(d.get(this)?.delete(t)!==!0)throw unknownHandler(this,e);resolvedFor(this.constructor).giDisconnect.call(this,t);return}declaredDisconnect(this,e)||pureDisconnect(this,e)}emit(e,...t){let n=resolvedFor(this.constructor),r=giKeyOf(n,e);if(r!==null){n.routeD?n.giEmit.call(this,r,...t):emitDeclared(this,r,t);return}throw Error(`No signal '${e}' on object '${this.constructor.name}'. emit() is GObject's and takes a declared signal or a declared property's notify::<prop>; to dispatch a NativeScript event use notify({ eventName: '${e}', object: this }).`)}get_property(e){return n(this,t(e))}set_property(e,n){r(this,t(e),n)}}return declare(WithSignals,a,{connect:WithSignals.prototype.connect,disconnect:WithSignals.prototype.disconnect,emit:WithSignals.prototype.emit}),WithSignals}function withProperties(e,t){class WithProperties extends e{static emittedSignals=declaredEmissionsOf(t)}return declare(WithProperties,t,void 0),WithProperties}function valuesOf(e){let t=f.get(e);return t===void 0&&f.set(e,t=new Map),t}function defaultValueOf(e){return e.kind===`object`?null:e.default===void 0?e.kind===`string`?``:e.kind===`boolean`?!1:0:e.default}export{emittedSignalsOf,readDeclaredValue,withProperties,withSignals};
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{blurView as e,finishWindow as t,focusView as n,isViewFocused as r,watchBackButton as i}from"./window-source.js";import{Application as a}from"@nativescript/core";let o=null;function useWindowHost(e){o=e}const s={canFinish:!1,isForeground:()=>!0,watchForeground(e){let resume=()=>e(!0),suspend=()=>e(!1);return a.on(`resume`,resume),a.on(`suspend`,suspend),()=>{a.off(`resume`,resume),a.off(`suspend`,suspend)}},watchBack(e){return i(t=>{e()&&(t.cancel=!0)})},finish:t,isFocused:r,requestFocus:n,clearFocus:e};function windowHost(){return o??s}export{s as nativeWindowHost,useWindowHost,windowHost};
1
+ import"./_virtual/_rolldown/runtime.js";import{blurView as e,canFinishWindow as t,finishWindow as n,focusView as r,isViewFocused as i,watchBackButton as a}from"./window-source.js";import{Application as o}from"@nativescript/core";let s=null;function useWindowHost(e){s=e}const c={get canFinish(){return t()},isForeground:()=>!0,watchForeground(e){let resume=()=>e(!0),suspend=()=>e(!1);return o.on(`resume`,resume),o.on(`suspend`,suspend),()=>{o.off(`resume`,resume),o.off(`suspend`,suspend)}},watchBack(e){return a(t=>{e()&&(t.cancel=!0)})},finish:n,isFocused:i,requestFocus:r,clearFocus:e};function windowHost(){return s??c}export{c as nativeWindowHost,useWindowHost,windowHost};
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{Application as e}from"@nativescript/core";const t=!0,n=`activityBackPressed`;function watchBackButton(t){let r=e.android;return r?(r.on(n,t),()=>r.off(n,t)):()=>{}}function finishWindow(){let t=e.android?.foregroundActivity??e.android?.startActivity;if(!t?.finish)throw Error(`Android has no activity to finish for this window`);t.finish()}const peer=e=>e.nativeViewProtected;function isViewFocused(e){return peer(e)?.isFocused?.()===!0}function focusView(e){peer(e)?.requestFocus?.()}function blurView(e){peer(e)?.clearFocus?.()}export{blurView,t as canFinishWindow,finishWindow,focusView,isViewFocused,watchBackButton};
1
+ import"./_virtual/_rolldown/runtime.js";import{Application as e}from"@nativescript/core";function canFinishWindow(){return!0}const t=`activityBackPressed`;function watchBackButton(n){let r=e.android;return r?(r.on(t,n),()=>r.off(t,n)):()=>{}}function finishWindow(){let t=e.android?.foregroundActivity??e.android?.startActivity;if(!t?.finish)throw Error(`Android has no activity to finish for this window`);t.finish()}const peer=e=>e.nativeViewProtected;function isViewFocused(e){return peer(e)?.isFocused?.()===!0}function focusView(e){peer(e)?.requestFocus?.()}function blurView(e){peer(e)?.clearFocus?.()}export{blurView,canFinishWindow,finishWindow,focusView,isViewFocused,watchBackButton};
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";const e=!1;function finishWindow(){throw Error(`iOS has no public API for an app to close its own window`)}const peer=e=>e.nativeViewProtected;function isViewFocused(e){return peer(e)?.isFirstResponder===!0}function focusView(e){peer(e)?.becomeFirstResponder?.()}function blurView(e){peer(e)?.resignFirstResponder?.()}function watchBackButton(e){return()=>{}}export{blurView,e as canFinishWindow,finishWindow,focusView,isViewFocused,watchBackButton};
1
+ import"./_virtual/_rolldown/runtime.js";function canFinishWindow(){return!1}function finishWindow(){throw Error(`iOS has no public API for an app to close its own window`)}const peer=e=>e.nativeViewProtected;function isViewFocused(e){return peer(e)?.isFirstResponder===!0}function focusView(e){peer(e)?.becomeFirstResponder?.()}function blurView(e){peer(e)?.resignFirstResponder?.()}function watchBackButton(e){return()=>{}}export{blurView,canFinishWindow,finishWindow,focusView,isViewFocused,watchBackButton};
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";const e=!1;function finishWindow(){throw Error(`there is no platform window to close on this host`)}function isViewFocused(e){throw Error(`there is no platform focus to read on this host`)}function focusView(e){throw Error(`there is no platform focus to move on this host`)}function blurView(e){throw Error(`there is no platform focus to clear on this host`)}function watchBackButton(e){return()=>{}}export{blurView,e as canFinishWindow,finishWindow,focusView,isViewFocused,watchBackButton};
1
+ import"./_virtual/_rolldown/runtime.js";function canFinishWindow(){return!1}function finishWindow(){throw Error(`there is no platform window to close on this host`)}function isViewFocused(e){throw Error(`there is no platform focus to read on this host`)}function focusView(e){throw Error(`there is no platform focus to move on this host`)}function blurView(e){throw Error(`there is no platform focus to clear on this host`)}function watchBackButton(e){return()=>{}}export{blurView,canFinishWindow,finishWindow,focusView,isViewFocused,watchBackButton};
@@ -64,8 +64,10 @@ export interface BuildOptions {
64
64
  template?: TemplateScope;
65
65
  /**
66
66
  * Translates a string the `.blp` marked with `_()` or `C_()`, as GtkBuilder does with its
67
- * gettext domain. Called with the authored text and the `C_()` context, if any. Without it a
68
- * marked string stays as authored, which is English: the marking is carried, not acted on.
67
+ * gettext domain. Called with the authored text and the `C_()` context, if any. Without it the
68
+ * translator the platform registered answers (`registerDefaultTranslate` — on Android the real
69
+ * opt-in installs GLib's default-domain gettext, as GtkBuilder uses when no domain is set), and
70
+ * with neither a marked string stays as authored, which is English: carried, not acted on.
69
71
  * Covers properties, the labels of `responses`, `strings [ ]` items and breakpoint setters.
70
72
  */
71
73
  translate?: (text: string, context?: string) => string;
@@ -0,0 +1 @@
1
+ export declare const AdwDefaultTranslateNsTest: () => Promise<void>;
@@ -0,0 +1 @@
1
+ export declare const GtkLabelMarkupNsTest: () => Promise<void>;
@@ -8,4 +8,4 @@ export declare const ContentProvider: Pick<typeof import("@gjsify/adwaita-core")
8
8
  export declare const ContentFormats: typeof import("@gjsify/adwaita-core").ContentFormats;
9
9
  export declare const AppLaunchContext: typeof import("@gjsify/adwaita-core").GdkAppLaunchContext;
10
10
  export declare const CURRENT_TIME = 0;
11
- export declare const KEY_space: 32, KEY_a: 97, KEY_d: 100, KEY_e: 101, KEY_q: 113, KEY_s: 115, KEY_w: 119, KEY_Return: 65293, KEY_Escape: 65307, KEY_Left: 65361, KEY_Up: 65362, KEY_Right: 65363, KEY_Down: 65364;
11
+ export declare const KEY_space: 32, KEY_a: 97, KEY_d: 100, KEY_e: 101, KEY_q: 113, KEY_s: 115, KEY_w: 119, KEY_Return: 65293, KEY_Escape: 65307, KEY_Left: 65361, KEY_Up: 65362, KEY_Right: 65363, KEY_Down: 65364, KEY_Back: 269025062;
@@ -53,6 +53,8 @@ export interface TouchGestureEventData extends EventData {
53
53
  export declare class Style extends Observable {
54
54
  #private;
55
55
  direction?: 'ltr' | 'rtl' | null;
56
+ /** In DIPs, and unset until written: `fontSizeProperty` carries no `defaultValue`. */
57
+ fontSize?: number;
56
58
  readonly viewRef: WeakRef<View>;
57
59
  constructor(view: View);
58
60
  get visibility(): string;
@@ -280,8 +282,96 @@ export declare class GridLayout extends LayoutBase {
280
282
  static setColumnSpan(view: View, value: number): void;
281
283
  static setRowSpan(view: View, value: number): void;
282
284
  }
285
+ /**
286
+ * A `Span`'s style — NOT a {@link View}'s {@link Style}.
287
+ *
288
+ * `Span extends ViewBase` upstream, so it has none of `View`'s shortcuts and carries only
289
+ * what a span can be given. Every member is unset until written, which is what the font
290
+ * properties answer on a device: `fontSizeProperty` and `fontFamilyProperty` are registered
291
+ * with no `defaultValue` (`ui/styling/style-properties.ts`).
292
+ */
293
+ export declare class SpanStyle extends Observable {
294
+ fontFamily: string | undefined;
295
+ fontSize: number | undefined;
296
+ fontStyle: string | undefined;
297
+ fontWeight: string | undefined;
298
+ textDecoration: string | undefined;
299
+ verticalAlignment: string | undefined;
300
+ }
301
+ /**
302
+ * One styled stretch of a {@link FormattedString}.
303
+ *
304
+ * The font and decoration members are ACCESSORS OVER `style`, as `ui/text-base/span.ts`
305
+ * has them — a double that made them own fields could not report a widget that wrote one
306
+ * and expected the other to see it.
307
+ */
308
+ export declare class Span extends Observable {
309
+ static readonly linkTapEvent = "linkTap";
310
+ readonly _style: SpanStyle;
311
+ get style(): SpanStyle;
312
+ /** NativeScript unescapes the two whitespace spellings a markup file can carry. */
313
+ private _text;
314
+ get text(): string;
315
+ set text(value: string);
316
+ get fontFamily(): string | undefined;
317
+ set fontFamily(value: string | undefined);
318
+ get fontSize(): number | undefined;
319
+ set fontSize(value: number | undefined);
320
+ get fontStyle(): string | undefined;
321
+ set fontStyle(value: string | undefined);
322
+ get fontWeight(): string | undefined;
323
+ set fontWeight(value: string | undefined);
324
+ get textDecoration(): string | undefined;
325
+ set textDecoration(value: string | undefined);
326
+ /**
327
+ * DERIVED, never written — upstream flips it from `addEventListener` /
328
+ * `removeEventListener` through `_setTappable(this.hasListeners(Span.linkTapEvent))`,
329
+ * and `setSpanModifiers` attaches the native `ClickableSpan` only for a tappable span.
330
+ * So subscribing IS what makes a span a link, and this reads the listeners rather than
331
+ * a flag a caller could set without one.
332
+ */
333
+ get tappable(): boolean;
334
+ }
335
+ /**
336
+ * The `ObservableArray<Span>` behind {@link FormattedString.spans}, as the four members
337
+ * that collection really offers.
338
+ *
339
+ * NOT A PLAIN ARRAY, and a double that used one would be the easier lie: `ObservableArray`
340
+ * reads by `getItem(pos)` and has no index access at all, so `spans[0]` is `undefined` on a
341
+ * device. A spec written against an array would pass here and read nothing there.
342
+ */
343
+ export declare class SpanList {
344
+ private readonly _items;
345
+ get length(): number;
346
+ push(span: Span): number;
347
+ /** A negative `pos` counts from the end, as upstream's does. */
348
+ getItem(pos: number): Span;
349
+ [Symbol.iterator](): Generator<Span, void, unknown>;
350
+ }
351
+ /** The rich-text value of a {@link Label} — a FLAT list of spans, no nesting. */
352
+ export declare class FormattedString extends Observable {
353
+ readonly spans: SpanList;
354
+ /** `formatted-string.ts`: the span texts concatenated, nothing between them. */
355
+ toString(): string;
356
+ }
283
357
  export declare class Label extends View {
284
- text: string;
358
+ private _text;
359
+ private _formattedText;
360
+ /**
361
+ * A write is a NO-OP while {@link formattedText} is set, as on a device:
362
+ * `[textProperty.setNative]` returns early when the label carries rich text
363
+ * (`ui/text-base/index.android.ts:192-195`), so the spans are what shows and this
364
+ * property is whatever the spans last said.
365
+ */
366
+ get text(): string;
367
+ set text(value: string);
368
+ /**
369
+ * Unset until something writes it — `formattedTextProperty` carries no `defaultValue`
370
+ * (`ui/text-base/text-base-common.ts:194`), so a label that was never given rich text
371
+ * reads `undefined`, not `null`.
372
+ */
373
+ get formattedText(): FormattedString | null | undefined;
374
+ set formattedText(value: FormattedString | null | undefined);
285
375
  textWrap: boolean;
286
376
  textAlignment: string;
287
377
  textOverflow: string;
@@ -84,8 +84,8 @@ export declare class AdwBanner extends AdwBanner_base {
84
84
  * Whether {@link title} is Pango markup. Defaults to TRUE, as in libadwaita
85
85
  * (:422-425).
86
86
  *
87
- * NS has no inline-markup layer, so markup is reduced to its plain text —
88
- * closer to what GTK paints than the raw tags would be.
87
+ * Markup is reduced to its plain text here — closer to what GTK paints than the raw
88
+ * tags would be, and deliberately not the drawn path `Gtk.Label` takes: see the header.
89
89
  */
90
90
  get useMarkup(): boolean;
91
91
  set useMarkup(value: boolean | string);
@@ -1,5 +1,5 @@
1
1
  import { Label, type EventData, type View } from '@nativescript/core';
2
- import type { AdwComboOption, AdwListModelInput } from '@gjsify/adwaita-core';
2
+ import type { AdwComboOption, ComboWatchableModel } from '@gjsify/adwaita-core';
3
3
  import { AdwActionRow } from './adw-action-row.js';
4
4
  import { GtkImage } from './gtk-image.js';
5
5
  import { type ConstructProps } from './construct-props.js';
@@ -27,6 +27,13 @@ export declare class AdwComboRow extends AdwActionRow {
27
27
  protected readonly _chevron: GtkImage;
28
28
  /** The headless options list + selectedIndex↔selectedValue state machine (ADR 0004). */
29
29
  private readonly _state;
30
+ /**
31
+ * The list the MARKUP door fills — `<adw:ComboRow model='[…]'>` is JSON text, and a real
32
+ * `Gio.ListModel` has no attribute spelling (ADR 0122 § 5). Held for the row's whole life so
33
+ * re-parsing the attribute splices the list the row already points at rather than replacing
34
+ * it, which would reset the selection.
35
+ */
36
+ private readonly _authored;
30
37
  /**
31
38
  * A `selected` written while the row has no model yet. NativeScript's XML builder assigns
32
39
  * every attribute before it adds the children, so `<adw:ComboRow selected="1">` reaches
@@ -47,15 +54,23 @@ export declare class AdwComboRow extends AdwActionRow {
47
54
  private _syncChooser;
48
55
  /** Open the native action chooser and apply the picked option. */
49
56
  private _openChooser;
50
- /** The list model (`Adw.ComboRow:model`). Updates the inline value label. */
51
- get model(): AdwComboOption[];
52
- set model(value: AdwListModelInput | string);
57
+ /**
58
+ * The list model (`Adw.ComboRow:model`) — the OBJECT that was assigned, by identity, as
59
+ * `row.model === model` is measured to hold in libadwaita (ADR 0122 § 4). The normalised
60
+ * descriptors are {@link options}.
61
+ */
62
+ get model(): ComboWatchableModel | null;
63
+ set model(value: ComboWatchableModel | string | null);
64
+ /** The held model's items as `{ value, label }` descriptors. */
65
+ get options(): AdwComboOption[];
53
66
  /** `adw_combo_row_set_model`. */
54
- set_model(model: AdwListModelInput | null): void;
67
+ set_model(model: ComboWatchableModel | null): void;
68
+ /** `adw_combo_row_get_model`. */
69
+ get_model(): ComboWatchableModel | null;
55
70
  /**
56
- * XML inflation: a child at `model` is the row's list — a `Gtk.StringList` is already an
57
- * `AdwListModelInput`, so it goes through the same setter as the property. Everything
58
- * else is a row edge, as on any action row.
71
+ * XML inflation: a child at `model` is the row's list — a `Gtk.StringList` IS a
72
+ * `Gio.ListModel`, so it goes through the same setter as the property. Everything else is a
73
+ * row edge, as on any action row.
59
74
  */
60
75
  _addChildFromBuilder(name: string, child: View): void;
61
76
  /** The selected option index. Updates the inline value label. */
@@ -66,4 +81,13 @@ export declare class AdwComboRow extends AdwActionRow {
66
81
  /** The selected option's `value`, or `''` when out of range. */
67
82
  get selectedValue(): string;
68
83
  set selectedValue(value: string);
84
+ /**
85
+ * The selected ITEM (`Adw.ComboRow:selected-item`) — the model's own object at
86
+ * {@link selected}, read through `get_item`, so the identity comparison a `selected-item`
87
+ * consumer writes holds. `null` for the sentinel and for no model. Read-only, as in
88
+ * libadwaita.
89
+ */
90
+ get selectedItem(): unknown;
91
+ /** `adw_combo_row_get_selected_item`. */
92
+ get_selected_item(): unknown;
69
93
  }
@@ -1,4 +1,4 @@
1
- import type { AdwAdjustmentInput, AdwListModelInput } from '@gjsify/adwaita-core';
1
+ import type { AdwAdjustmentInput } from '@gjsify/adwaita-core';
2
2
  import { type ShadowedName } from './shadowed-properties.js';
3
3
  /**
4
4
  * The keys a widget's construct-props bag accepts, derived from the widget itself.
@@ -33,31 +33,37 @@ export type WithSnakeCase<Props> = Props & {
33
33
  [K in keyof Props as K extends string ? SnakeCase<K> : K]: Props[K];
34
34
  };
35
35
  /**
36
- * The two properties whose SETTER takes a portable VALUE the getter does not hand back, and
37
- * what each one accepts.
36
+ * The two properties whose SETTER takes a value the getter does not hand back, and what each
37
+ * one accepts BEYOND its getter's type.
38
38
  *
39
39
  * THE GETTER TYPE IS NOT THE WHOLE DOOR HERE, and the difference is not an XML artifact like
40
- * `size`'s `| string`. `set model` takes `AdwListModelInput` — bare strings included, which
41
- * is `Gtk.StringList`'s own model and what `Gtk.StringList` itself is — and hands back
42
- * normalised `AdwComboOption`s; `set adjustment` takes a PARTIAL and hands back a whole one,
43
- * which is what makes `adjustment: { upper: 20 }` move one bound. Read off the getter alone,
44
- * the bag refused both — `new Adw.ComboRow({ model: ['Blue', 'Teal'] })` and
45
- * `new Adw.SpinRow({ adjustment: { lower: 0, upper: 100 } })` are the spellings the website
46
- * gallery has published on every such block, and every one of them was `TS2322` while the
47
- * runtime took it: `applyConstructProps` assigns through the setter, so nothing could fail.
40
+ * `size`'s `| string`. `set adjustment` takes a PARTIAL and hands back a whole one, which is
41
+ * what makes `adjustment: { upper: 20 }` move one bound. Read off the getter alone, the bag
42
+ * refused `new Adw.SpinRow({ adjustment: { lower: 0, upper: 100 } })` — a spelling the website
43
+ * gallery has published on every such block — with `TS2322` while the runtime took it:
44
+ * `applyConstructProps` assigns through the setter, so nothing could fail.
45
+ *
46
+ * `model` IS NARROWER THAN IT WAS, and the narrowing is the point. It used to widen to
47
+ * `AdwListModelInput`, arrays included, which was right while a `Gtk.StringList` WAS an array;
48
+ * since ADR 0122 § 4 `model` is an object property over `Gio.ListModel`, so
49
+ * `new Adw.ComboRow({ model: ['Blue', 'Teal'] })` is a `TypeError` at runtime and has to be one
50
+ * at compile time too — a bag that still admitted it would only move the failure to the first
51
+ * person who ran it. What is left to widen is the STRING: `model='[…]'` is the XML attribute's
52
+ * JSON door, which a `Gio.ListModel` has no attribute spelling for, and the getter hands back a
53
+ * model rather than the string it parsed.
48
54
  *
49
55
  * TWO KEY NAMES AND FOUR ACCESSORS: `model` on `AdwComboRow` and `GtkDropDown`, `adjustment`
50
56
  * on `AdwSpinRow` and `AdwSliderRow`, each pair declaring the same input type as the other.
51
57
  * Keyed by NAME like {@link ALIGNMENT_AXES}, because a widget that grows one of these
52
58
  * properties grows it with that meaning or the vocabulary gate refuses the name.
53
59
  *
54
- * It is held by `gtk-value-doors.spec.ts`, which writes all four spellings — array, a
55
- * `Gtk.StringList`, an object literal and a `Gtk.Adjustment` — through this door and is
56
- * type-checked with the rest of the package, so narrowing this table stops that file
57
- * compiling.
60
+ * It is held by `gtk-value-doors.spec.ts`, which writes every accepted spelling — a
61
+ * `Gtk.StringList`, an object literal and a `Gtk.Adjustment` — through this door and asserts
62
+ * the array as the refusal it became, and is type-checked with the rest of the package, so
63
+ * narrowing this table further stops that file compiling.
58
64
  */
59
65
  export interface ValueProps {
60
- model: AdwListModelInput;
66
+ model: string;
61
67
  adjustment: AdwAdjustmentInput;
62
68
  }
63
69
  /** The keys {@link ValueProps} declares — {@link ConstructProps} widens exactly these. */
@@ -1,5 +1,5 @@
1
1
  import { Label, StackLayout, type EventData, type View } from '@nativescript/core';
2
- import type { AdwComboOption, AdwListModelInput } from '@gjsify/adwaita-core';
2
+ import type { AdwComboOption, ComboWatchableModel } from '@gjsify/adwaita-core';
3
3
  import { GtkImage } from './gtk-image.js';
4
4
  import { type ConstructProps } from './construct-props.js';
5
5
  /** Event name emitted when {@link GtkDropDown.selected} changes through a pick. Mirrors GObject `notify::selected`. */
@@ -95,14 +95,31 @@ export declare class GtkDropDown extends GtkDropDown_base {
95
95
  protected readonly _chevron: GtkImage;
96
96
  /** The headless options list + selectedIndex↔selectedValue state machine (ADR 0004). */
97
97
  private readonly _state;
98
+ /**
99
+ * The list the MARKUP door fills — `<gtk:DropDown model='[…]'>` is JSON text, and a real
100
+ * `Gio.ListModel` has no attribute spelling (ADR 0122 § 5). Held for the widget's whole life
101
+ * so re-parsing the attribute splices the list it already points at rather than replacing
102
+ * it, which would reset the selection.
103
+ */
104
+ private readonly _authored;
98
105
  /** Title shown atop the substituted `action()` sheet. */
99
106
  private _chooserTitle;
100
107
  constructor(props?: ConstructProps<GtkDropDown>);
101
108
  /** Open the native chooser and apply the picked option. */
102
109
  private _openChooser;
103
- /** The list model (`Gtk.DropDown:model`). Updates the button label. */
104
- get model(): AdwComboOption[];
105
- set model(value: AdwListModelInput | string);
110
+ /**
111
+ * The list model (`Gtk.DropDown:model`) — the OBJECT that was assigned, by identity, as
112
+ * `dropdown.model === model` is measured to hold in GTK (ADR 0122 § 4). The normalised
113
+ * descriptors are {@link options}.
114
+ */
115
+ get model(): ComboWatchableModel | null;
116
+ set model(value: ComboWatchableModel | string | null);
117
+ /** The held model's items as `{ value, label }` descriptors. */
118
+ get options(): AdwComboOption[];
119
+ /** `gtk_drop_down_set_model`. */
120
+ set_model(model: ComboWatchableModel | null): void;
121
+ /** `gtk_drop_down_get_model`. */
122
+ get_model(): ComboWatchableModel | null;
106
123
  /**
107
124
  * XML inflation: a child at `model` is the list, written through the property's setter.
108
125
  * Anything else is refused, as GTK refuses a child widget on a `GtkDropDown`.
@@ -118,8 +135,14 @@ export declare class GtkDropDown extends GtkDropDown_base {
118
135
  /** The selected option's `value`, or `''` when out of range. */
119
136
  get selectedValue(): string;
120
137
  set selectedValue(value: string);
121
- /** The selected option descriptor, or `null` when out of range (`Gtk.DropDown:selected-item`). */
122
- get selectedItem(): AdwComboOption | null;
138
+ /**
139
+ * The selected ITEM (`Gtk.DropDown:selected-item`) — the model's own object at
140
+ * {@link selected}, read through `get_item`, so the identity comparison a `selected-item`
141
+ * consumer writes holds. `null` for the sentinel and for no model. Read-only, as in GTK.
142
+ */
143
+ get selectedItem(): unknown;
144
+ /** `gtk_drop_down_get_selected_item`. */
145
+ get_selected_item(): unknown;
123
146
  /**
124
147
  * Optional title shown atop the chooser sheet. A SUBSTITUTION affordance:
125
148
  * GTK's popover has no title, but a bare native sheet gives no clue what is
@@ -1,10 +1,12 @@
1
- import { Label } from '@nativescript/core';
1
+ import { Label, type EventData } from '@nativescript/core';
2
2
  import { type LabelEllipsizeMode, type LabelJustification } from '@gjsify/adwaita-core';
3
3
  import { type ConstructProps } from './construct-props.js';
4
+ /** Event name emitted when a link in the markup is tapped, before it is opened. */
5
+ export declare const ACTIVATE_LINK = "activate-link";
4
6
  declare const GtkLabel_base: ((abstract new (...args: any[]) => {
5
- addEventListener(eventName: string, callback: (data: import("@nativescript/core").EventData) => void, thisArg?: unknown, once?: boolean): void;
6
- removeEventListener(eventName: string, callback?: (data: import("@nativescript/core").EventData) => void, thisArg?: unknown): void;
7
- connect(eventName: string, callback: (self: /*elided*/ any, data: import("@nativescript/core").EventData) => unknown): number;
7
+ addEventListener(eventName: string, callback: (data: EventData) => void, thisArg?: unknown, once?: boolean): void;
8
+ removeEventListener(eventName: string, callback?: (data: EventData) => void, thisArg?: unknown): void;
9
+ connect(eventName: string, callback: (self: /*elided*/ any, data: EventData) => unknown): number;
8
10
  disconnect(handlerId: number): void;
9
11
  emit(eventName: string, ...args: unknown[]): void;
10
12
  get_property(name: string): unknown;
@@ -59,7 +61,7 @@ declare const GtkLabel_base: ((abstract new (...args: any[]) => {
59
61
  set_focus_on_click(focusOnClick: boolean): void;
60
62
  grab_focus(): boolean;
61
63
  _emit(eventName: string): void;
62
- notify<T extends import("@nativescript/core").EventData>(data: T): void;
64
+ notify<T extends EventData>(data: T): void;
63
65
  notifyPropertyChange(name: string, value: unknown, oldValue?: unknown): void;
64
66
  set(name: string, value: unknown): void;
65
67
  get(name: string): unknown;
@@ -78,6 +80,8 @@ export declare class GtkLabel extends GtkLabel_base {
78
80
  private _xalignWritten;
79
81
  private _justify;
80
82
  private _selectable;
83
+ /** The `<a href>` of the last render — kept so a re-parse inherits `visited` by URI. */
84
+ private _links;
81
85
  constructor(props?: ConstructProps<GtkLabel>);
82
86
  /**
83
87
  * `Gtk.Label:label` — the text, as written, before markup and the mnemonic marker are
@@ -88,9 +92,8 @@ export declare class GtkLabel extends GtkLabel_base {
88
92
  /**
89
93
  * `Gtk.Label:use-markup` — whether {@link label} is Pango markup.
90
94
  *
91
- * TRUE means the markup is REDUCED to its plain text here, not rendered: see the
92
- * header. FALSE, the default, shows the string literally, so a `<` in a sentence stays
93
- * a `<`.
95
+ * TRUE means the markup is DRAWN, as styled `Span`s: see the header. FALSE, the
96
+ * default, shows the string literally, so a `<` in a sentence stays a `<`.
94
97
  */
95
98
  get useMarkup(): boolean;
96
99
  set useMarkup(raw: boolean | string);
@@ -201,5 +204,23 @@ export declare class GtkLabel extends GtkLabel_base {
201
204
  set_css_classes(names: readonly string[]): void;
202
205
  private _setClasses;
203
206
  private _render;
207
+ /**
208
+ * `emit_activate_link` for the link at `index`: the user's handlers under GTK's handled
209
+ * accumulator, then — only if none handled it — the default launch.
210
+ *
211
+ * The link becomes VISITED whenever the emission was handled, INCLUDING by a handler
212
+ * that cancelled the launch (gtklabel.c:2053, `if (handled && !link->visited)`): GTK
213
+ * reads a TRUE as "this link has been followed, my way". `Gtk.LinkButton` differs — it
214
+ * sets `visited` inside its own default handler, which a cancelling handler skips — and
215
+ * the two are not the same rule.
216
+ */
217
+ private _activateLink;
218
+ /**
219
+ * The launcher call, on its own method so a caller (or a spec) can stand in for the
220
+ * app the host would have opened — the same door `Adw.AboutDialog` uses on this
221
+ * surface, because the two must not disagree about what following a link does. A URI
222
+ * the host cannot launch is dropped, as a failed launch is.
223
+ */
224
+ protected launch(uri: string): void;
204
225
  }
205
226
  export {};
@@ -51,11 +51,18 @@ export declare class GtkWindow extends AdwSingleChildBase {
51
51
  private _requestClose;
52
52
  /**
53
53
  * What the back button does, in order: the topmost dialog, an open bottom sheet, the innermost
54
- * navigation view, then `close-request`. The sheet sits over the content a navigation view lives
54
+ * navigation view, the window's key controllers (`Gdk.KEY_Back`), then `close-request`. The sheet sits over the content a navigation view lives
55
55
  * in, and libadwaita closes it on Escape before anything under it sees the key. Always consumes the press — the system's own back would `finish()` too, but
56
56
  * without asking the handlers.
57
57
  */
58
58
  private _handleBack;
59
+ /**
60
+ * Back as GTK would see it: a `key-pressed` of `Gdk.KEY_Back` reaching the toplevel's key
61
+ * controllers AFTER the focused content (dialog, sheet, navigation view) had its turn, since the
62
+ * key travels from the focus up. The press arrives by NativeScript's back event, not through
63
+ * the view's key listener, so it is handed to the controllers here.
64
+ */
65
+ private _deliverBackKey;
59
66
  /** A subclass that shows things over the window (dialogs) takes the press first; true = taken. */
60
67
  protected _consumeBack(): boolean;
61
68
  /** Only a window with no window above it owns the back button. */
@@ -0,0 +1,43 @@
1
+ import { FormattedString, Span } from '@nativescript/core';
2
+ import { type LabelMarkupRender, type LabelMarkupRun } from '@gjsify/adwaita-core';
3
+ /**
4
+ * One run as one `Span`.
5
+ *
6
+ * The `<span>` attributes are written FIRST and the pango tags after, so a tag wins a
7
+ * collision — the same declared order the web port states, for the same reason: the runs
8
+ * record the tags as booleans and the `<span>`s as a separate stack, so neither renderer can
9
+ * know which element was inner.
10
+ *
11
+ * `mnemonics` is `use-underline`, applied to the run's TEXT and not to the markup string:
12
+ * `gtk_label_set_markup_with_mnemonic` parses first and strips the marker out of the result,
13
+ * so an `_` inside a tag's attributes is not a mnemonic.
14
+ */
15
+ export declare function labelMarkupSpan(run: LabelMarkupRun, mnemonics: boolean, base?: number): Span;
16
+ /**
17
+ * Whether `render` needs the `FormattedString` path at all.
18
+ *
19
+ * A label whose markup is only `<markup>` around plain prose draws IDENTICALLY from
20
+ * `text`, and taking the rich path for it would move every such label onto a different
21
+ * native mechanism (an Android `SpannableStringBuilder` rather than a plain `CharSequence`)
22
+ * for no visible difference. So the predicate is "any run carries style, or there is a
23
+ * link", and a markup label that needs neither keeps the path it has always had.
24
+ *
25
+ * LOCAL TO THIS MODULE on purpose: it is a NativeScript write-path question, and a core
26
+ * helper for it would be a core function no renderer suite drives.
27
+ */
28
+ export declare function labelMarkupNeedsSpans(render: LabelMarkupRender): boolean;
29
+ /**
30
+ * `render` as a `FormattedString`, with every run inside an `<a href>` subscribed to
31
+ * `onLinkTap`.
32
+ *
33
+ * SUBSCRIBING IS WHAT MAKES A SPAN TAPPABLE: `tappable` is derived from
34
+ * `hasListeners(Span.linkTapEvent)` (`Span._setTappable`) and `setSpanModifiers` attaches
35
+ * the native `ClickableSpan` only for a tappable span, so the listener is not an extra on
36
+ * top of the link — it IS the link.
37
+ *
38
+ * A LINK WITH NO TEXT HAS NO SPAN, and cannot: `createSpannableStringBuilder` skips any
39
+ * span whose text is empty (`spanLength > 0`), so an empty `Span` would not reach the
40
+ * native text at all. The web port keeps the empty `<a>`; here the link survives only in
41
+ * the render's `links`, which is what answers `has-tooltip` and the `link` style class.
42
+ */
43
+ export declare function labelMarkupFormattedString(render: LabelMarkupRender, mnemonics: boolean, base: number | undefined, onLinkTap: (index: number) => void): FormattedString;
@@ -1,10 +1,15 @@
1
1
  import type { EventData, Observable } from '@nativescript/core';
2
- import { type ForeignClassMeta, type ForeignProperty } from '@gjsify/adwaita-core';
2
+ import { type ForeignClassMeta, type ForeignObjectProperty, type ForeignProperty, type ForeignScalarProperty } from '@gjsify/adwaita-core';
3
3
  /**
4
- * A declared property, plus the one thing the engine's vocabulary has no room for: how a value is
5
- * brought into the property's shape BEFORE it is stored. The engine never sees `normalize`.
4
+ * One arm of {@link ForeignProperty}, plus the one thing the engine's vocabulary has no room for:
5
+ * how a value is brought into the property's shape BEFORE it is stored. The engine never sees
6
+ * `normalize`.
7
+ *
8
+ * Applied per ARM rather than to the union, because `ForeignProperty` is a discriminated union
9
+ * since ADR 0122 § 6 and `property.kind === 'object'` has to keep narrowing to the arm that
10
+ * carries `valueType`.
6
11
  */
7
- export interface DeclaredProperty extends ForeignProperty {
12
+ type Declared<P> = P & {
8
13
  /**
9
14
  * Replaces the seam's own coercion for EVERY write, typed or not — a floor, a clamp, a lenient
10
15
  * parse. Runs identically on both legs, ahead of the store and of the equal-write check, so a
@@ -16,7 +21,38 @@ export interface DeclaredProperty extends ForeignProperty {
16
21
  * here, since a write that resolves to the value already held is not a change.
17
22
  */
18
23
  readonly normalize?: (value: unknown, self: object) => unknown;
19
- }
24
+ /**
25
+ * Replaces the equal-write check for this property on the PURE leg: `written` is the value as
26
+ * the caller spelled it, `next` what {@link Declared.normalize} made of it, `held` what the
27
+ * store holds — and the answer decides whether the write notifies at all.
28
+ *
29
+ * WHY. A C setter guards on `g_strcmp0 (value, adw_…_get_…(self))`, against the GETTER
30
+ * READBACK rather than the stored field. Where storage normalises, the two differ and the
31
+ * guard can never fire: `GtkImage` turns an empty icon name into "no icon", so writing `''`
32
+ * to a button that already reads back `null` notifies EVERY time (measured on GJS 1.88.1 /
33
+ * libadwaita 1.9.4). Comparing the held value says the opposite, and only the property whose
34
+ * `normalize` collapses distinct writes onto one held value can tell the difference.
35
+ *
36
+ * The real leg has no use for it — there the guard IS the C one.
37
+ */
38
+ readonly changed?: (next: unknown, held: unknown, written: unknown, self: object) => boolean;
39
+ /**
40
+ * The rest of the C setter, on the PURE leg: runs once this property's own `notify::<name>`
41
+ * is out, so a setter that also drives OTHER properties emits in the order C does.
42
+ *
43
+ * WHY IT IS NOT `normalize`. A normalizer runs AHEAD of the store, so a cross-write made
44
+ * there notifies before the property that caused it. `Adw.SplitButton` measures the other way
45
+ * round — `label = 'Open'` on an icon button emits `label` first and the slots it clears
46
+ * after — and the two cannot both be one hook. The SHAPE of a value still belongs to
47
+ * `normalize`; what the write does to its siblings belongs here.
48
+ *
49
+ * Not run on the real leg, where the C setter does this itself: a second pass would write the
50
+ * cleared slot a second time, and C answers a redundant `null` with a CRITICAL.
51
+ */
52
+ readonly afterNotify?: (self: object) => void;
53
+ };
54
+ /** A declared property of any kind, with its optional {@link Declared.normalize}. */
55
+ export type DeclaredProperty = Declared<ForeignScalarProperty> | Declared<ForeignObjectProperty>;
20
56
  /** {@link ForeignClassMeta} whose properties may carry a {@link DeclaredProperty.normalize}. */
21
57
  export interface DeclaredClassMeta extends Omit<ForeignClassMeta, 'Properties'> {
22
58
  readonly Properties?: Readonly<Record<string, DeclaredProperty>>;
@@ -187,3 +223,4 @@ export declare function withProperties<TBase extends ObservableConstructor>(Base
187
223
  /** Only what this class ADDS; `emittedSignalsOf` merges it with the base's. */
188
224
  readonly emittedSignals: readonly string[];
189
225
  }) & TBase;
226
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { type View } from '@nativescript/core';
2
2
  import type { BackPressedEvent } from './window-source.js';
3
- export declare const canFinishWindow = true;
3
+ export declare function canFinishWindow(): boolean;
4
4
  export declare function watchBackButton(onBack: (event: BackPressedEvent) => void): () => void;
5
5
  export declare function finishWindow(): void;
6
6
  export declare function isViewFocused(view: View): boolean;
@@ -1,6 +1,11 @@
1
1
  import type { View } from '@nativescript/core';
2
- /** Whether {@link finishWindow} can end the window on this platform. */
3
- export declare const canFinishWindow = false;
2
+ /**
3
+ * Whether {@link finishWindow} can end the window on this platform. A FUNCTION, not a constant: the
4
+ * library build (`--library`, one module per file) folds an imported `const` into its importer, so
5
+ * `window-host.js` would carry this base file's `false` whatever platform variant the app's bundle
6
+ * resolves in its place.
7
+ */
8
+ export declare function canFinishWindow(): boolean;
4
9
  export declare function finishWindow(): void;
5
10
  export declare function isViewFocused(_view: View): boolean;
6
11
  export declare function focusView(_view: View): void;
@@ -1,6 +1,6 @@
1
1
  import type { View } from '@nativescript/core';
2
2
  import type { BackPressedEvent } from './window-source.js';
3
- export declare const canFinishWindow = false;
3
+ export declare function canFinishWindow(): boolean;
4
4
  export declare function finishWindow(): void;
5
5
  export declare function isViewFocused(view: View): boolean;
6
6
  export declare function focusView(view: View): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/adwaita-nativescript",
3
- "version": "0.64.12-next.281",
3
+ "version": "0.64.13-next.283",
4
4
  "description": "Native Adwaita widgets for the NativeScript runtime — real NativeScript components (StackLayout/GridLayout/Switch/Label) styled like Libadwaita, not a webview",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -73,15 +73,15 @@
73
73
  "design-system"
74
74
  ],
75
75
  "dependencies": {
76
- "@gjsify/adwaita-core": "0.64.12-next.281",
77
- "@gjsify/adwaita-fonts": "0.64.12-next.281",
78
- "@gjsify/adwaita-icons": "0.64.12-next.281",
79
- "@gjsify/canvas2d-core": "0.64.12-next.281",
80
- "@gjsify/native-platform": "0.64.12-next.281"
76
+ "@gjsify/adwaita-core": "0.64.13-next.283",
77
+ "@gjsify/adwaita-fonts": "0.64.13-next.283",
78
+ "@gjsify/adwaita-icons": "0.64.13-next.283",
79
+ "@gjsify/canvas2d-core": "0.64.13-next.283",
80
+ "@gjsify/native-platform": "0.64.13-next.283"
81
81
  },
82
82
  "peerDependencies": {
83
83
  "@nativescript/core": "*",
84
- "@gjsify/app-settings": "0.64.12-next.281"
84
+ "@gjsify/app-settings": "0.64.13-next.283"
85
85
  },
86
86
  "peerDependenciesMeta": {
87
87
  "@nativescript/core": {
@@ -92,11 +92,11 @@
92
92
  }
93
93
  },
94
94
  "devDependencies": {
95
- "@gjsify/app-settings": "0.64.12-next.281",
96
- "@gjsify/blueprint": "0.64.12-next.281",
97
- "@gjsify/cli": "0.64.12-next.281",
98
- "@gjsify/unit": "0.64.12-next.281",
99
- "@gjsify/vite-plugin-blueprint": "0.64.12-next.281",
95
+ "@gjsify/app-settings": "0.64.13-next.283",
96
+ "@gjsify/blueprint": "0.64.13-next.283",
97
+ "@gjsify/cli": "0.64.13-next.283",
98
+ "@gjsify/unit": "0.64.13-next.283",
99
+ "@gjsify/vite-plugin-blueprint": "0.64.13-next.283",
100
100
  "@types/node": "^25.9.2",
101
101
  "typescript": "^6.0.3"
102
102
  },
@@ -126,5 +126,5 @@
126
126
  "url": "https://github.com/gjsify/gjsify/issues"
127
127
  },
128
128
  "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/nativescript-bridge/adwaita#readme",
129
- "gitHead": "c4d2e266c0d9849860b9828c14ebfe37b6d493b8"
129
+ "gitHead": "05fae97125a374e84bf57c2d2d086fb53523f205"
130
130
  }
@@ -173,6 +173,8 @@ function unloadView(view: View): void {
173
173
  */
174
174
  export class Style extends Observable {
175
175
  direction?: 'ltr' | 'rtl' | null = null;
176
+ /** In DIPs, and unset until written: `fontSizeProperty` carries no `defaultValue`. */
177
+ fontSize?: number;
176
178
  readonly viewRef: WeakRef<View>;
177
179
  #visibility = 'visible';
178
180
 
@@ -663,8 +665,181 @@ export class GridLayout extends LayoutBase {
663
665
  }
664
666
  }
665
667
 
668
+ /**
669
+ * A `Span`'s style — NOT a {@link View}'s {@link Style}.
670
+ *
671
+ * `Span extends ViewBase` upstream, so it has none of `View`'s shortcuts and carries only
672
+ * what a span can be given. Every member is unset until written, which is what the font
673
+ * properties answer on a device: `fontSizeProperty` and `fontFamilyProperty` are registered
674
+ * with no `defaultValue` (`ui/styling/style-properties.ts`).
675
+ */
676
+ export class SpanStyle extends Observable {
677
+ fontFamily: string | undefined;
678
+ fontSize: number | undefined;
679
+ fontStyle: string | undefined;
680
+ fontWeight: string | undefined;
681
+ textDecoration: string | undefined;
682
+ verticalAlignment: string | undefined;
683
+ }
684
+
685
+ /**
686
+ * One styled stretch of a {@link FormattedString}.
687
+ *
688
+ * The font and decoration members are ACCESSORS OVER `style`, as `ui/text-base/span.ts`
689
+ * has them — a double that made them own fields could not report a widget that wrote one
690
+ * and expected the other to see it.
691
+ */
692
+ export class Span extends Observable {
693
+ static readonly linkTapEvent = 'linkTap';
694
+
695
+ readonly _style: SpanStyle = new SpanStyle();
696
+
697
+ get style(): SpanStyle {
698
+ return this._style;
699
+ }
700
+
701
+ /** NativeScript unescapes the two whitespace spellings a markup file can carry. */
702
+ private _text = '';
703
+
704
+ get text(): string {
705
+ return this._text;
706
+ }
707
+
708
+ set text(value: string) {
709
+ this._text = String(value ?? '')
710
+ .replace(/\\n/g, '\n')
711
+ .replace(/\\t/g, '\t');
712
+ }
713
+
714
+ get fontFamily(): string | undefined {
715
+ return this._style.fontFamily;
716
+ }
717
+
718
+ set fontFamily(value: string | undefined) {
719
+ this._style.fontFamily = value;
720
+ }
721
+
722
+ get fontSize(): number | undefined {
723
+ return this._style.fontSize;
724
+ }
725
+
726
+ set fontSize(value: number | undefined) {
727
+ this._style.fontSize = value;
728
+ }
729
+
730
+ get fontStyle(): string | undefined {
731
+ return this._style.fontStyle;
732
+ }
733
+
734
+ set fontStyle(value: string | undefined) {
735
+ this._style.fontStyle = value;
736
+ }
737
+
738
+ get fontWeight(): string | undefined {
739
+ return this._style.fontWeight;
740
+ }
741
+
742
+ set fontWeight(value: string | undefined) {
743
+ this._style.fontWeight = value;
744
+ }
745
+
746
+ get textDecoration(): string | undefined {
747
+ return this._style.textDecoration;
748
+ }
749
+
750
+ set textDecoration(value: string | undefined) {
751
+ this._style.textDecoration = value;
752
+ }
753
+
754
+ /**
755
+ * DERIVED, never written — upstream flips it from `addEventListener` /
756
+ * `removeEventListener` through `_setTappable(this.hasListeners(Span.linkTapEvent))`,
757
+ * and `setSpanModifiers` attaches the native `ClickableSpan` only for a tappable span.
758
+ * So subscribing IS what makes a span a link, and this reads the listeners rather than
759
+ * a flag a caller could set without one.
760
+ */
761
+ get tappable(): boolean {
762
+ return (listenersOf(this).get(Span.linkTapEvent)?.length ?? 0) > 0;
763
+ }
764
+ }
765
+
766
+ /**
767
+ * The `ObservableArray<Span>` behind {@link FormattedString.spans}, as the four members
768
+ * that collection really offers.
769
+ *
770
+ * NOT A PLAIN ARRAY, and a double that used one would be the easier lie: `ObservableArray`
771
+ * reads by `getItem(pos)` and has no index access at all, so `spans[0]` is `undefined` on a
772
+ * device. A spec written against an array would pass here and read nothing there.
773
+ */
774
+ export class SpanList {
775
+ private readonly _items: Span[] = [];
776
+
777
+ get length(): number {
778
+ return this._items.length;
779
+ }
780
+
781
+ push(span: Span): number {
782
+ return this._items.push(span);
783
+ }
784
+
785
+ /** A negative `pos` counts from the end, as upstream's does. */
786
+ getItem(pos: number): Span {
787
+ return this._items[pos < 0 ? this._items.length + pos : pos]!;
788
+ }
789
+
790
+ *[Symbol.iterator](): Generator<Span, void, unknown> {
791
+ yield* this._items;
792
+ }
793
+ }
794
+
795
+ /** The rich-text value of a {@link Label} — a FLAT list of spans, no nesting. */
796
+ export class FormattedString extends Observable {
797
+ readonly spans: SpanList = new SpanList();
798
+
799
+ /** `formatted-string.ts`: the span texts concatenated, nothing between them. */
800
+ toString(): string {
801
+ let text = '';
802
+ for (const span of this.spans) text += span.text;
803
+ return text;
804
+ }
805
+ }
806
+
666
807
  export class Label extends View {
667
- text = '';
808
+ private _text = '';
809
+ private _formattedText: FormattedString | null | undefined;
810
+
811
+ /**
812
+ * A write is a NO-OP while {@link formattedText} is set, as on a device:
813
+ * `[textProperty.setNative]` returns early when the label carries rich text
814
+ * (`ui/text-base/index.android.ts:192-195`), so the spans are what shows and this
815
+ * property is whatever the spans last said.
816
+ */
817
+ get text(): string {
818
+ return this._text;
819
+ }
820
+
821
+ set text(value: string) {
822
+ if (this._formattedText === null || this._formattedText === undefined) this._text = value;
823
+ }
824
+
825
+ /**
826
+ * Unset until something writes it — `formattedTextProperty` carries no `defaultValue`
827
+ * (`ui/text-base/text-base-common.ts:194`), so a label that was never given rich text
828
+ * reads `undefined`, not `null`.
829
+ */
830
+ get formattedText(): FormattedString | null | undefined {
831
+ return this._formattedText;
832
+ }
833
+
834
+ set formattedText(value: FormattedString | null | undefined) {
835
+ this._formattedText = value;
836
+ // The device re-derives the plain text from the spans on BOTH legs:
837
+ // `[formattedTextProperty.setNative]` calls
838
+ // `textProperty.nativeValueChange(this, value?.toString() ?? '')`, which is why a
839
+ // `text` written BEFORE the clear would be wiped to the empty string.
840
+ this._text = value?.toString() ?? '';
841
+ }
842
+
668
843
  textWrap = false;
669
844
  textAlignment = 'initial';
670
845
  textOverflow = 'initial';