uxml-preview 0.6.0 → 0.7.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.
@@ -1,87 +1,63 @@
1
1
  /**
2
2
  * Unity's control defaults, as far as we have measured them.
3
3
  *
4
- * Unity ships a theme stylesheet that gives controls their own margin, padding
5
- * and border before any author USS runs. This renderer supplied none of it, so
6
- * every Button sat 3px left and 1px high of where Unity puts it — invisible on
7
- * one button and compounding across a row.
8
- *
9
- * **Only measured values live here.** Every declaration below was derived from
10
- * a Unity layout dump in tests/golden/unity/, and adding `Button`'s margin
11
- * moved all five Button cases from 18 mismatched values to zero. Values read
12
- * from Unity's source instead would look identical in this file while being
13
- * wrong in a way no test could see: they would not appear in the unmeasured
14
- * list, so they would quietly pass for ground truth.
15
- *
16
- * Two kinds of measurement feed this file, and the second was a long time
17
- * coming. Geometry comes from the coordinate dumps. `-unity-text-align` cannot:
18
- * where a glyph sits inside a box does not move the box, so no dump can ever
19
- * see it. It came from the Step 6 eye check — Unity centres a Button's label
20
- * and this renderer had it at the top left, which is visible the moment the two
21
- * screenshots sit side by side and invisible in 368 compared numbers.
22
- *
23
- * `opacity` on `:disabled` came from the same screenshots, but by sampling
24
- * pixels rather than looking. Unity's disabled Drop button is rgb(41,50,67);
25
- * the base colour rgb(58,74,104) composited at half over the footer's
26
- * rgb(24,26,31) is (41, 50, 67.5) — all three channels exact. That arithmetic
27
- * is the evidence, and it is why the value is 0.5 and not a number that merely
28
- * looked about right.
29
- *
30
- * Getting there took two wrong turns worth recording. First the author's
31
- * `Button:disabled` rule was blamed for not applying — it genuinely does not,
32
- * because `#DropButton` outranks it, in both engines. Then Unity was accused of
33
- * ranking state rules above specificity, and `state-vs-id` and `state-vs-inline`
34
- * refuted that: Unity answers 40 to both, exactly as this cascade already did.
35
- * The dimming was never about the cascade at all.
36
- *
37
- * What is deliberately absent, and why:
38
- *
39
- * - `Label` — measured, and it has no default margin. `inherit-vs-direct`
40
- * puts an explicitly-sized Label at the origin of a sized parent, and Unity
41
- * reports x=0 y=0. Nothing to add is a result, not an omission.
42
- * - padding, border, font — invisible to the cases we have. Every compared
43
- * element is explicitly sized, and USS is border-box, so padding and border
44
- * do not move the outer rectangle. They are unmeasured, so they are not here.
45
- * - `Label`'s text alignment — the eye check could not separate it from the
46
- * box at this size. Unmeasured, so absent.
47
- *
48
- * The class names were a separate claim from the values, and are now measured
49
- * too. `unity-button` came from Unity's documented `Button.ussClassName`, which
50
- * the margin dumps said nothing about — they proved the spacing, not the
51
- * selector delivering it. The golden case `theme-class-hook` was written to
52
- * settle exactly that, and Unity answered on 2026-08-05: a `.unity-button` rule
53
- * in author USS reaches a bare `<ui:Button>`, sizing it 120×40 in both engines.
54
- * The selector below is therefore measured, not assumed.
55
- */
56
- /** Where every value in this file was measured. Theme values move between versions. */
57
- export declare const THEME_UNITY_VERSION = "6000.0.40f1";
58
- /**
59
- * Parsed once and spliced in ahead of author sheets, so an author rule of equal
60
- * specificity wins on order — which is how a theme stylesheet behaves in Unity.
61
- *
62
- * Class selectors rather than type selectors, also for Unity's reasons: a theme
63
- * rule at `.unity-button` (0,1,0) beats an author's `Button { }` (0,0,1), and
64
- * that is a real Unity gotcha worth reproducing rather than smoothing over.
4
+ * Unity supplies control spacing before author USS runs; omitting it once put
5
+ * every Button 3px left and 1px high, compounding across a row. Only measured
6
+ * values live here. Values copied from Unity's source could look just as
7
+ * authoritative while being wrong without appearing in the unmeasured list.
8
+ *
9
+ * There are two measured themes: editor in an EditorWindow on 6000.0.40f1
10
+ * (tests/layout/unity/6000.0.40f1/probe-editor-070/), runtime on a real runtime
11
+ * panel on 6000.3.25f1 (tests/layout/unity/6000.3.25f1/probe-panel/), with
12
+ * identical runtime values on 6000.0.40f1. Geometry comes from coordinate dumps.
13
+ * `-unity-text-align` came from the Step 6 eye check: a glyph's position inside
14
+ * its box does not move the box, so 368 matching coordinates could not reveal
15
+ * that Unity centred Button text while this renderer put it at the top left.
16
+ *
17
+ * Opacity 0.5 was established by pixel arithmetic: Unity's disabled Drop button
18
+ * is rgb(41,50,67); its base rgb(58,74,104) composited at half over the footer's
19
+ * rgb(24,26,31) gives (41,50,67.5). It is measured, not chosen by appearance.
20
+ * `nested-disabled` now places it on `.unity-disabled`, which Unity adds only
21
+ * where enabled="false" was written. This replaces the earlier `:disabled`
22
+ * rule that applied half opacity at every disabled level and dimmed twice.
23
+ *
24
+ * Two wrong turns preceded that result. The author's `Button:disabled` rule
25
+ * was first blamed for not applying, but `#DropButton` outranks it in both
26
+ * engines. Then state rules were thought to outrank specificity; `state-vs-id`
27
+ * and `state-vs-inline` both returned 40 in Unity, refuting that explanation.
28
+ * The dimming was never a cascade defect.
29
+ *
30
+ * Earlier omissions, superseded by c07-existing and c07-states:
31
+ * - "Label has nothing" described only its measured editor margin; Label and
32
+ * Button spacing and flex-shrink are now measured for both themes.
33
+ * - "Padding, border, font deliberately absent" is superseded by measured
34
+ * padding, borders, colours and font size; Label text alignment stays absent.
35
+ *
36
+ * Class hooks are a separate claim from values: margin dumps proved spacing,
37
+ * not the selector delivering it. `unity-button` began with the documented
38
+ * Button.ussClassName; `theme-class-hook` then confirmed on 2026-08-05 that
39
+ * author `.unity-button` reaches a bare <ui:Button>, sizing it 120×40 in Unity
40
+ * and this renderer. The hook is measured, not assumed.
65
41
  */
66
- export declare const THEME_USS = ":disabled {\n opacity: 0.5;\n}\n\n.unity-button {\n margin: 1px 3px;\n -unity-text-align: middle-center;\n}\n";
42
+ export type Theme = 'runtime' | 'editor';
43
+ export declare const DEFAULT_THEME: Theme;
44
+ /** Unity version used to measure the editor theme. */
45
+ export declare const THEME_UNITY_VERSION: string;
46
+ /** Unity measurement version for each theme. */
47
+ export declare const THEME_UNITY_VERSIONS: Readonly<Record<Theme, string>>;
48
+ /** Panel defaults inherited by the rendered elements. */
49
+ export declare const PANEL_TEXT_DEFAULTS_SELECTOR = "UXML";
67
50
  /**
68
- * **Unmeasured, and reachable: nested disabled elements.**
69
- *
70
- * `enabled="false"` puts a whole subtree into `:disabled` — measured, by
71
- * `disabled-inherits`. The rule above therefore hands every level its own
72
- * `opacity: 0.5`, and CSS multiplies them, so a disabled button inside a
73
- * disabled panel comes out at a quarter. Unity almost certainly dims once.
74
- *
75
- * Not guessed at, because the fix has a choice inside it — dim only where
76
- * `enabled="false"` was written, or suppress the inherited one — and picking
77
- * without evidence is how the `.unity-button` selector became a hypothesis
78
- * nobody noticed for a day. Opacity leaves no trace in a coordinate dump, so
79
- * settling it needs a screenshot of a nested case. Recorded in
80
- * `docs/backlog.md` and visible in `visual-nested-disabled`.
51
+ * Editor theme stylesheet; kept as the legacy editor-sheet export.
52
+ * Parsed once and spliced in ahead of author sheets, so equal specificity lets
53
+ * author rules win on order, as in Unity. Class selectors also preserve Unity's
54
+ * specificity: `.unity-button` (0,1,0) beats an author `Button {}` (0,0,1).
81
55
  */
56
+ export declare const THEME_USS: string;
57
+ export declare const THEME_SHEETS: Readonly<Record<Theme, string>>;
82
58
  /**
83
59
  * Purpose: how much width a vertical scrollbar claims, given whether it shows.
84
60
  * Ensures: 0 when the content fits — Unity hides the scroller rather than
85
61
  * shrinking the viewport for a bar nobody can see.
86
62
  */
87
- export declare function verticalScrollbarWidth(overflows: boolean): number;
63
+ export declare function verticalScrollbarWidth(overflows: boolean, theme?: Theme): number;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Theme } from './controls/theme';
1
2
  import { NodeId, UxmlDocument, Warning } from './model/types';
2
3
  import { ComputedStyle, ResolveResult } from './style/resolve';
3
4
  import { LayoutBox, MeasureText } from './layout/yoga';
@@ -10,6 +11,7 @@ import { ResolveFont } from './render/fonts';
10
11
  * See docs/ROADMAP.md.
11
12
  */
12
13
  export type { Span, SourceRef, NodeId, ElementName, Attribute, ElementSpans, ElementNode, Combinator, SimpleSelector, SelectorPart, Selector, Declaration, Rule, SheetItem, StyleSheet, WarningKind, WarningKindMap, WarningReason, WarningSubject, Warning, UxmlDocument, StyleOrigin, } from './model/types';
14
+ export type { Theme } from './controls/theme';
13
15
  export { collectDependencies, expandTemplates, TEMPLATE_DEPTH_LIMIT } from './template/expand';
14
16
  export type { TemplateExpansion, TemplateResolver } from './template/expand';
15
17
  export { loadLayoutEngine, isLayoutEngineReady, liveNodeCount } from './layout/yoga';
@@ -76,6 +78,14 @@ export declare function serialize(doc: UxmlDocument): {
76
78
  uss: string;
77
79
  };
78
80
  export interface RenderOptions {
81
+ /**
82
+ * Defaults to 'runtime' since 0.7.0 (Unity's PanelSettings runtime theme).
83
+ * 'editor' is Unity's dark editor theme, used for the published 662/676 figure.
84
+ * The core draws no panel background (transparent, as Unity does). Runtime
85
+ * text is dark (#1b1b1b), so hosts drawing on a dark backdrop must provide
86
+ * a panel background.
87
+ */
88
+ theme?: Theme;
79
89
  /** Resolves font assets once per distinct path and form in each render. */
80
90
  resolveFont?: ResolveFont;
81
91
  /**
@@ -127,6 +137,8 @@ export interface RenderOptions {
127
137
  export { classifyVisibility } from './render/visibility';
128
138
  export type { Visibility } from './render/visibility';
129
139
  export interface RenderResult {
140
+ /** The theme actually drawn, after option validation. */
141
+ theme: Theme;
130
142
  /** Expanded document used for rendering, separate from the source AST. */
131
143
  document?: UxmlDocument;
132
144
  /** Computed styles keyed by rendered element id. */