@gjsify/gtk-host 0.44.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -4
- package/lib/esm/adapters/solid.js +1 -1
- package/lib/esm/conformance/diagnostics.js +1 -1
- package/lib/esm/conformance/index.js +2 -2
- package/lib/esm/descriptors/adw.js +1 -1
- package/lib/esm/descriptors/gtk.js +1 -1
- package/lib/esm/errors.js +1 -1
- package/lib/esm/generated/widgets.js +1 -1
- package/lib/esm/host.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/list/controller.js +1 -0
- package/lib/esm/list/index.js +1 -0
- package/lib/esm/list/scroll.js +1 -0
- package/lib/esm/policies.js +1 -1
- package/lib/esm/probe.js +1 -1
- package/lib/esm/props.js +1 -1
- package/lib/esm/registry.js +1 -1
- package/lib/esm/signals.js +1 -1
- package/lib/esm/style/document.js +1 -0
- package/lib/esm/style/gtk-props.js +1 -1
- package/lib/esm/style/index.js +1 -1
- package/lib/esm/style/layout.js +1 -1
- package/lib/esm/style/paint.js +1 -1
- package/lib/esm/style/sheet.js +3 -3
- package/lib/esm/style/theme.js +3 -0
- package/lib/esm/style/tokens.js +1 -1
- package/lib/types/adapters/solid.d.ts +35 -0
- package/lib/types/conformance/diagnostics.d.ts +1 -1
- package/lib/types/descriptors/index.d.ts +3 -3
- package/lib/types/errors.d.ts +10 -0
- package/lib/types/generated/props.d.ts +684 -816
- package/lib/types/generated/widgets.d.ts +1 -1
- package/lib/types/generator/emit-types.d.mts +2 -2
- package/lib/types/generator/emit.d.mts +16 -6
- package/lib/types/generator/girs-vocabulary.d.mts +45 -0
- package/lib/types/generator/main.d.mts +16 -8
- package/lib/types/generator/model.d.mts +95 -0
- package/lib/types/generator/names.d.mts +19 -0
- package/lib/types/generator/vocabulary-dts.d.mts +47 -0
- package/lib/types/host.d.ts +3 -3
- package/lib/types/index.d.ts +1 -1
- package/lib/types/list/controller.d.ts +112 -0
- package/lib/types/list/index.d.ts +2 -0
- package/lib/types/list/list.spec.d.ts +2 -0
- package/lib/types/list/scroll.d.ts +26 -0
- package/lib/types/policies.d.ts +18 -1
- package/lib/types/probe.d.ts +49 -0
- package/lib/types/probe.spec.d.ts +2 -0
- package/lib/types/props.d.ts +13 -1
- package/lib/types/registry.d.ts +1 -1
- package/lib/types/signals.d.ts +3 -1
- package/lib/types/style/document.d.ts +22 -0
- package/lib/types/style/index.d.ts +6 -3
- package/lib/types/style/layout.d.ts +34 -0
- package/lib/types/style/sheet.d.ts +0 -5
- package/lib/types/style/theme.d.ts +158 -0
- package/lib/types/style/theme.spec.d.ts +2 -0
- package/lib/types/style/tokens.d.ts +76 -0
- package/lib/types/style/tokens.spec.d.ts +2 -0
- package/lib/types/types.d.ts +84 -4
- package/package.json +22 -16
- package/lib/types/generator/gir.d.mts +0 -164
- package/lib/types/generator/mini.fixture.d.mts +0 -30
- package/lib/types/generator/surface.d.mts +0 -62
- package/lib/types/generator/tsmap.d.mts +0 -73
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Gdk from 'gi://Gdk?version=4.0';
|
|
2
|
+
import Gtk from 'gi://Gtk?version=4.0';
|
|
3
|
+
/** A document GTK refused, or one that would have discarded what follows it. */
|
|
4
|
+
export declare class StyleSheetError extends Error {
|
|
5
|
+
readonly name = "StyleSheetError";
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Refuse a document that would take everything after it with it.
|
|
10
|
+
*
|
|
11
|
+
* `subject` names what is being loaded, because the two callers have very different
|
|
12
|
+
* readers: a generated rule is this package's bug, and an application's theme
|
|
13
|
+
* document is the application's.
|
|
14
|
+
*/
|
|
15
|
+
export declare function assertContained(document: string, subject: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Put a provider on a display at `priority`, and say which display that was.
|
|
18
|
+
*
|
|
19
|
+
* `subject` names what is being installed, because the failure a caller has to act
|
|
20
|
+
* on is "there is no display yet" and the fix depends on which document it is.
|
|
21
|
+
*/
|
|
22
|
+
export declare function installProvider(provider: Gtk.CssProvider, subject: string, display: Gdk.Display | null | undefined, priority: number): Gdk.Display;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
export { GTK_CSS_PROBES, GTK_CSS_PROPERTIES, NOT_GTK_CSS } from './gtk-css.js';
|
|
2
2
|
export { GTK_WIDGET_PROPERTIES, GTK_WIDGET_PROPERTY_PROBES, NOT_GTK_WIDGET_PROPERTIES } from './gtk-props.js';
|
|
3
|
-
export { MINIMAL_TOKENS, lookupToken, requireToken } from './tokens.js';
|
|
3
|
+
export { MINIMAL_TOKENS, TAILWIND_DEFAULT_TOKENS, lookupToken, mergeTokens, requireToken, tailwindDefaultHint, } from './tokens.js';
|
|
4
4
|
export type { Scale, StyleTokens } from './tokens.js';
|
|
5
5
|
export { UnknownUtilityError } from './errors.js';
|
|
6
6
|
export { PAINT_PROPERTIES, partitionPaint, resolvePaintUtility } from './paint.js';
|
|
7
7
|
export type { PaintProps } from './paint.js';
|
|
8
8
|
export { LAYOUT_PROPERTIES, partitionLayout, resolveLayoutUtility } from './layout.js';
|
|
9
|
-
export type { AlignValue, Edge, JustifyValue, LayoutIntent, LayoutPartition, LayoutProps, OverlayIntent, } from './layout.js';
|
|
9
|
+
export type { AlignValue, Edge, JustifyValue, LayoutIntent, LayoutPartition, LayoutProps, OverlayIntent, WrapIntent, } from './layout.js';
|
|
10
10
|
export { partition, resolveUtilities, resolveUtility } from './resolve.js';
|
|
11
11
|
export type { Partitioned, StyleProps } from './resolve.js';
|
|
12
|
-
export { StyleSheet,
|
|
12
|
+
export { StyleSheet, VARIANT_PSEUDO } from './sheet.js';
|
|
13
13
|
export type { StyleSheetOptions } from './sheet.js';
|
|
14
|
+
export { assertContained, StyleSheetError } from './document.js';
|
|
15
|
+
export { ADWAITA_NAMED_COLORS, NEUTRAL_THEME, NOT_ADWAITA_NAMED_COLORS, THEME_PROVIDER_PRIORITY, ThemeRegistry, } from './theme.js';
|
|
16
|
+
export type { Theme, ThemeRegistryOptions } from './theme.js';
|
|
@@ -27,6 +27,7 @@ export interface LayoutProps {
|
|
|
27
27
|
paddingBottom?: string;
|
|
28
28
|
paddingLeft?: string;
|
|
29
29
|
flexDirection?: 'row' | 'column';
|
|
30
|
+
flexWrap?: 'nowrap' | 'wrap';
|
|
30
31
|
flexGrow?: string;
|
|
31
32
|
alignItems?: AlignValue;
|
|
32
33
|
justifyContent?: JustifyValue;
|
|
@@ -114,6 +115,25 @@ export interface LayoutIntent {
|
|
|
114
115
|
* `relative` would make it undetectable.
|
|
115
116
|
*/
|
|
116
117
|
readonly overlay?: OverlayIntent;
|
|
118
|
+
/**
|
|
119
|
+
* `flex-wrap` — the element becomes a DIFFERENT WIDGET.
|
|
120
|
+
*
|
|
121
|
+
* A `Gtk.Box` lays its children on one line and has no second line to put
|
|
122
|
+
* anything on. Wrapping on GTK is `Gtk.FlowBox`, which is not another property
|
|
123
|
+
* on the box but another class — so this is the same shape as
|
|
124
|
+
* {@link LayoutIntent.distribute}'s `space-between`: L1 names the widget the
|
|
125
|
+
* answer needs and L2 swaps it, because L1 resolves properties for an element
|
|
126
|
+
* and has no say in what the element becomes.
|
|
127
|
+
*
|
|
128
|
+
* The SPACINGS travel with it, and that is the reason this field carries values
|
|
129
|
+
* at all rather than being a flag. `Gtk.FlowBox` has NO `spacing` (measured,
|
|
130
|
+
* `gtk-props.ts`) — it has `row-spacing` and `column-spacing`, both real at once
|
|
131
|
+
* — so a gap on a wrapping element cannot take the `Gtk.Box:spacing` route the
|
|
132
|
+
* gap routes below use, and the axis-qualified spellings stop being an
|
|
133
|
+
* orientation question. Routing them here is what keeps `gap-*` from emitting a
|
|
134
|
+
* property the widget does not install.
|
|
135
|
+
*/
|
|
136
|
+
readonly wrap?: WrapIntent;
|
|
117
137
|
/**
|
|
118
138
|
* `text-*` — only a text widget aligns text.
|
|
119
139
|
*
|
|
@@ -124,6 +144,20 @@ export interface LayoutIntent {
|
|
|
124
144
|
*/
|
|
125
145
|
readonly textAlign?: 'left' | 'center' | 'right' | 'justify';
|
|
126
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* `flex-nowrap` / `flex-wrap`, with the spacings a wrapping widget needs.
|
|
149
|
+
*
|
|
150
|
+
* `single` is carried rather than dropped for the reason `relative` is: it is the
|
|
151
|
+
* half L2 can hold the other half against, and a resolution that never sees it
|
|
152
|
+
* cannot tell "this element does not wrap" from "nobody asked".
|
|
153
|
+
*/
|
|
154
|
+
export type WrapIntent = {
|
|
155
|
+
readonly lines: 'single';
|
|
156
|
+
} | {
|
|
157
|
+
readonly lines: 'multi';
|
|
158
|
+
readonly rowSpacing?: number;
|
|
159
|
+
readonly columnSpacing?: number;
|
|
160
|
+
};
|
|
127
161
|
export type OverlayIntent = {
|
|
128
162
|
readonly role: 'context';
|
|
129
163
|
} | {
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import Gdk from 'gi://Gdk?version=4.0';
|
|
2
2
|
/** A variant this sheet knows how to express, and the pseudo-class it becomes. */
|
|
3
3
|
export declare const VARIANT_PSEUDO: Readonly<Record<string, string>>;
|
|
4
|
-
/** A rule GTK refused, or one that would have poisoned the document. */
|
|
5
|
-
export declare class StyleSheetError extends Error {
|
|
6
|
-
readonly name = "StyleSheetError";
|
|
7
|
-
constructor(message: string);
|
|
8
|
-
}
|
|
9
4
|
export interface StyleSheetOptions {
|
|
10
5
|
/**
|
|
11
6
|
* Where the provider is installed. Omitted means the default display — the
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import Gdk from 'gi://Gdk?version=4.0';
|
|
2
|
+
/**
|
|
3
|
+
* Where a theme document is installed. See decision 2 for why it is this number.
|
|
4
|
+
*
|
|
5
|
+
* Exported because it is the fact a reader has to check against their own providers,
|
|
6
|
+
* and because a consumer installing a fourth document needs to know what it has to
|
|
7
|
+
* sit between.
|
|
8
|
+
*/
|
|
9
|
+
export declare const THEME_PROVIDER_PRIORITY: number;
|
|
10
|
+
/**
|
|
11
|
+
* The named colours libadwaita defines, measured rather than read.
|
|
12
|
+
*
|
|
13
|
+
* MEASURED on libadwaita 1.9.3 by resolving `var(--<name>, <sentinel>)` on a real
|
|
14
|
+
* widget and checking the sentinel did NOT come back — the only test that
|
|
15
|
+
* distinguishes "the name exists" from "the name is a typo that defines nothing".
|
|
16
|
+
* `theme.spec.ts` re-measures both directions against the libadwaita that is
|
|
17
|
+
* running, so a release that renames one goes red here rather than in a window.
|
|
18
|
+
*
|
|
19
|
+
* The list is what a theme may OVERRIDE, and overriding a name libadwaita does not
|
|
20
|
+
* define is the exact silent failure this set exists to catch: `--acccent-bg-color`
|
|
21
|
+
* is a perfectly valid custom property that nothing ever reads.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ADWAITA_NAMED_COLORS: readonly string[];
|
|
24
|
+
/**
|
|
25
|
+
* Names that are NOT custom properties, and the claim each one carries.
|
|
26
|
+
*
|
|
27
|
+
* Without this direction the set above could name every string in GTK and still
|
|
28
|
+
* pass. `borders` is the interesting row: it is a real Adwaita colour under the
|
|
29
|
+
* LEGACY `@define-color` mechanism and is not a CSS variable, which is exactly the
|
|
30
|
+
* confusion decision 1 is about. `accent_bg_color` is the same point in the other
|
|
31
|
+
* spelling — the underscored legacy name of a variable that does exist.
|
|
32
|
+
*/
|
|
33
|
+
export declare const NOT_ADWAITA_NAMED_COLORS: readonly string[];
|
|
34
|
+
/** One named look: a GTK CSS document, a palette, and which desktops default to it. */
|
|
35
|
+
export interface Theme {
|
|
36
|
+
/** How the application asks for it. Also what a refusal names. */
|
|
37
|
+
readonly name: string;
|
|
38
|
+
/**
|
|
39
|
+
* The application's own GTK CSS document.
|
|
40
|
+
*
|
|
41
|
+
* Goes through the same containment probe as a generated rule, and for a
|
|
42
|
+
* stronger reason: this is the document this package did not write.
|
|
43
|
+
*/
|
|
44
|
+
readonly css?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Adwaita named colours to redefine, WITHOUT the `--` prefix.
|
|
47
|
+
*
|
|
48
|
+
* `{ 'accent-bg-color': 'rgb(53 132 228)' }`. Emitted as a `:root` block ahead of
|
|
49
|
+
* {@link Theme.css}, so a rule in {@link Theme.css} redefining one of these names
|
|
50
|
+
* WINS — the last definition in a document is the one that applies.
|
|
51
|
+
*/
|
|
52
|
+
readonly namedColors?: Readonly<Record<string, string>>;
|
|
53
|
+
/**
|
|
54
|
+
* The `process.platform` values this theme is the default for, or `'*'` for any.
|
|
55
|
+
*
|
|
56
|
+
* Data on the theme rather than a table in the registry, because "this look
|
|
57
|
+
* belongs on macOS" is a fact about the look.
|
|
58
|
+
*
|
|
59
|
+
* `'*'` exists because `process.platform` has more values than the three desktops
|
|
60
|
+
* this project targets — `freebsd`, `openbsd`, `android`, `sunos`, … — and GTK
|
|
61
|
+
* runs on several of them. A registry that only knew `linux`/`darwin`/`win32`
|
|
62
|
+
* would make `selectDefault(process.platform)`, the call this seam is documented
|
|
63
|
+
* with, THROW on a platform where nothing is wrong. A fallback theme says so once
|
|
64
|
+
* instead, and a named theme still wins over it by being registered later.
|
|
65
|
+
*/
|
|
66
|
+
readonly defaultOn?: readonly string[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The one theme shipped now, and it deliberately changes nothing.
|
|
70
|
+
*
|
|
71
|
+
* A GTK application should look like the desktop it is running on, and the accent is
|
|
72
|
+
* the user's — they picked it in Settings and expect their applications to use it.
|
|
73
|
+
* So the neutral theme is an EMPTY document, and that is a statement rather than a
|
|
74
|
+
* placeholder: selecting it is how an application returns to Adwaita exactly, which
|
|
75
|
+
* is measurably true because reloading the provider to the empty string restores
|
|
76
|
+
* every named colour to libadwaita's own value.
|
|
77
|
+
*
|
|
78
|
+
* It is also what makes the registry useful with one theme registered: there is
|
|
79
|
+
* always something to switch back TO.
|
|
80
|
+
*/
|
|
81
|
+
export declare const NEUTRAL_THEME: Theme;
|
|
82
|
+
export interface ThemeRegistryOptions {
|
|
83
|
+
/**
|
|
84
|
+
* Where the provider is installed. Omitted means the default display — the right
|
|
85
|
+
* answer for an application and the wrong one for a test, which is why it is
|
|
86
|
+
* injectable at all.
|
|
87
|
+
*/
|
|
88
|
+
readonly display?: Gdk.Display | null;
|
|
89
|
+
/** Provider priority. Defaults to {@link THEME_PROVIDER_PRIORITY}; see decision 2. */
|
|
90
|
+
readonly priority?: number;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Named themes, one selected, swapped on a single provider.
|
|
94
|
+
*
|
|
95
|
+
* NOT a module-level singleton, unlike the token configuration one layer up. A
|
|
96
|
+
* registry holds a `Gdk.Display` and a `Gtk.CssProvider`, so a test that could not
|
|
97
|
+
* make its own would have to share the session's — and the registry is exactly the
|
|
98
|
+
* object whose whole behaviour is "what is installed on the display right now".
|
|
99
|
+
*/
|
|
100
|
+
export declare class ThemeRegistry {
|
|
101
|
+
#private;
|
|
102
|
+
constructor(options?: ThemeRegistryOptions);
|
|
103
|
+
/**
|
|
104
|
+
* Add a theme, refusing anything that would be a silent no-op.
|
|
105
|
+
*
|
|
106
|
+
* The document is PROBED here rather than at selection, so the error names the
|
|
107
|
+
* line that declared the theme instead of the line that switched to it — which
|
|
108
|
+
* may be a user clicking a row in the application's settings, hours later.
|
|
109
|
+
*/
|
|
110
|
+
register(theme: Theme): this;
|
|
111
|
+
/** The registered names, in registration order. */
|
|
112
|
+
get names(): readonly string[];
|
|
113
|
+
/** The selected theme's name, or null before anything is selected. */
|
|
114
|
+
get current(): string | null;
|
|
115
|
+
/** The document a theme produces. Exposed because a test that cannot read it proves nothing. */
|
|
116
|
+
documentOf(theme: Theme): string;
|
|
117
|
+
/**
|
|
118
|
+
* Switch to a registered theme, replacing whatever was loaded.
|
|
119
|
+
*
|
|
120
|
+
* Idempotent, and cheap enough to call from a settings row's handler: the
|
|
121
|
+
* document was probed at registration, so this is one `load_from_string` plus, on
|
|
122
|
+
* the first call only, one `add_provider_for_display`.
|
|
123
|
+
*/
|
|
124
|
+
select(name: string): void;
|
|
125
|
+
/**
|
|
126
|
+
* Select the theme that declares itself the default for `platform`.
|
|
127
|
+
*
|
|
128
|
+
* The platform is a PARAMETER and this module never reads `process.platform`
|
|
129
|
+
* itself — the same discipline the intent seam one layer up argues for. It keeps
|
|
130
|
+
* a `process` read (and the OS declaration that comes with one) out of a package
|
|
131
|
+
* whose job is GTK, and it lets a settings screen preview another desktop's look
|
|
132
|
+
* by passing that desktop's name.
|
|
133
|
+
*
|
|
134
|
+
* The last registered match wins, so an application registering its own theme
|
|
135
|
+
* after the neutral one gets its own — including over a theme that declares
|
|
136
|
+
* `'*'`, which is how the shipped neutral default stays a fallback rather than a
|
|
137
|
+
* ceiling.
|
|
138
|
+
*/
|
|
139
|
+
selectDefault(platform: string): void;
|
|
140
|
+
/**
|
|
141
|
+
* Take the theme document off the display, leaving nothing behind.
|
|
142
|
+
*
|
|
143
|
+
* Selecting the neutral theme reloads the document to empty, which is all an
|
|
144
|
+
* application needs. It is NOT all a TEST needs, and the difference was measured
|
|
145
|
+
* in this file's own spec: a vector that read "libadwaita's own accent" read the
|
|
146
|
+
* PREVIOUS vector's green instead, because that registry's provider was still on
|
|
147
|
+
* the shared display with a `--accent-bg-color` in it — and the assertion named
|
|
148
|
+
* "back to Adwaita exactly" then passed against the green. Ownership belongs with
|
|
149
|
+
* whoever created the registry, so there has to be a way to give it up.
|
|
150
|
+
*
|
|
151
|
+
* The provider is removed from the display it was INSTALLED on rather than from
|
|
152
|
+
* whatever `Gdk.Display.get_default()` answers now. A later `select()` installs
|
|
153
|
+
* again: position relative to the generated sheet is decided by the priority
|
|
154
|
+
* numbers, not by insertion order, so re-installing cannot land in the wrong
|
|
155
|
+
* place (decision 2).
|
|
156
|
+
*/
|
|
157
|
+
dispose(): void;
|
|
158
|
+
}
|
|
@@ -43,8 +43,84 @@ export interface StyleTokens {
|
|
|
43
43
|
* scale would let a project's typo resolve against a value nobody chose, which is
|
|
44
44
|
* the failure the declared-vocabulary rule exists to prevent — and it would make
|
|
45
45
|
* "the values come from the project" false in the common case.
|
|
46
|
+
*
|
|
47
|
+
* That decision stands, and {@link TAILWIND_DEFAULT_TOKENS} is not a retreat from
|
|
48
|
+
* it: the measured gap is that a project REPLACING this default with its own
|
|
49
|
+
* generated scales loses `0` and `full`, which nothing in its `@theme` was ever
|
|
50
|
+
* going to declare. The answer is an opt-in a reader can see in their own code, not
|
|
51
|
+
* a wider default nobody chose. This constant stays as small as it is.
|
|
46
52
|
*/
|
|
47
53
|
export declare const MINIMAL_TOKENS: StyleTokens;
|
|
54
|
+
/**
|
|
55
|
+
* The Tailwind defaults a project's own `@theme` does not replace — OPT-IN.
|
|
56
|
+
*
|
|
57
|
+
* MEASURED, and this is the highest-frequency finding of the whole exercise. Running
|
|
58
|
+
* one production-shaped application's real class vocabulary — 87 distinct utilities,
|
|
59
|
+
* 826 occurrences — through this partition with tokens generated mechanically from
|
|
60
|
+
* its Tailwind v4 `@theme` resolves **81 of 87 distinct and 803 of 826 occurrences**.
|
|
61
|
+
* Five of the six failures are one thing: `rounded-full` (11 uses) and
|
|
62
|
+
* `inset-0`/`left-0`/`right-0`/`top-0` (9 between them). The project's declared
|
|
63
|
+
* scales simply have no `full` and no `0`.
|
|
64
|
+
*
|
|
65
|
+
* They have no reason to. **`0` and `full` are not design decisions.** A token source
|
|
66
|
+
* emits the values a designer chose; `inset-0` means "flush" and `rounded-full` means
|
|
67
|
+
* "a pill", and neither is a number anybody picked. A project that declares its whole
|
|
68
|
+
* palette still leans on Tailwind for the STRUCTURAL tokens, and finds out one class
|
|
69
|
+
* at a time.
|
|
70
|
+
*
|
|
71
|
+
* So this set is deliberately NOT a copy of Tailwind's default theme, and the name
|
|
72
|
+
* would be a lie if it carried the numeric ladder: shipping `spacing-4` … `spacing-96`
|
|
73
|
+
* would be shipping a design decision the project has already made differently, which
|
|
74
|
+
* is the opposite of the point. It carries the structural tokens and the keyword sets
|
|
75
|
+
* — the ones a `@theme` has no reason to name — and nothing that is a value someone
|
|
76
|
+
* chose.
|
|
77
|
+
*
|
|
78
|
+
* THREE DIVERGENCES FROM TAILWIND'S OWN NUMBERS, each forced and each measured:
|
|
79
|
+
*
|
|
80
|
+
* - **Every length is px, not rem.** Tailwind v4's spacing is rem-based. A `rem`
|
|
81
|
+
* token reaches CSS padding unchanged and is a NAMED ERROR the moment the same
|
|
82
|
+
* token is asked to become a margin, because `Gtk.Widget:margin-top` is a `gint`
|
|
83
|
+
* of device pixels with no unit conversion behind it. A rem scale here would
|
|
84
|
+
* therefore trade "the token is missing" for "the token throws on half the
|
|
85
|
+
* families", which is worse.
|
|
86
|
+
* - **`full` is `9999px`, not `calc(infinity * 1px)`.** GTK's parser has no
|
|
87
|
+
* infinity, and a border radius larger than the box is clamped anyway.
|
|
88
|
+
* - **`inherit` is absent from the colours.** `color: inherit` parses, but
|
|
89
|
+
* `alpha(inherit, 0.5)` does not (measured: *"inherit" is not a valid color
|
|
90
|
+
* name*), so `bg-inherit/50` would be a refusal rather than a colour. The other
|
|
91
|
+
* four keywords survive the alpha modifier and are carried.
|
|
92
|
+
*
|
|
93
|
+
* Opting in is a VISIBLE LINE in the consumer's code, which is the whole design:
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* configureStyle({ tokens: mergeTokens(TAILWIND_DEFAULT_TOKENS, projectTokens) });
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* Use {@link mergeTokens} and not a spread. `{ ...TAILWIND_DEFAULT_TOKENS,
|
|
100
|
+
* ...projectTokens }` replaces whole SCALES, so a project declaring any `spacing` at
|
|
101
|
+
* all loses `0` again — which is the exact bug this constant exists to answer.
|
|
102
|
+
*/
|
|
103
|
+
export declare const TAILWIND_DEFAULT_TOKENS: StyleTokens;
|
|
104
|
+
/**
|
|
105
|
+
* Several token sets into one, merging PER TOKEN and not per scale.
|
|
106
|
+
*
|
|
107
|
+
* The distinction is the whole function. `{ ...defaults, ...project }` is an object
|
|
108
|
+
* spread over the SCALE names, so a project that declares any `spacing` replaces the
|
|
109
|
+
* default `spacing` wholesale and loses `0` — silently, and visible only as
|
|
110
|
+
* `inset-0` throwing much later. Later sets win token by token, which is what a
|
|
111
|
+
* reader means by "my values on top of the defaults".
|
|
112
|
+
*/
|
|
113
|
+
export declare function mergeTokens(...sets: readonly StyleTokens[]): StyleTokens;
|
|
114
|
+
/**
|
|
115
|
+
* The sentence a scale-miss error adds when Tailwind's defaults DO define the token.
|
|
116
|
+
*
|
|
117
|
+
* The measured six failures each become a one-line fix with this and stay a search
|
|
118
|
+
* without it: "not in the borderRadius scale. Known: l, m, s" sends a reader to
|
|
119
|
+
* invent a radius, where naming the opt-in sends them to the line that was missing.
|
|
120
|
+
* Empty for a token nothing would have answered, so an ordinary typo is not offered
|
|
121
|
+
* a remedy that would not have helped.
|
|
122
|
+
*/
|
|
123
|
+
export declare function tailwindDefaultHint(scaleName: string, token: string): string;
|
|
48
124
|
/** A token's value, or `undefined` when the scale is absent or does not carry it. */
|
|
49
125
|
export declare const lookupToken: (scale: Scale | undefined, token: string) => string | undefined;
|
|
50
126
|
/**
|
package/lib/types/types.d.ts
CHANGED
|
@@ -117,12 +117,43 @@ export type ChildPolicy = {
|
|
|
117
117
|
remove: string;
|
|
118
118
|
wrap: 'list-box-row' | 'flow-box-child' | null;
|
|
119
119
|
}
|
|
120
|
-
/**
|
|
120
|
+
/**
|
|
121
|
+
* `Adw.HeaderBar`, `Adw.ToolbarView`, `Adw.ActionRow`: named attachment points.
|
|
122
|
+
*
|
|
123
|
+
* `remove` is OPTIONAL because a slot can be backed two ways and only one of them
|
|
124
|
+
* needs it. A `set_`-prefixed slot is emptied by writing `null` back through the
|
|
125
|
+
* same setter (`detachChild` already does exactly that, via `setterSlotOf`), so a
|
|
126
|
+
* policy whose slots are ALL setters never reaches a remove method — and
|
|
127
|
+
* `Adw.NavigationSplitView` / `Adw.OverlaySplitView` have none to name: measured on
|
|
128
|
+
* libadwaita 1.9.3, their only `remove*` methods are `GtkWidget`'s
|
|
129
|
+
* (`remove_controller`, `remove_css_class`, …). Declaring `remove: 'remove'` there
|
|
130
|
+
* would be a claim `descriptorProblems()` correctly rejects.
|
|
131
|
+
*
|
|
132
|
+
* An ADDER-backed slot (`add_top_bar`, `pack_start`) is the opposite: nothing takes
|
|
133
|
+
* a child back out of it but a remove method, so `remove` is REQUIRED the moment one
|
|
134
|
+
* slot does not start with `set_`. That rule is machine-checked in `policyProblems()`
|
|
135
|
+
* rather than left to this comment — optional in the type and unchecked would turn
|
|
136
|
+
* `Adw.ToolbarView` losing its `remove` into a `TypeError` deep inside an unmount.
|
|
137
|
+
*/
|
|
121
138
|
| {
|
|
122
139
|
kind: 'slotted';
|
|
123
140
|
slots: Record<string, string>;
|
|
124
141
|
defaultSlot: string;
|
|
125
|
-
remove
|
|
142
|
+
remove?: string;
|
|
143
|
+
/**
|
|
144
|
+
* Slots whose adder hands the child to an inner `Gtk.ListBox`, and which
|
|
145
|
+
* therefore need the same wrap `indexed` declares — keyed by slot, because a
|
|
146
|
+
* widget can have one such slot and two ordinary ones.
|
|
147
|
+
*
|
|
148
|
+
* MEASURED on GTK 4.22.4, and it is the wrap or a leak: `gtk_list_box_remove`
|
|
149
|
+
* does NOT unwrap. A `Gtk.ListBox` given a non-row child puts it inside an
|
|
150
|
+
* implicit `GtkListBoxRow`, and removing the ORIGINAL child then answers
|
|
151
|
+
* `Gtk-WARNING **: Tried to remove non-child 0x…` and leaves it parented —
|
|
152
|
+
* with a plain `Gtk.Label` and with a `Gtk.Button` alike. `Adw.ExpanderRow`'s
|
|
153
|
+
* `add_row` is that adder, so its disclosure slot declares the wrap and the
|
|
154
|
+
* host addresses the row it made.
|
|
155
|
+
*/
|
|
156
|
+
wrapSlots?: Readonly<Record<string, 'list-box-row'>>;
|
|
126
157
|
}
|
|
127
158
|
/**
|
|
128
159
|
* `Gtk.Stack`, `Adw.NavigationView`: children addressed by name/tag.
|
|
@@ -139,6 +170,55 @@ export type ChildPolicy = {
|
|
|
139
170
|
remove: string;
|
|
140
171
|
nameFrom: string;
|
|
141
172
|
titled: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Take the child out of view BEFORE the parent removes it, and put its
|
|
175
|
+
* own `visible` back afterwards. Declared per widget, because it is a
|
|
176
|
+
* defect in one of them rather than a property of being keyed.
|
|
177
|
+
*
|
|
178
|
+
* The defect is libadwaita's. `stack_remove` — what both
|
|
179
|
+
* `adw_view_stack_remove` and dispose call — clears `visible_child`, then
|
|
180
|
+
* does `g_clear_object (&page->widget)`, and never touches
|
|
181
|
+
* `last_visible_child`, which can still point at that same page. A later
|
|
182
|
+
* reader then dereferences a page whose widget is NULL:
|
|
183
|
+
*
|
|
184
|
+
* Gtk-CRITICAL **: gtk_widget_set_child_visible: assertion 'GTK_IS_WIDGET (widget)' failed
|
|
185
|
+
*
|
|
186
|
+
* Source: `refs/libadwaita/src/adw-view-stack.c` — `stack_remove` at 1184,
|
|
187
|
+
* the stale read at 934 in `transition_done_cb`. Read at 42f647f
|
|
188
|
+
* (1.10.alpha.1); that file is byte-identical at the 1.9.3 tag, which is
|
|
189
|
+
* what is installed here, so one reading covers both.
|
|
190
|
+
*
|
|
191
|
+
* MEASURED on libadwaita 1.9.3 / GTK 4.22.4 / GJS 1.88.1. Reproducer, no
|
|
192
|
+
* renderer involved: add `a` and `b`, present a window holding the stack,
|
|
193
|
+
* `set_visible_child_name('b')`, `remove(a)`, then let the window go away.
|
|
194
|
+
* Each precondition alone is silent, a stack never made visible included —
|
|
195
|
+
* `set_visible_child` only records `last_visible_child` when
|
|
196
|
+
* `gtk_widget_is_visible` answers yes. `Gtk.Stack` and
|
|
197
|
+
* `Adw.NavigationView`, the other two `keyed` descriptors, do not
|
|
198
|
+
* reproduce it at all, which is why this is a field and not the kind.
|
|
199
|
+
*
|
|
200
|
+
* WHICH read fires decides what a test has to do, so it is measured rather
|
|
201
|
+
* than listed: the UNMAP one. `AdwAnimation` connects `adw_animation_skip`
|
|
202
|
+
* to its widget's `unmap` (`adw-animation.c`) and the skip runs
|
|
203
|
+
* `transition_done_cb`, so merely hiding the window is enough and
|
|
204
|
+
* destroying it does the same — while a queued resize plus draw, and a
|
|
205
|
+
* direct `measure()`, both stayed quiet. The file's other reads (snapshot,
|
|
206
|
+
* size-allocate, measure) are real paths this reproducer does not reach.
|
|
207
|
+
*
|
|
208
|
+
* Hiding first is libadwaita's OWN cleanup: the visibility notify runs
|
|
209
|
+
* `update_child_visible`, which does clear `last_visible_child`. Measured
|
|
210
|
+
* SUFFICIENT and not merely necessary — 400 randomised
|
|
211
|
+
* add/remove/switch/reorder steps against a live 200 ms transition, three
|
|
212
|
+
* seeds, 44/23/25 criticals unpatched against 0/0/0 patched.
|
|
213
|
+
*
|
|
214
|
+
* The restore is load-bearing. `reorderMode` answers `remove-all` for
|
|
215
|
+
* `keyed`, and measured, a reversal that hides without restoring leaves the
|
|
216
|
+
* stack with no visible child and no way back: the last line of
|
|
217
|
+
* `adw_view_stack_set_visible_child_name` is
|
|
218
|
+
* `if (gtk_widget_get_visible (page->widget)) set_visible_child (...)`, so
|
|
219
|
+
* for a hidden page it is a no-op with no warning at all.
|
|
220
|
+
*/
|
|
221
|
+
hideBeforeRemove?: boolean;
|
|
142
222
|
}
|
|
143
223
|
/** `Gtk.Grid`: position is data on the child, so document order carries nothing. */
|
|
144
224
|
| {
|
|
@@ -150,14 +230,14 @@ export type ChildPolicy = {
|
|
|
150
230
|
* Generated, not curated: the tag exists, its placement rule does not.
|
|
151
231
|
*
|
|
152
232
|
* The generated table adds every concrete GtkWidget descendant the GIR
|
|
153
|
-
* describes
|
|
233
|
+
* describes, plus the placement carriers, while the curated table measures placement for a
|
|
154
234
|
* fraction. Guessing an adder for the rest would be the worst of the three
|
|
155
235
|
* options: `add` and `append` and `set_child` all exist somewhere in GTK, and
|
|
156
236
|
* calling the wrong one is a warning at exit 0.
|
|
157
237
|
*
|
|
158
238
|
* So the honest state is spelled out. Such a widget can be CREATED and given
|
|
159
239
|
* properties and handlers; inserting a child raises a named error that says
|
|
160
|
-
* which tag needs a curated policy. A leaf widget — most of the
|
|
240
|
+
* which tag needs a curated policy. A leaf widget — most of the table — needs
|
|
161
241
|
* nothing more.
|
|
162
242
|
*/
|
|
163
243
|
| {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/gtk-host",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"description": "Framework-agnostic GTK4/Adwaita host: the element model UI-framework renderers bind to",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"types": "./lib/types/style/index.d.ts",
|
|
15
15
|
"default": "./lib/esm/style/index.js"
|
|
16
16
|
},
|
|
17
|
+
"./list": {
|
|
18
|
+
"types": "./lib/types/list/index.d.ts",
|
|
19
|
+
"default": "./lib/esm/list/index.js"
|
|
20
|
+
},
|
|
17
21
|
"./vue": {
|
|
18
22
|
"types": "./lib/types/adapters/vue.d.ts",
|
|
19
23
|
"default": "./lib/esm/adapters/vue.js"
|
|
@@ -67,11 +71,11 @@
|
|
|
67
71
|
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
68
72
|
"build:types": "gjsify tsc",
|
|
69
73
|
"build:test": "gjsify run build:test:gjs",
|
|
70
|
-
"build:test:node": "gjsify build src/test.mts --app node --outfile dist/test.node.mjs --define
|
|
71
|
-
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs --define
|
|
74
|
+
"build:test:node": "gjsify build src/test.mts --app node --outfile dist/test.node.mjs --define __VUE_OPTIONS_API__=false --define __VUE_PROD_DEVTOOLS__=false --define __VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false --define \"process.env.NODE_ENV='production'\" --exclude-globals navigator",
|
|
75
|
+
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs --define __VUE_OPTIONS_API__=false --define __VUE_PROD_DEVTOOLS__=false --define __VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false --define \"process.env.NODE_ENV='production'\" --exclude-globals navigator",
|
|
72
76
|
"test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:gjs",
|
|
73
77
|
"test:gjs": "gjsify run test.gjs.mjs",
|
|
74
|
-
"test:gjs-on-node": "gjsify run build:gjsify && gjsify run build:test:node &&
|
|
78
|
+
"test:gjs-on-node": "gjsify run build:gjsify && gjsify run build:test:node && node dist/test.node.mjs",
|
|
75
79
|
"generate": "gjsify build src/generator/main.mts --app gjs --outfile tmp/generate.gjs.mjs && gjsify run tmp/generate.gjs.mjs -- --out src/generated && gjsify format src/generated"
|
|
76
80
|
},
|
|
77
81
|
"keywords": [
|
|
@@ -82,14 +86,14 @@
|
|
|
82
86
|
"host"
|
|
83
87
|
],
|
|
84
88
|
"dependencies": {
|
|
85
|
-
"@girs/adw-1": "
|
|
86
|
-
"@girs/gdk-4.0": "
|
|
87
|
-
"@girs/gio-2.0": "
|
|
88
|
-
"@girs/gjs": "
|
|
89
|
-
"@girs/glib-2.0": "
|
|
90
|
-
"@girs/gobject-2.0": "
|
|
91
|
-
"@girs/gtk-4.0": "
|
|
92
|
-
"@girs/pango-1.0": "
|
|
89
|
+
"@girs/adw-1": "4.6.0",
|
|
90
|
+
"@girs/gdk-4.0": "4.6.0",
|
|
91
|
+
"@girs/gio-2.0": "4.6.0",
|
|
92
|
+
"@girs/gjs": "4.6.0",
|
|
93
|
+
"@girs/glib-2.0": "4.6.0",
|
|
94
|
+
"@girs/gobject-2.0": "4.6.0",
|
|
95
|
+
"@girs/gtk-4.0": "4.6.0",
|
|
96
|
+
"@girs/pango-1.0": "4.6.0"
|
|
93
97
|
},
|
|
94
98
|
"peerDependencies": {
|
|
95
99
|
"@vue/runtime-core": "^3.5.0",
|
|
@@ -112,13 +116,12 @@
|
|
|
112
116
|
}
|
|
113
117
|
},
|
|
114
118
|
"devDependencies": {
|
|
115
|
-
"@gjsify/cli": "^0.
|
|
119
|
+
"@gjsify/cli": "^0.46.0",
|
|
116
120
|
"@vue/runtime-core": "^3.5.0",
|
|
117
121
|
"solid-js": "^1.9.0",
|
|
118
|
-
"@gjsify/unit": "^0.
|
|
122
|
+
"@gjsify/unit": "^0.46.0",
|
|
119
123
|
"@types/node": "^25.9.2",
|
|
120
124
|
"typescript": "^6.0.3",
|
|
121
|
-
"@gjsify/domparser": "^0.44.0",
|
|
122
125
|
"@gjsify/node-gi": "file:../../node-gi/node-gi",
|
|
123
126
|
"vue": "^3.5.41",
|
|
124
127
|
"vue-tsc": "^3.3.11",
|
|
@@ -134,7 +137,10 @@
|
|
|
134
137
|
"browser": "none",
|
|
135
138
|
"nativescript": "none"
|
|
136
139
|
},
|
|
137
|
-
"tier": 3
|
|
140
|
+
"tier": 3,
|
|
141
|
+
"widgetVocabulary": {
|
|
142
|
+
"role": "reference"
|
|
143
|
+
}
|
|
138
144
|
},
|
|
139
145
|
"license": "MIT",
|
|
140
146
|
"repository": {
|