@ng-native/fabric 0.0.1 → 0.1.1
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/LICENSE +21 -0
- package/README.md +54 -1
- package/dist/color-mix.d.ts +20 -0
- package/dist/color-mix.js +306 -0
- package/dist/color-mix.js.map +1 -0
- package/dist/css.d.ts +615 -0
- package/dist/css.js +1405 -0
- package/dist/css.js.map +1 -0
- package/dist/defer-triggers.d.ts +53 -0
- package/dist/defer-triggers.js +184 -0
- package/dist/defer-triggers.js.map +1 -0
- package/dist/engine.d.ts +1066 -0
- package/dist/engine.js +2764 -0
- package/dist/engine.js.map +1 -0
- package/dist/fabric.d.ts +20 -0
- package/dist/fabric.js +44 -0
- package/dist/fabric.js.map +1 -0
- package/dist/forms-inputs.d.ts +15 -0
- package/dist/forms-inputs.js +54 -0
- package/dist/forms-inputs.js.map +1 -0
- package/dist/host.d.ts +133 -0
- package/dist/host.js +55 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/inline-token.d.ts +12 -0
- package/dist/inline-token.js +52 -0
- package/dist/inline-token.js.map +1 -0
- package/dist/inline-transform.d.ts +14 -0
- package/dist/inline-transform.js +41 -0
- package/dist/inline-transform.js.map +1 -0
- package/dist/native-drive.d.ts +100 -0
- package/dist/native-drive.js +318 -0
- package/dist/native-drive.js.map +1 -0
- package/dist/relative-colour.d.ts +17 -0
- package/dist/relative-colour.js +71 -0
- package/dist/relative-colour.js.map +1 -0
- package/dist/scroll-animation.d.ts +41 -0
- package/dist/scroll-animation.js +169 -0
- package/dist/scroll-animation.js.map +1 -0
- package/dist/transition.d.ts +139 -0
- package/dist/transition.js +569 -0
- package/dist/transition.js.map +1 -0
- package/package.json +43 -3
package/dist/css.d.ts
ADDED
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime half of the CSS system: selector matching and the cascade.
|
|
3
|
+
*
|
|
4
|
+
* All the expensive work happened at build time (parsing, longhand expansion, value conversion,
|
|
5
|
+
* specificity maths, sorting), so this only walks a pre-sorted rule list and merges. It is
|
|
6
|
+
* framework-agnostic and knows nothing about Angular.
|
|
7
|
+
*/
|
|
8
|
+
import { type HueMethod, type MixSpace } from './color-mix.ts';
|
|
9
|
+
import { type Channel } from './relative-colour.ts';
|
|
10
|
+
import type { Keyframe } from './transition.ts';
|
|
11
|
+
/** One `[name]` or `[name op "value"]` test. */
|
|
12
|
+
export interface AttributeTest {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
/** Absent means a presence test. */
|
|
15
|
+
readonly operator?: 'equal' | 'prefix' | 'suffix' | 'substring' | 'includes' | 'dash-match';
|
|
16
|
+
readonly value?: string;
|
|
17
|
+
/** The `i` flag: the value is compared without case, and is written here in lower case. */
|
|
18
|
+
readonly insensitive?: true;
|
|
19
|
+
}
|
|
20
|
+
export interface Compound {
|
|
21
|
+
readonly type?: string;
|
|
22
|
+
readonly id?: string;
|
|
23
|
+
/** `:root`: the node at the top of the tree. */
|
|
24
|
+
readonly root?: true;
|
|
25
|
+
readonly classes: readonly string[];
|
|
26
|
+
readonly attributes?: readonly AttributeTest[];
|
|
27
|
+
/** `:is()` / `:where()` arguments: the compound matches if any of these do. */
|
|
28
|
+
readonly is?: readonly (readonly Compound[])[];
|
|
29
|
+
/** `:not()` arguments: the compound matches only if none of these do. */
|
|
30
|
+
readonly not?: readonly Compound[];
|
|
31
|
+
/** `:host`: the node must be the host of the component whose sheet is being evaluated. */
|
|
32
|
+
readonly host?: true;
|
|
33
|
+
/** `:host-context()`: the host, or one of its ancestors, must match one of these. */
|
|
34
|
+
readonly hostContext?: readonly Compound[];
|
|
35
|
+
/**
|
|
36
|
+
* `:is(<compound> *)`: every one of these must match some ancestor, the node itself excluded.
|
|
37
|
+
* What Tailwind's `group-*` variants compile to.
|
|
38
|
+
*/
|
|
39
|
+
readonly ancestors?: readonly Compound[];
|
|
40
|
+
/** Interaction state the engine tracks: `:focus` and `:active`. */
|
|
41
|
+
readonly pseudo?: readonly ('focus' | 'active')[];
|
|
42
|
+
/**
|
|
43
|
+
* `:first-child` and its family, reduced to the counting tests CSS defines them as. More than
|
|
44
|
+
* one because `:only-child` is two: first from the start and first from the end.
|
|
45
|
+
*/
|
|
46
|
+
readonly nth?: readonly NthTest[];
|
|
47
|
+
/** `:empty`: no children at all, text included. */
|
|
48
|
+
readonly empty?: true;
|
|
49
|
+
}
|
|
50
|
+
/** `an + b`, counted from the start unless `fromEnd`. */
|
|
51
|
+
export interface NthTest {
|
|
52
|
+
readonly a: number;
|
|
53
|
+
readonly b: number;
|
|
54
|
+
readonly fromEnd?: true;
|
|
55
|
+
}
|
|
56
|
+
export type Combinator = 'descendant' | 'child' | 'next-sibling' | 'later-sibling';
|
|
57
|
+
export interface StyleRule {
|
|
58
|
+
readonly compounds: readonly Compound[];
|
|
59
|
+
/** Between compounds; length is `compounds.length - 1`. */
|
|
60
|
+
readonly combinators: readonly Combinator[];
|
|
61
|
+
readonly specificity: number;
|
|
62
|
+
readonly order: number;
|
|
63
|
+
readonly declarations: Readonly<Record<string, unknown>>;
|
|
64
|
+
readonly important?: Readonly<Record<string, unknown>>;
|
|
65
|
+
/** Custom properties this rule defines, pre-converted into every form a use site might want. */
|
|
66
|
+
readonly tokens?: Readonly<Record<string, TokenValue>>;
|
|
67
|
+
/** Declarations whose value is a `var()`, resolved once the token map is known. */
|
|
68
|
+
readonly deferred?: readonly DeferredDeclaration[];
|
|
69
|
+
/** The media query guarding this rule, if any. */
|
|
70
|
+
readonly condition?: MediaCondition;
|
|
71
|
+
/** Memo of the last condition evaluation, and the conditions version it was made against. */
|
|
72
|
+
activeAt?: number;
|
|
73
|
+
active?: boolean;
|
|
74
|
+
}
|
|
75
|
+
export type MediaCondition = {
|
|
76
|
+
readonly all: readonly MediaCondition[];
|
|
77
|
+
} | {
|
|
78
|
+
readonly any: readonly MediaCondition[];
|
|
79
|
+
} | {
|
|
80
|
+
readonly feature: 'width' | 'height';
|
|
81
|
+
readonly op: 'gt' | 'gte' | 'lt' | 'lte' | 'eq';
|
|
82
|
+
readonly value: number;
|
|
83
|
+
} | {
|
|
84
|
+
readonly feature: 'orientation' | 'prefers-color-scheme' | 'prefers-reduced-motion';
|
|
85
|
+
readonly value: string;
|
|
86
|
+
};
|
|
87
|
+
/** What media queries are evaluated against. Pushed in by the host: the engine imports no RN. */
|
|
88
|
+
export interface Conditions {
|
|
89
|
+
readonly width: number;
|
|
90
|
+
readonly height: number;
|
|
91
|
+
readonly colorScheme: 'light' | 'dark';
|
|
92
|
+
/**
|
|
93
|
+
* The user asked for less animation. Optional because it is a preference rather than a
|
|
94
|
+
* measurement: an app that never asks the platform gets `no-preference`, which is what a
|
|
95
|
+
* platform that cannot answer means anyway.
|
|
96
|
+
*/
|
|
97
|
+
readonly reducedMotion?: boolean;
|
|
98
|
+
}
|
|
99
|
+
/** A custom property's value, in each form it can legally take. Absent forms are unusable. */
|
|
100
|
+
export interface TokenValue {
|
|
101
|
+
readonly length?: number | string;
|
|
102
|
+
/** An angle, in degrees whatever unit it was written in. */
|
|
103
|
+
readonly angle?: number;
|
|
104
|
+
/** A time, in milliseconds whatever unit it was written in. */
|
|
105
|
+
readonly time?: number;
|
|
106
|
+
readonly color?: string;
|
|
107
|
+
readonly keyword?: string;
|
|
108
|
+
readonly number?: number;
|
|
109
|
+
/** A font weight, as the string `fontWeight` takes. */
|
|
110
|
+
readonly weight?: string;
|
|
111
|
+
/** The first family of a font stack. A single word is read from `keyword` instead. */
|
|
112
|
+
readonly family?: string;
|
|
113
|
+
/**
|
|
114
|
+
* A bare number as a line-height: a multiple of the font size, settled where it is used. A
|
|
115
|
+
* length is read from `length` instead.
|
|
116
|
+
*/
|
|
117
|
+
readonly lineHeight?: {
|
|
118
|
+
readonly __defer: DeferredDeclaration['compute'];
|
|
119
|
+
};
|
|
120
|
+
/** A whole shadow list, in the processed shape `boxShadow` takes. */
|
|
121
|
+
readonly shadow?: readonly unknown[];
|
|
122
|
+
/** One filter function, as the one-entry list `filter` takes: a slot of Tailwind's filters. */
|
|
123
|
+
readonly filter?: readonly unknown[];
|
|
124
|
+
/** One transform function, as the one-entry list `transform` takes: a 3D rotation or skew. */
|
|
125
|
+
readonly transform?: readonly unknown[];
|
|
126
|
+
/** One font variant, as the one-entry list `fontVariant` takes: a numeric variant's slot. */
|
|
127
|
+
readonly fontVariant?: readonly string[];
|
|
128
|
+
/** Bare colour channels, `13, 110, 253`, for an `rgba(var(--x), <alpha>)` to finish. */
|
|
129
|
+
readonly channels?: readonly number[];
|
|
130
|
+
/**
|
|
131
|
+
* Defined as `rgba(var(--channels), <alpha>)`: a colour made of a channels token and an alpha
|
|
132
|
+
* written or tokened. Settled on the node that defines it, as an `hsl` one is.
|
|
133
|
+
*/
|
|
134
|
+
readonly deferredColour?: Extract<ColourExpression, {
|
|
135
|
+
channels: unknown;
|
|
136
|
+
}>;
|
|
137
|
+
/**
|
|
138
|
+
* Defined as another token, `var(--name)`. Resolved on the node that defines it, against the
|
|
139
|
+
* tokens in scope there, and passed down resolved - which is what a browser does.
|
|
140
|
+
*/
|
|
141
|
+
readonly alias?: string;
|
|
142
|
+
/** What an alias becomes when the token it names is not defined. */
|
|
143
|
+
readonly fallback?: TokenValue;
|
|
144
|
+
/**
|
|
145
|
+
* Defined as `hsl(var(--h), var(--s), var(--l))`, or `hsla()` with an alpha: how Bulma writes
|
|
146
|
+
* every colour. Resolved into `color` on the node that defines it, alongside its aliases, so a
|
|
147
|
+
* use site never has to know a token was ever built this way.
|
|
148
|
+
*/
|
|
149
|
+
readonly hsl?: {
|
|
150
|
+
readonly h: HslChannel;
|
|
151
|
+
readonly s: HslChannel;
|
|
152
|
+
readonly l: HslChannel;
|
|
153
|
+
readonly alpha?: HslChannel;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/** One channel of an `hsl()` token: settled at build time, or a token to read at match time. */
|
|
157
|
+
export type HslChannel = number | {
|
|
158
|
+
readonly reference: string;
|
|
159
|
+
readonly fallback?: number;
|
|
160
|
+
};
|
|
161
|
+
/** The forms a token can be read in: one per kind of value a use site can need. */
|
|
162
|
+
export type TokenKind = 'length' | 'color' | 'keyword' | 'number' | 'weight' | 'family' | 'lineHeight' | 'shadow' | 'filter' | 'transform' | 'fontVariant' | 'channels';
|
|
163
|
+
export interface DeferredDeclaration {
|
|
164
|
+
/**
|
|
165
|
+
* The React Native style properties this lands in. Usually one, but a four-sided shorthand is
|
|
166
|
+
* unambiguous given a single-valued token, so `padding: var(--gap)` writes all four.
|
|
167
|
+
*/
|
|
168
|
+
readonly props: readonly string[];
|
|
169
|
+
/** A `var()` reference. Exactly one of this and `compute` is present. */
|
|
170
|
+
readonly kind?: TokenKind;
|
|
171
|
+
readonly reference?: string;
|
|
172
|
+
/**
|
|
173
|
+
* The tokens a fallback that is itself a `var()` names, tried in turn when `reference` is not
|
|
174
|
+
* defined: `var(--a, var(--b, green))` is `--a`, then `--b`, then `green`.
|
|
175
|
+
*/
|
|
176
|
+
readonly alternatives?: readonly string[];
|
|
177
|
+
readonly fallback?: unknown;
|
|
178
|
+
/**
|
|
179
|
+
* What to write when the reference resolves, whatever it resolves to: `flex: var(--grow)` sets a
|
|
180
|
+
* shrink of 1 and a basis of 0%, but only when there is a grow for them to go with.
|
|
181
|
+
*/
|
|
182
|
+
readonly whenSet?: unknown;
|
|
183
|
+
/**
|
|
184
|
+
* What to write when the reference resolves to nothing: the property's initial value, which is
|
|
185
|
+
* what a browser gives a property whose `var()` cannot be substituted. Only where it differs
|
|
186
|
+
* from leaving the property out: `flex-shrink` starts at 1 in CSS and at 0 in Yoga.
|
|
187
|
+
*/
|
|
188
|
+
readonly unset?: unknown;
|
|
189
|
+
/**
|
|
190
|
+
* For a colour built from `channels`, the token its alpha comes from:
|
|
191
|
+
* `rgba(var(--bs-primary-rgb), var(--bs-bg-opacity))`. A written alpha is an `adjust` instead.
|
|
192
|
+
*/
|
|
193
|
+
readonly alpha?: {
|
|
194
|
+
readonly reference: string;
|
|
195
|
+
readonly fallback?: number;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* A gradient whose stops are custom properties, filled in once a node's tokens are known. What
|
|
199
|
+
* a utility framework's `from-*` and `to-*` classes compile to, since the class that paints the
|
|
200
|
+
* gradient is not the class that supplies its colours.
|
|
201
|
+
*/
|
|
202
|
+
readonly gradient?: GradientTemplate | readonly GradientTemplate[];
|
|
203
|
+
/**
|
|
204
|
+
* Arithmetic around the reference, settled at build time. `value * scale + offset`, then no
|
|
205
|
+
* smaller than `floor`. What `calc(var(--x) + 12px)` and `max(var(--x), 16px)` become.
|
|
206
|
+
*/
|
|
207
|
+
readonly adjust?: {
|
|
208
|
+
readonly scale?: number;
|
|
209
|
+
readonly offset?: number;
|
|
210
|
+
readonly floor?: number;
|
|
211
|
+
/**
|
|
212
|
+
* A fraction to multiply the resolved colour's alpha by. What
|
|
213
|
+
* `color-mix(in oklab, var(--x) 90%, transparent)` becomes, which is Tailwind's `/90`.
|
|
214
|
+
*/
|
|
215
|
+
readonly alpha?: number;
|
|
216
|
+
};
|
|
217
|
+
/** Declared `!important`: ranked with the important declarations, not the plain ones. */
|
|
218
|
+
readonly important?: true;
|
|
219
|
+
/**
|
|
220
|
+
* A length relative to the viewport or to the font size in scope, plus an absolute `offset`
|
|
221
|
+
* when it came from a sum: `calc(1.375rem + 1.5vw)` is 1.5vw with 22 added.
|
|
222
|
+
*/
|
|
223
|
+
readonly compute?: {
|
|
224
|
+
readonly unit: 'em' | 'vw' | 'vh' | 'vmin' | 'vmax';
|
|
225
|
+
readonly factor: number;
|
|
226
|
+
readonly offset?: number;
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* A structured value - a transform list, a shadow, a filter - with lengths like `compute`'s
|
|
230
|
+
* somewhere inside it, each marked `{ __defer: compute }`. Filled in where it is used.
|
|
231
|
+
*/
|
|
232
|
+
readonly within?: unknown;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* A colour a deferred value is made of: settled at build time, a token, or a `color-mix()` of two
|
|
236
|
+
* such, worked out once the tokens are known. What a gradient stop, a shadow's colour or a colour
|
|
237
|
+
* property with a `var()` in a mix becomes.
|
|
238
|
+
*/
|
|
239
|
+
export type ColourExpression = {
|
|
240
|
+
readonly color: string;
|
|
241
|
+
} | {
|
|
242
|
+
readonly reference: string;
|
|
243
|
+
readonly alternatives?: readonly string[];
|
|
244
|
+
readonly fallback?: string;
|
|
245
|
+
} | {
|
|
246
|
+
/** A token of bare channels, as `rgba(var(--channels), <alpha>)` reads it. */
|
|
247
|
+
readonly channels: {
|
|
248
|
+
readonly reference: string;
|
|
249
|
+
readonly fallback?: readonly number[];
|
|
250
|
+
};
|
|
251
|
+
readonly alpha?: number | {
|
|
252
|
+
readonly reference: string;
|
|
253
|
+
readonly fallback?: number;
|
|
254
|
+
};
|
|
255
|
+
} | {
|
|
256
|
+
readonly hsl: NonNullable<TokenValue['hsl']>;
|
|
257
|
+
} | {
|
|
258
|
+
/** `oklch(from <colour> <channel> <channel> <channel> [/ <alpha>])`. */
|
|
259
|
+
readonly relative: {
|
|
260
|
+
readonly space: MixSpace;
|
|
261
|
+
readonly from: ColourExpression;
|
|
262
|
+
readonly channels: readonly [Channel, Channel, Channel];
|
|
263
|
+
readonly alpha?: Channel;
|
|
264
|
+
};
|
|
265
|
+
} | {
|
|
266
|
+
readonly mix: {
|
|
267
|
+
readonly space: MixSpace;
|
|
268
|
+
readonly hue?: HueMethod;
|
|
269
|
+
readonly a: ColourExpression;
|
|
270
|
+
readonly aPercentage?: number;
|
|
271
|
+
readonly b: ColourExpression;
|
|
272
|
+
readonly bPercentage?: number;
|
|
273
|
+
};
|
|
274
|
+
};
|
|
275
|
+
/** One component's compiled styles, pre-sorted by specificity then source order. */
|
|
276
|
+
/**
|
|
277
|
+
* A gradient with holes in it: everything but the stop colours is settled at build time.
|
|
278
|
+
*
|
|
279
|
+
* The shape is React Native's own processed one, so filling it in is a copy with the references
|
|
280
|
+
* resolved rather than a translation.
|
|
281
|
+
*/
|
|
282
|
+
export interface GradientTemplate {
|
|
283
|
+
readonly type: 'linear-gradient' | 'radial-gradient';
|
|
284
|
+
readonly colorStops: readonly {
|
|
285
|
+
/** The custom property holding this stop's colour. A stop with no colour is not painted. */
|
|
286
|
+
readonly reference?: string;
|
|
287
|
+
/** A colour made from tokens and literals instead, such as a `color-mix()` of one. */
|
|
288
|
+
readonly colour?: ColourExpression;
|
|
289
|
+
readonly positionReference?: string;
|
|
290
|
+
readonly position?: string | number;
|
|
291
|
+
}[];
|
|
292
|
+
/**
|
|
293
|
+
* A radial gradient's centre, by the edges native measures from: each offset written, or a
|
|
294
|
+
* token with what is written beside its name to use when it is not set.
|
|
295
|
+
*/
|
|
296
|
+
readonly position?: Readonly<Record<string, string | number | {
|
|
297
|
+
readonly reference: string;
|
|
298
|
+
readonly fallback?: string | number;
|
|
299
|
+
}>>;
|
|
300
|
+
}
|
|
301
|
+
export interface StyleSheet {
|
|
302
|
+
readonly rules: readonly StyleRule[];
|
|
303
|
+
/**
|
|
304
|
+
* `@keyframes` by name. Global within a sheet, as they are within a document; the engine keeps
|
|
305
|
+
* one registry across every sheet it sees, so a name defined in a global stylesheet is usable
|
|
306
|
+
* from a component's.
|
|
307
|
+
*/
|
|
308
|
+
readonly keyframes?: Readonly<Record<string, readonly Keyframe[]>>;
|
|
309
|
+
/**
|
|
310
|
+
* Whether any rule here asks about a node's position among its siblings.
|
|
311
|
+
*
|
|
312
|
+
* Said on the sheet because what these cost is not matching but invalidation: adding a row
|
|
313
|
+
* changes what its neighbours match while nothing about those neighbours moved, so the engine
|
|
314
|
+
* has to re-resolve a whole child list when it changes. It only does that where a sheet asks.
|
|
315
|
+
*/
|
|
316
|
+
readonly structural?: true;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* What one node resolved to. `style` is what it renders with; `inherited` is what its children
|
|
320
|
+
* start from, which is the parent's own `inherited` plus whatever inheritable values this node
|
|
321
|
+
* set. Keeping the two apart is what lets resolution go downwards.
|
|
322
|
+
*/
|
|
323
|
+
export interface StyleCache {
|
|
324
|
+
epoch: number;
|
|
325
|
+
/**
|
|
326
|
+
* Identity token standing for "the ancestor chain, as far as matching is concerned". A node
|
|
327
|
+
* mints a fresh one whenever it recomputes, and reuses its previous one when it does not, so a
|
|
328
|
+
* descendant can tell whether anything above it moved with a single reference comparison.
|
|
329
|
+
*
|
|
330
|
+
* It has to cover more than the inherited values. `.wrap.dark .label` and
|
|
331
|
+
* `:host-context(.dark) .label` both change what a descendant matches when a class toggles on
|
|
332
|
+
* an ancestor, while nothing inherited changes at all, so watching the inherited map alone
|
|
333
|
+
* leaves those stale.
|
|
334
|
+
*/
|
|
335
|
+
context: object;
|
|
336
|
+
/** The parent's `context` this was computed from. */
|
|
337
|
+
parentContext: object;
|
|
338
|
+
/** The conditions version this was resolved under. */
|
|
339
|
+
generation: number;
|
|
340
|
+
style: Record<string, unknown>;
|
|
341
|
+
inherited: Record<string, unknown>;
|
|
342
|
+
/**
|
|
343
|
+
* Custom properties in scope for this node and its descendants. Cascades exactly as inherited
|
|
344
|
+
* values do, and by the same copy-on-write rule, so a subtree that defines none shares one map.
|
|
345
|
+
*/
|
|
346
|
+
tokens: Readonly<Record<string, TokenValue>>;
|
|
347
|
+
}
|
|
348
|
+
/** What the matcher needs of a node. The engine's node satisfies this structurally. */
|
|
349
|
+
export interface StyleTarget {
|
|
350
|
+
readonly name: string;
|
|
351
|
+
readonly parent: StyleTarget | null;
|
|
352
|
+
/**
|
|
353
|
+
* Needed only by the selectors that ask about a node's place among its siblings, which is why
|
|
354
|
+
* it is read through the parent rather than kept as an index: an index would have to be right
|
|
355
|
+
* after every insertion and removal, and this is right by construction.
|
|
356
|
+
*/
|
|
357
|
+
readonly children?: readonly StyleTarget[];
|
|
358
|
+
/**
|
|
359
|
+
* Only elements are counted by the selectors that ask about position. Text is not one, and
|
|
360
|
+
* neither is the anchor a structural directive leaves behind - the same reason a browser does
|
|
361
|
+
* not count a comment. Absent means element, so a hand-built target needs nothing extra.
|
|
362
|
+
*/
|
|
363
|
+
readonly kind?: string;
|
|
364
|
+
readonly classes: ReadonlySet<string> | null;
|
|
365
|
+
readonly props: Readonly<Record<string, unknown>>;
|
|
366
|
+
/**
|
|
367
|
+
* The sheet this node's own rules come from, which is the sheet of the component whose renderer
|
|
368
|
+
* created it. Read from the node rather than passed in, because a node's ancestors usually
|
|
369
|
+
* belong to other components and must be matched against their own sheets, not this one's.
|
|
370
|
+
*/
|
|
371
|
+
readonly sheet: StyleSheet | null;
|
|
372
|
+
/**
|
|
373
|
+
* The sheet of the component this node is the *host* of, if it is one. Distinct from `sheet`,
|
|
374
|
+
* which is the sheet of the component that *created* it: a host node is created by the parent,
|
|
375
|
+
* so those two are always different sheets and `:host` needs the second.
|
|
376
|
+
*/
|
|
377
|
+
hostSheet: StyleSheet | null;
|
|
378
|
+
/**
|
|
379
|
+
* Custom properties set on the node itself, `[style.--tint]` or `style="--tint: red"`, already
|
|
380
|
+
* converted (`inline-token.ts`). In scope for its own rules and its descendants', and stronger
|
|
381
|
+
* than any rule's, as inline style is on the web. Absent on a hand-built target.
|
|
382
|
+
*/
|
|
383
|
+
readonly customProperties?: Readonly<Record<string, TokenValue>> | null;
|
|
384
|
+
/** Memo slot, owned by the resolver. */
|
|
385
|
+
styleCache: StyleCache | null;
|
|
386
|
+
/** Set when something that could change what this node matches has changed. */
|
|
387
|
+
styleDirty: boolean;
|
|
388
|
+
/** `:focus`. Set by the engine from the native focus and blur events. */
|
|
389
|
+
focused?: boolean;
|
|
390
|
+
/**
|
|
391
|
+
* `:active`. Set by the engine on the responder and every one of its ancestors, because a press
|
|
392
|
+
* activates the whole chain on the web too, not only the deepest element under the finger.
|
|
393
|
+
*/
|
|
394
|
+
active?: boolean;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Deterministic work counters for the matcher.
|
|
398
|
+
*
|
|
399
|
+
* Wall-clock is noise; a compound comparison is not. Asserting on these catches an algorithmic
|
|
400
|
+
* regression (a walk that became quadratic, a cache that stopped hitting) in a way that a timing
|
|
401
|
+
* assertion never could without being flaky. `test/css-cost.test.ts` holds the baselines.
|
|
402
|
+
*
|
|
403
|
+
* The cost is one integer increment per comparison, against a Set lookup and several property
|
|
404
|
+
* reads, so it does not distort what it measures.
|
|
405
|
+
*/
|
|
406
|
+
export declare const styleStats: {
|
|
407
|
+
/** Calls to `matchesCompound`, the innermost unit of matching work. */
|
|
408
|
+
compoundTests: number;
|
|
409
|
+
/** Rules considered, i.e. calls to `matches`. */
|
|
410
|
+
ruleTests: number;
|
|
411
|
+
/** Nodes cascaded, as opposed to handed back from the memo. */
|
|
412
|
+
nodesResolved: number;
|
|
413
|
+
};
|
|
414
|
+
export declare function resetStyleStats(): void;
|
|
415
|
+
/**
|
|
416
|
+
* Right-to-left matching, as every CSS engine does it: the rightmost compound is the cheapest
|
|
417
|
+
* filter and rejects almost everything immediately.
|
|
418
|
+
*/
|
|
419
|
+
export declare function matches(node: StyleTarget, rule: StyleRule, sheet?: StyleSheet | null): boolean;
|
|
420
|
+
/** One rule in a cascade: the sheet it came from, which `:host` needs, and its weight here. */
|
|
421
|
+
interface RuleEntry {
|
|
422
|
+
readonly rule: StyleRule;
|
|
423
|
+
readonly sheet: StyleSheet;
|
|
424
|
+
readonly weight: number;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* The bucket a rule is filed under: the most selective simple selector in its rightmost compound,
|
|
428
|
+
* which is what a browser calls the key selector.
|
|
429
|
+
*
|
|
430
|
+
* Matching counts leftwards from that compound, so if it cannot match a node then nothing to its
|
|
431
|
+
* left needs looking at. Anything that could match a node whose name, id and classes say nothing -
|
|
432
|
+
* an attribute test, `:host`, `:is()`, a bare pseudo-class, `*` - goes in the universal bucket and
|
|
433
|
+
* is offered to everything, because the alternative is a rule that silently stops applying.
|
|
434
|
+
*/
|
|
435
|
+
export declare function ruleKey(rule: StyleRule): string;
|
|
436
|
+
/** Where a rule sits in the merged, weight-sorted list. The cascade depends on that order. */
|
|
437
|
+
interface IndexedEntry {
|
|
438
|
+
readonly entry: RuleEntry;
|
|
439
|
+
readonly at: number;
|
|
440
|
+
}
|
|
441
|
+
export interface RuleIndex {
|
|
442
|
+
readonly buckets: ReadonlyMap<string, readonly IndexedEntry[]>;
|
|
443
|
+
readonly universal: readonly IndexedEntry[];
|
|
444
|
+
}
|
|
445
|
+
/** File a merged, sorted rule list by key selector. Done once per sheet pair, not per node. */
|
|
446
|
+
export declare function indexRules(entries: readonly RuleEntry[]): RuleIndex;
|
|
447
|
+
/**
|
|
448
|
+
* The rules worth trying against a node, in the order they were merged in.
|
|
449
|
+
*
|
|
450
|
+
* Each bucket is already in order, so the collected list only needs sorting when more than one
|
|
451
|
+
* contributed - which for a node with one class and a name is the common case, and cheap: the
|
|
452
|
+
* lists are short by construction, which is the entire point of the index.
|
|
453
|
+
*/
|
|
454
|
+
export declare function candidateRules(node: StyleTarget, index: RuleIndex): RuleEntry[];
|
|
455
|
+
/**
|
|
456
|
+
* The runtime half of CSS for one engine: the global sheet, the conditions media queries are
|
|
457
|
+
* evaluated against, and the memo that makes resolution cost nodes x rules rather than
|
|
458
|
+
* nodes x rules x depth.
|
|
459
|
+
*
|
|
460
|
+
* One per engine rather than module state, so two surfaces in one process (or two engines in
|
|
461
|
+
* one test) cannot overwrite each other's sheet or viewport.
|
|
462
|
+
*
|
|
463
|
+
* Inherited state is pushed **down** rather than walked up: a node takes what its parent already
|
|
464
|
+
* resolved and overlays its own declarations. That is how real CSS engines do it, and it matters
|
|
465
|
+
* for two separate reasons.
|
|
466
|
+
*
|
|
467
|
+
* Correctness first. Walking up meant matching every ancestor against the *starting node's*
|
|
468
|
+
* sheet, but an ancestor almost always belongs to a different component, so a component's rules
|
|
469
|
+
* reached nodes it did not own while a parent's real values never arrived. Reading `sheet` off
|
|
470
|
+
* each node fixes both directions at once.
|
|
471
|
+
*
|
|
472
|
+
* Cost second. Walking up re-derived, for every node, everything its parent had already worked
|
|
473
|
+
* out. Memoising by epoch makes it nodes x rules, and a node that sets no inheritable value hands
|
|
474
|
+
* its parent's map straight on rather than copying it, so the common case allocates nothing.
|
|
475
|
+
*/
|
|
476
|
+
export declare class StyleResolver {
|
|
477
|
+
private conditions;
|
|
478
|
+
/**
|
|
479
|
+
* Bumped whenever the conditions move. Every cached result and every per-rule condition memo
|
|
480
|
+
* is stamped with it, so a rotation or a theme switch invalidates the lot in one assignment
|
|
481
|
+
* rather than walking the tree.
|
|
482
|
+
*/
|
|
483
|
+
private generation;
|
|
484
|
+
private emptyCache;
|
|
485
|
+
/**
|
|
486
|
+
* The rules a node is matched against, merged across the global sheet, the sheet of the
|
|
487
|
+
* component it hosts and the sheet that created it, sorted once by weight and then filed by key
|
|
488
|
+
* selector. Keyed by the creating sheet and then the hosted one, so a component's nodes share a
|
|
489
|
+
* single index.
|
|
490
|
+
*/
|
|
491
|
+
private readonly merged;
|
|
492
|
+
/**
|
|
493
|
+
* The application-level sheet, if any: the one set of rules allowed to match a node whatever
|
|
494
|
+
* component created it, which is what resets, utility classes and `:root` tokens all need.
|
|
495
|
+
*/
|
|
496
|
+
private readonly globalSheet;
|
|
497
|
+
/**
|
|
498
|
+
* Custom properties the host supplies rather than the stylesheet: the safe-area insets, and
|
|
499
|
+
* whatever else is a property of the device instead of the design.
|
|
500
|
+
*
|
|
501
|
+
* Seeded rather than forced. They stand in for the root's inherited tokens, so a `:root` rule
|
|
502
|
+
* in the app's own sheet overrides them the way it would override anything it inherited, and an
|
|
503
|
+
* app that wants to pin an inset for a tablet layout or a screenshot still can.
|
|
504
|
+
*/
|
|
505
|
+
private tokensOnRoot;
|
|
506
|
+
/** What the host has supplied so far, so a second source can add to it rather than replace it. */
|
|
507
|
+
get rootTokens(): Readonly<Record<string, TokenValue>>;
|
|
508
|
+
/**
|
|
509
|
+
* Told of a `var()` that names a custom property nothing in scope defines and has no fallback,
|
|
510
|
+
* which is dropped. Set only in development, where it is how the engine says so.
|
|
511
|
+
*/
|
|
512
|
+
onUndefinedToken: ((name: string, props: readonly string[]) => void) | null;
|
|
513
|
+
constructor(globalSheet: StyleSheet | null, conditions: Conditions);
|
|
514
|
+
setConditions(next: Conditions): void;
|
|
515
|
+
setRootTokens(next: Readonly<Record<string, TokenValue>>): void;
|
|
516
|
+
/**
|
|
517
|
+
* Resolve a node, memoised for the life of one epoch.
|
|
518
|
+
*
|
|
519
|
+
* `epoch` scopes the memo. The engine bumps it once per commit, so within a commit each node
|
|
520
|
+
* resolves at most once however many descendants ask for its inherited values.
|
|
521
|
+
*/
|
|
522
|
+
resolve(node: StyleTarget, epoch: number): StyleCache;
|
|
523
|
+
/**
|
|
524
|
+
* Whether a node's last answer still stands under a parent that resolved to `parentContext`,
|
|
525
|
+
* without resolving it. What lets a commit step over a clean child in one comparison.
|
|
526
|
+
*/
|
|
527
|
+
holds(node: StyleTarget, parentContext: object): boolean;
|
|
528
|
+
/**
|
|
529
|
+
* Whether a previous result still stands: nothing about the node changed, nothing above it
|
|
530
|
+
* moved, and the conditions have not.
|
|
531
|
+
*/
|
|
532
|
+
private reusable;
|
|
533
|
+
/**
|
|
534
|
+
* Nothing anywhere can match this node, and it sets no custom property of its own, so its style
|
|
535
|
+
* is whatever it inherits.
|
|
536
|
+
*/
|
|
537
|
+
private hasNoRules;
|
|
538
|
+
/**
|
|
539
|
+
* A node with no rules anywhere: it renders with what it inherits and passes the same map on.
|
|
540
|
+
*
|
|
541
|
+
* It still mints a context, because a rule further down may match on one of *its* classes.
|
|
542
|
+
* When there is nothing to inherit either, one shared cache object serves every such node, so
|
|
543
|
+
* an application that writes no CSS allocates nothing per node.
|
|
544
|
+
*/
|
|
545
|
+
private unstyled;
|
|
546
|
+
/**
|
|
547
|
+
* The rules worth trying against a node.
|
|
548
|
+
*
|
|
549
|
+
* The merged list is built once per (creating sheet, hosted sheet) pair and indexed by key
|
|
550
|
+
* selector; what comes back here is only the buckets this node can reach. For a component's own
|
|
551
|
+
* sheet that changes little, but a global utility sheet is hundreds of rules and a screen is a
|
|
552
|
+
* thousand nodes, and the difference is between a million match attempts and a few thousand.
|
|
553
|
+
*/
|
|
554
|
+
private rulesFor;
|
|
555
|
+
/**
|
|
556
|
+
* Weakest first. A host node is matched against two component sheets: the one belonging to the
|
|
557
|
+
* component it hosts, whose `:host` rules exist to reach exactly this node, and the one that
|
|
558
|
+
* created it. Both carry the bump; the creator comes later and so wins a tie, as the outer
|
|
559
|
+
* document does over `:host` on the web. The sort is stable, so within one sheet source order
|
|
560
|
+
* survives and a later sheet wins equal weight.
|
|
561
|
+
*/
|
|
562
|
+
private merge;
|
|
563
|
+
/** The declarations that apply to a node. The list is sorted, so later simply wins. */
|
|
564
|
+
private cascade;
|
|
565
|
+
/**
|
|
566
|
+
* Whether a rule's media query holds, memoised per rule.
|
|
567
|
+
*
|
|
568
|
+
* Conditions are the same for every node, so this is answered once per rule per change rather
|
|
569
|
+
* than once per rule per node.
|
|
570
|
+
*/
|
|
571
|
+
private conditionHolds;
|
|
572
|
+
private evaluate;
|
|
573
|
+
/** What the device answers for a feature that is a keyword rather than a measurement. */
|
|
574
|
+
private preference;
|
|
575
|
+
/** A length relative to the viewport, in points. */
|
|
576
|
+
private viewportLength;
|
|
577
|
+
/**
|
|
578
|
+
* Write the declarations that could not be settled at build time: a `var()` reference, or a
|
|
579
|
+
* length relative to the viewport or to the font size in scope.
|
|
580
|
+
*
|
|
581
|
+
* A declaration with no token and no usable fallback is dropped rather than written as
|
|
582
|
+
* undefined, which is what a browser does with a value it cannot resolve.
|
|
583
|
+
*/
|
|
584
|
+
private applyDeferred;
|
|
585
|
+
/** One deferred declaration's value, from the tokens in scope and the node's own style. */
|
|
586
|
+
private settled;
|
|
587
|
+
/** A reference with nothing defined for it and nothing to fall back to. */
|
|
588
|
+
private reportUndefined;
|
|
589
|
+
/**
|
|
590
|
+
* A structured value with every deferred length and colour inside it settled, or undefined when
|
|
591
|
+
* a colour in it cannot be: a shadow with no colour is not a shadow, as CSS reads it.
|
|
592
|
+
*/
|
|
593
|
+
private settledWithin;
|
|
594
|
+
/** A structured value with every deferred length and colour inside it settled. */
|
|
595
|
+
private filledIn;
|
|
596
|
+
/**
|
|
597
|
+
* A list's parts filled in, a whole shadow or filter token standing for however many entries it
|
|
598
|
+
* holds: none, for an empty filter slot.
|
|
599
|
+
*/
|
|
600
|
+
private filledList;
|
|
601
|
+
/** A length relative to the viewport or to the font size in scope. */
|
|
602
|
+
private computed;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Where a component's compiled sheet lives: a static on the component class, written by the
|
|
606
|
+
* Metro transformer at build time.
|
|
607
|
+
*
|
|
608
|
+
* `RendererFactory2.createRenderer(host, type)` receives the component definition, and a
|
|
609
|
+
* definition references its class, so a renderer can find its own sheet with no registry and no
|
|
610
|
+
* generated id. That is also how encapsulation is scoped for free: a component's renderer only
|
|
611
|
+
* ever matches that component's rules, so its elements cannot be styled by anyone else's CSS.
|
|
612
|
+
*/
|
|
613
|
+
export declare const NATIVE_STYLES = "\u0275nativeStyles";
|
|
614
|
+
export declare function styleSheetOf(type: unknown): StyleSheet | null;
|
|
615
|
+
export {};
|