@ng-native/fabric 0.17.1 → 0.18.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/dist/css.d.ts +49 -2
- package/dist/css.js +206 -19
- package/dist/css.js.map +1 -1
- package/dist/engine.d.ts +283 -11
- package/dist/engine.js +1068 -56
- package/dist/engine.js.map +1 -1
- package/dist/host.d.ts +8 -0
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/inline-derived-token.js +18 -5
- package/dist/inline-derived-token.js.map +1 -1
- package/dist/inline-token.d.ts +10 -4
- package/dist/inline-token.js +48 -5
- package/dist/inline-token.js.map +1 -1
- package/dist/native-paint.d.ts +66 -0
- package/dist/native-paint.js +246 -0
- package/dist/native-paint.js.map +1 -0
- package/dist/scroll-animation.d.ts +5 -0
- package/dist/scroll-animation.js +1 -1
- package/dist/scroll-animation.js.map +1 -1
- package/dist/transition.d.ts +5 -0
- package/dist/transition.js.map +1 -1
- package/package.json +1 -1
package/dist/css.d.ts
CHANGED
|
@@ -186,13 +186,28 @@ export interface Conditions {
|
|
|
186
186
|
/** A run of CSS whitespace: spaces, tabs, newlines, carriage returns and form feeds, and no other. */
|
|
187
187
|
export declare const CSS_SPACE: RegExp;
|
|
188
188
|
/** A custom property's value, in each form it can legally take. Absent forms are unusable. */
|
|
189
|
+
/**
|
|
190
|
+
* A colour only the platform resolves, `platform-color(link)` or a system colour, held by its
|
|
191
|
+
* names, which the engine turns into the shape each platform reads (`Engine.color`). It has no
|
|
192
|
+
* channels here, so nothing can mix, fade or shade it, or draw it in a gradient or a shadow.
|
|
193
|
+
*/
|
|
194
|
+
export interface PlatformColour {
|
|
195
|
+
readonly platformColor: readonly string[];
|
|
196
|
+
}
|
|
197
|
+
export declare const isPlatformColour: (value: unknown) => value is PlatformColour;
|
|
189
198
|
export interface TokenValue {
|
|
190
199
|
readonly length?: number | string;
|
|
191
200
|
/** An angle, in degrees whatever unit it was written in. */
|
|
192
201
|
readonly angle?: number;
|
|
193
202
|
/** A time, in milliseconds whatever unit it was written in. */
|
|
194
203
|
readonly time?: number;
|
|
195
|
-
|
|
204
|
+
/** A colour, or one only the platform resolves, by name: `platform-color(link)`, `LinkText`. */
|
|
205
|
+
readonly color?: string | PlatformColour;
|
|
206
|
+
/**
|
|
207
|
+
* The token holding a platform colour that one made of others, `color-mix(in srgb, var(--x)
|
|
208
|
+
* 50%, white)`, was worked out of, which leaves it with no value: what a warning names.
|
|
209
|
+
*/
|
|
210
|
+
readonly platformColourIn?: string;
|
|
196
211
|
readonly keyword?: string;
|
|
197
212
|
readonly number?: number;
|
|
198
213
|
/** A font weight, as the string `fontWeight` takes. */
|
|
@@ -329,6 +344,11 @@ export interface DeferredDeclaration {
|
|
|
329
344
|
* gradient is not the class that supplies its colours.
|
|
330
345
|
*/
|
|
331
346
|
readonly gradient?: GradientTemplate | readonly GradientTemplate[];
|
|
347
|
+
/**
|
|
348
|
+
* A band of the box from side to side whose edges are tokens, `clipBand` as a library's sheet
|
|
349
|
+
* writes it for a slider: each edge a percentage, or a token with the percentage beside it.
|
|
350
|
+
*/
|
|
351
|
+
readonly band?: readonly BandEdge[];
|
|
332
352
|
/**
|
|
333
353
|
* Arithmetic around the reference, settled at build time. `value * scale + offset`, then no
|
|
334
354
|
* smaller than `floor`. What `calc(var(--x) + 12px)` and `max(var(--x), 16px)` become.
|
|
@@ -690,6 +710,14 @@ export interface StyleTarget {
|
|
|
690
710
|
}
|
|
691
711
|
/** Whether a prop of a shape in a drawing is a paint it hands down: see `inheritFrom`. */
|
|
692
712
|
export declare const handsDownPaint: (key: string) => boolean;
|
|
713
|
+
/**
|
|
714
|
+
* A border's unsided width and colour, written beside the four sides once the cascade and every
|
|
715
|
+
* token have settled them, where they agree. Android strokes a rounded border, the only way it
|
|
716
|
+
* draws one dashed or dotted, from `borderWidth` and `borderColor` alone, and only when every
|
|
717
|
+
* side equals them; given the sides alone it fills each in solid. A border with no width strokes
|
|
718
|
+
* nothing, so preflight's `border: 0 solid` adds nothing to every element.
|
|
719
|
+
*/
|
|
720
|
+
export declare function settleUnsidedBorder(own: Record<string, unknown>): void;
|
|
693
721
|
/**
|
|
694
722
|
* Deterministic work counters for the matcher.
|
|
695
723
|
*
|
|
@@ -1030,6 +1058,13 @@ export declare class StyleResolver {
|
|
|
1030
1058
|
* compiler refuses the same value written out, but a token is only known here.
|
|
1031
1059
|
*/
|
|
1032
1060
|
onUnreadDisplay: ((name: string, value: string | undefined) => void) | null;
|
|
1061
|
+
/**
|
|
1062
|
+
* Told of a declaration dropped for working a colour out of a token that holds a platform
|
|
1063
|
+
* colour, which has no channels: a `color-mix()`, a relative colour, a gradient or a shadow.
|
|
1064
|
+
* Set only in development: the compiler says so of a sheet that holds both, but only here is it
|
|
1065
|
+
* known for a token one sheet sets and another reads.
|
|
1066
|
+
*/
|
|
1067
|
+
onPlatformColour: ((name: string, props: readonly string[], on?: string) => void) | null;
|
|
1033
1068
|
constructor(globalSheet: StyleSheet | null, conditions: Conditions);
|
|
1034
1069
|
/**
|
|
1035
1070
|
* Match `sheet` against every node from now on, as a global sheet, after the application's;
|
|
@@ -1317,8 +1352,12 @@ export declare class StyleResolver {
|
|
|
1317
1352
|
private settled;
|
|
1318
1353
|
/** A line's longhands from its tokens, with a width in `em` worked out against the font size. */
|
|
1319
1354
|
private settledLine;
|
|
1355
|
+
/** Why a declaration came to nothing, where something is told: in development. */
|
|
1356
|
+
private reportUnsettled;
|
|
1320
1357
|
/** A reference with nothing defined for it and nothing to fall back to. */
|
|
1321
1358
|
private reportUndefined;
|
|
1359
|
+
/** A colour worked out of a token holding a platform colour, which cannot be. */
|
|
1360
|
+
private reportPlatformColour;
|
|
1322
1361
|
/** A display token set to a value native has no display for. */
|
|
1323
1362
|
private reportDisplay;
|
|
1324
1363
|
/**
|
|
@@ -1326,7 +1365,10 @@ export declare class StyleResolver {
|
|
|
1326
1365
|
* a colour in it cannot be: a shadow with no colour is not a shadow, as CSS reads it.
|
|
1327
1366
|
*/
|
|
1328
1367
|
private settledWithin;
|
|
1329
|
-
/**
|
|
1368
|
+
/**
|
|
1369
|
+
* A structured value with every deferred length and colour inside it settled. A platform colour
|
|
1370
|
+
* is settled only as the `whole` value: inside a shadow or a filter native draws from channels.
|
|
1371
|
+
*/
|
|
1330
1372
|
private filledIn;
|
|
1331
1373
|
/**
|
|
1332
1374
|
* A list's parts filled in, a whole shadow or filter token standing for however many entries it
|
|
@@ -1361,6 +1403,11 @@ export declare const isNegativeLineHeight: (prop: string, text: string) => boole
|
|
|
1361
1403
|
export declare function boundRelativeLength(prop: string, text: string, on?: string): DeferredDeclaration | null;
|
|
1362
1404
|
/** `hsl()` reads a channels token as hue, saturation and lightness; `rgb()` as sRGB. */
|
|
1363
1405
|
type ChannelSpace = 'rgb' | 'hsl';
|
|
1406
|
+
/** An edge of a band: a percentage, or a token with the percentage beside it where one is. */
|
|
1407
|
+
type BandEdge = string | {
|
|
1408
|
+
readonly reference: string;
|
|
1409
|
+
readonly fallback?: string;
|
|
1410
|
+
};
|
|
1364
1411
|
/**
|
|
1365
1412
|
* Arithmetic with tokens in it, as the compiler leaves it: numbers, token references and
|
|
1366
1413
|
* `[op, a, b]`, in points, degrees or plain numbers as the slot it fills counts. A percentage
|
package/dist/css.js
CHANGED
|
@@ -11,6 +11,9 @@ import { ELEMENT_STYLES } from "./element-styles.js";
|
|
|
11
11
|
import { relativeColour } from "./relative-colour.js";
|
|
12
12
|
/** A run of CSS whitespace: spaces, tabs, newlines, carriage returns and form feeds, and no other. */
|
|
13
13
|
export const CSS_SPACE = /[ \t\n\r\f]+/;
|
|
14
|
+
export const isPlatformColour = (value) => typeof value === 'object' &&
|
|
15
|
+
value !== null &&
|
|
16
|
+
Array.isArray(value.platformColor);
|
|
14
17
|
/**
|
|
15
18
|
* Where a form a token does not have can be read from instead. A length is already a
|
|
16
19
|
* line-height and a single word is already a family, so neither is stored twice in every token
|
|
@@ -70,6 +73,9 @@ const INHERITED = new Set([
|
|
|
70
73
|
'textShadowOffset',
|
|
71
74
|
'textShadowRadius',
|
|
72
75
|
'textShadowColor',
|
|
76
|
+
// `text-wrap` and `word-break`, which CSS inherits, as the paragraph props they are.
|
|
77
|
+
'lineBreakStrategyIOS',
|
|
78
|
+
'textBreakStrategy',
|
|
73
79
|
'selectable',
|
|
74
80
|
// CSS inherits it, and its `none` is the element alone: a descendant's `auto` takes touches
|
|
75
81
|
// again. The engine commits a computed `none` as native's `box-none`, which means that.
|
|
@@ -82,10 +88,48 @@ const INHERITED = new Set([
|
|
|
82
88
|
const INHERITED_POINTER_EVENTS = new Set(['none', 'auto']);
|
|
83
89
|
/**
|
|
84
90
|
* A shape's paint, which SVG hands down: a path under an `<svg>` with a `fill` has that fill.
|
|
85
|
-
*
|
|
86
|
-
*
|
|
91
|
+
* Handed down through any element, as a browser does, `.btn { fill: currentColor }` to the
|
|
92
|
+
* icon in the button, and taken only by a library's drawing (`StyleTarget.namespace`). An icon's
|
|
93
|
+
* shapes are left to react-native-svg, which hands a group's paint down itself, from what the
|
|
94
|
+
* shape set as its own.
|
|
95
|
+
*
|
|
96
|
+
* ponytail: an inline style's paint is handed down by a drawing's node alone (`setsInherited`).
|
|
97
|
+
* Hand it down from any node as a rule's is if `[style.fill]` on a box around a drawing is seen.
|
|
87
98
|
*/
|
|
88
99
|
const SHAPE_PAINT_INHERITED = new Set(['fill', 'stroke', 'strokeWidth']);
|
|
100
|
+
/**
|
|
101
|
+
* Whether a node takes the shape's paint it is handed: a node of a library's drawing, or one a
|
|
102
|
+
* package makes in it, as web-compat makes the span a text's words are drawn by.
|
|
103
|
+
*/
|
|
104
|
+
const takesPaint = (node) => node.namespace !== undefined || node.parent?.namespace !== undefined;
|
|
105
|
+
/** Whether a node is handed a shape's paint: see `SHAPE_PAINT_INHERITED`. */
|
|
106
|
+
const handedPaint = (inherited) => inherited['fill'] !== undefined ||
|
|
107
|
+
inherited['stroke'] !== undefined ||
|
|
108
|
+
inherited['strokeWidth'] !== undefined;
|
|
109
|
+
/** The styles of nodes outside a drawing with no rules, by the map they inherit: see `unpainted`. */
|
|
110
|
+
const unpaintedStyles = new WeakMap();
|
|
111
|
+
/**
|
|
112
|
+
* A style without the shape's paint it was handed, for a node outside a drawing: it hands the
|
|
113
|
+
* paint on and takes none, as an icon's shape commits only the paint it was given itself.
|
|
114
|
+
*/
|
|
115
|
+
function unpainted(style, own) {
|
|
116
|
+
if (!handedPaint(style))
|
|
117
|
+
return style;
|
|
118
|
+
if (own) {
|
|
119
|
+
for (const key of SHAPE_PAINT_INHERITED)
|
|
120
|
+
if (!(key in own))
|
|
121
|
+
delete style[key];
|
|
122
|
+
return style;
|
|
123
|
+
}
|
|
124
|
+
let bare = unpaintedStyles.get(style);
|
|
125
|
+
if (!bare) {
|
|
126
|
+
bare = { ...style };
|
|
127
|
+
for (const key of SHAPE_PAINT_INHERITED)
|
|
128
|
+
delete bare[key];
|
|
129
|
+
unpaintedStyles.set(style, bare);
|
|
130
|
+
}
|
|
131
|
+
return bare;
|
|
132
|
+
}
|
|
89
133
|
/** Whether a prop of a shape in a drawing is a paint it hands down: see `inheritFrom`. */
|
|
90
134
|
export const handsDownPaint = (key) => key === 'propList' || SHAPE_PAINT_INHERITED.has(key);
|
|
91
135
|
/**
|
|
@@ -126,6 +170,47 @@ function settleBorders(own) {
|
|
|
126
170
|
else
|
|
127
171
|
own['borderStyle'] = drawn;
|
|
128
172
|
}
|
|
173
|
+
/** A border's four sides and its logical ones, by the part of it they hold. */
|
|
174
|
+
const BORDER_SIDES = Object.fromEntries(['Width', 'Color'].map((part) => [
|
|
175
|
+
part,
|
|
176
|
+
{
|
|
177
|
+
physical: ['Top', 'Right', 'Bottom', 'Left'].map((side) => `border${side}${part}`),
|
|
178
|
+
logical: ['Start', 'End', 'Block', 'BlockStart', 'BlockEnd'].map((side) => `border${side}${part}`),
|
|
179
|
+
},
|
|
180
|
+
]));
|
|
181
|
+
/**
|
|
182
|
+
* A border's unsided width and colour, written beside the four sides once the cascade and every
|
|
183
|
+
* token have settled them, where they agree. Android strokes a rounded border, the only way it
|
|
184
|
+
* draws one dashed or dotted, from `borderWidth` and `borderColor` alone, and only when every
|
|
185
|
+
* side equals them; given the sides alone it fills each in solid. A border with no width strokes
|
|
186
|
+
* nothing, so preflight's `border: 0 solid` adds nothing to every element.
|
|
187
|
+
*/
|
|
188
|
+
export function settleUnsidedBorder(own) {
|
|
189
|
+
// No top width, its own or unsided: no four sides that agree. Most views have no border.
|
|
190
|
+
if (own['borderTopWidth'] === undefined && own['borderWidth'] === undefined)
|
|
191
|
+
return;
|
|
192
|
+
const width = agreedSides(own, 'Width');
|
|
193
|
+
if (width === undefined || width === 0)
|
|
194
|
+
return;
|
|
195
|
+
own['borderWidth'] = width;
|
|
196
|
+
const colour = agreedSides(own, 'Color');
|
|
197
|
+
if (colour !== undefined)
|
|
198
|
+
own['borderColor'] = colour;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* What the four sides of a border are, each read as native reads it, where they are the same,
|
|
202
|
+
* a colour held in an object by what is in it. A logical side, which a direction makes left or
|
|
203
|
+
* right, leaves it unsaid.
|
|
204
|
+
*/
|
|
205
|
+
function agreedSides(own, part) {
|
|
206
|
+
const { physical, logical } = BORDER_SIDES[part];
|
|
207
|
+
if (logical.some((key) => own[key] !== undefined))
|
|
208
|
+
return undefined;
|
|
209
|
+
const unsided = own[`border${part}`];
|
|
210
|
+
const [first, ...rest] = physical.map((key) => own[key] ?? unsided);
|
|
211
|
+
const same = (one) => one === first || JSON.stringify(one) === JSON.stringify(first);
|
|
212
|
+
return rest.every(same) ? first : undefined;
|
|
213
|
+
}
|
|
129
214
|
/**
|
|
130
215
|
* Deterministic work counters for the matcher.
|
|
131
216
|
*
|
|
@@ -2226,7 +2311,7 @@ function inheritFrom(parentInherited, own, node) {
|
|
|
2226
2311
|
const drawing = node?.namespace !== undefined;
|
|
2227
2312
|
let inherited = drawing ? ownPaint(node, parentInherited, own) : parentInherited;
|
|
2228
2313
|
for (const key of Object.keys(own)) {
|
|
2229
|
-
if (!(INHERITED.has(key) ||
|
|
2314
|
+
if (!(INHERITED.has(key) || SHAPE_PAINT_INHERITED.has(key)))
|
|
2230
2315
|
continue;
|
|
2231
2316
|
// `pointer-events: inherit`, which only an inline style on an element no rule matches still
|
|
2232
2317
|
// holds here: what the parent hands down stands.
|
|
@@ -2430,6 +2515,13 @@ export class StyleResolver {
|
|
|
2430
2515
|
* compiler refuses the same value written out, but a token is only known here.
|
|
2431
2516
|
*/
|
|
2432
2517
|
onUnreadDisplay = null;
|
|
2518
|
+
/**
|
|
2519
|
+
* Told of a declaration dropped for working a colour out of a token that holds a platform
|
|
2520
|
+
* colour, which has no channels: a `color-mix()`, a relative colour, a gradient or a shadow.
|
|
2521
|
+
* Set only in development: the compiler says so of a sheet that holds both, but only here is it
|
|
2522
|
+
* known for a token one sheet sets and another reads.
|
|
2523
|
+
*/
|
|
2524
|
+
onPlatformColour = null;
|
|
2433
2525
|
constructor(globalSheet, conditions) {
|
|
2434
2526
|
this.globalSheet = globalSheet;
|
|
2435
2527
|
this.conditions = conditions;
|
|
@@ -2884,7 +2976,9 @@ export class StyleResolver {
|
|
|
2884
2976
|
parentContext,
|
|
2885
2977
|
scope: scope ?? context,
|
|
2886
2978
|
parentScope,
|
|
2887
|
-
style:
|
|
2979
|
+
style: takesPaint(node)
|
|
2980
|
+
? unstyledStyle(parentInherited, inline)
|
|
2981
|
+
: unpainted(unstyledStyle(parentInherited, inline), null),
|
|
2888
2982
|
inherited: handedOn(node, parentInherited, inline, drawing),
|
|
2889
2983
|
tokens,
|
|
2890
2984
|
};
|
|
@@ -3054,11 +3148,11 @@ export class StyleResolver {
|
|
|
3054
3148
|
const drawing = node.namespace !== undefined;
|
|
3055
3149
|
const inline = node.inlineInherits ? inlineInherited(node.props['style'], drawing) : null;
|
|
3056
3150
|
// Nor one that takes a value from its parent's own style, which two parents differ in, nor
|
|
3057
|
-
//
|
|
3151
|
+
// one that takes a drawing's paint, which another node with its rules does not.
|
|
3058
3152
|
if (node.customProperties ||
|
|
3059
3153
|
inline ||
|
|
3060
3154
|
node.boundStyle ||
|
|
3061
|
-
|
|
3155
|
+
takesPaint(node) ||
|
|
3062
3156
|
matched.some(takesParents)) {
|
|
3063
3157
|
return this.style(node, matched, parentTokens, parentInherited, inline);
|
|
3064
3158
|
}
|
|
@@ -3108,10 +3202,13 @@ export class StyleResolver {
|
|
|
3108
3202
|
this.applyDeferred(result.deferred, own, tokens, parentInherited, result.important);
|
|
3109
3203
|
}
|
|
3110
3204
|
settleBorders(own);
|
|
3205
|
+
settleUnsidedBorder(own);
|
|
3111
3206
|
// `pointer-events: inherit` won the cascade: what the parent hands down stands.
|
|
3112
3207
|
if (own['pointerEvents'] === 'inherit')
|
|
3113
3208
|
delete own['pointerEvents'];
|
|
3114
3209
|
const style = { ...parentInherited, ...own };
|
|
3210
|
+
if (!takesPaint(node))
|
|
3211
|
+
unpainted(style, own);
|
|
3115
3212
|
settleLineHeight(style);
|
|
3116
3213
|
const inherited = decorate(style, inheritFrom(parentInherited, own, node), own);
|
|
3117
3214
|
const rtl = (style['direction'] ?? this.conditions.direction) === 'rtl';
|
|
@@ -3286,9 +3383,8 @@ export class StyleResolver {
|
|
|
3286
3383
|
continue;
|
|
3287
3384
|
}
|
|
3288
3385
|
const settled = this.settled(declaration, own, parentInherited, tokens);
|
|
3289
|
-
if (settled === undefined
|
|
3290
|
-
this.
|
|
3291
|
-
}
|
|
3386
|
+
if (settled === undefined)
|
|
3387
|
+
this.reportUnsettled(declaration, tokens);
|
|
3292
3388
|
const outranked = (prop) => !declaration.important && important !== null && prop in important;
|
|
3293
3389
|
// Said only of a display that is written: an important one wins over the token's.
|
|
3294
3390
|
const unread = settled === undefined && declaration.kind === 'display';
|
|
@@ -3390,6 +3486,13 @@ export class StyleResolver {
|
|
|
3390
3486
|
values[prop] = Math.max(points, 0);
|
|
3391
3487
|
return values;
|
|
3392
3488
|
}
|
|
3489
|
+
/** Why a declaration came to nothing, where something is told: in development. */
|
|
3490
|
+
reportUnsettled(declaration, tokens) {
|
|
3491
|
+
if (this.onUndefinedToken)
|
|
3492
|
+
this.reportUndefined(declaration, tokens);
|
|
3493
|
+
if (this.onPlatformColour)
|
|
3494
|
+
this.reportPlatformColour(declaration, tokens);
|
|
3495
|
+
}
|
|
3393
3496
|
/** A reference with nothing defined for it and nothing to fall back to. */
|
|
3394
3497
|
reportUndefined(declaration, tokens) {
|
|
3395
3498
|
const name = declaration.reference;
|
|
@@ -3401,6 +3504,14 @@ export class StyleResolver {
|
|
|
3401
3504
|
return;
|
|
3402
3505
|
this.onUndefinedToken(name, declaration.props, declaration.on);
|
|
3403
3506
|
}
|
|
3507
|
+
/** A colour worked out of a token holding a platform colour, which cannot be. */
|
|
3508
|
+
reportPlatformColour(declaration, tokens) {
|
|
3509
|
+
if (declaration.kind !== undefined && !COLOURED_KINDS.has(declaration.kind))
|
|
3510
|
+
return;
|
|
3511
|
+
const name = platformColourRead(declaration, tokens, new Set());
|
|
3512
|
+
if (name)
|
|
3513
|
+
this.onPlatformColour(name, declaration.props, declaration.on);
|
|
3514
|
+
}
|
|
3404
3515
|
/** A display token set to a value native has no display for. */
|
|
3405
3516
|
reportDisplay(declaration, tokens) {
|
|
3406
3517
|
const names = [declaration.reference, ...(declaration.alternatives ?? [])];
|
|
@@ -3413,7 +3524,7 @@ export class StyleResolver {
|
|
|
3413
3524
|
* a colour in it cannot be: a shadow with no colour is not a shadow, as CSS reads it.
|
|
3414
3525
|
*/
|
|
3415
3526
|
settledWithin(value, declaration, own, parentInherited, tokens) {
|
|
3416
|
-
const filled = this.filledIn(value, declaration, own, parentInherited, tokens);
|
|
3527
|
+
const filled = this.filledIn(value, declaration, own, parentInherited, tokens, true);
|
|
3417
3528
|
if (filled === UNSETTLED)
|
|
3418
3529
|
return undefined;
|
|
3419
3530
|
// As the compiler drops a shadow nobody can see: Tailwind composes five, four of them nothing.
|
|
@@ -3421,8 +3532,11 @@ export class StyleResolver {
|
|
|
3421
3532
|
? filled.filter((shadow) => !invisible(shadow.color))
|
|
3422
3533
|
: filled;
|
|
3423
3534
|
}
|
|
3424
|
-
/**
|
|
3425
|
-
|
|
3535
|
+
/**
|
|
3536
|
+
* A structured value with every deferred length and colour inside it settled. A platform colour
|
|
3537
|
+
* is settled only as the `whole` value: inside a shadow or a filter native draws from channels.
|
|
3538
|
+
*/
|
|
3539
|
+
filledIn(value, declaration, own, parentInherited, tokens, whole = false) {
|
|
3426
3540
|
if (!needsFilling(value))
|
|
3427
3541
|
return value;
|
|
3428
3542
|
const fill = (part) => this.filledIn(part, declaration, own, parentInherited, tokens);
|
|
@@ -3435,10 +3549,11 @@ export class StyleResolver {
|
|
|
3435
3549
|
return (ownColour ?? parentInherited['color'] ?? 'black');
|
|
3436
3550
|
};
|
|
3437
3551
|
const marked = settledMarker(value, tokens, current);
|
|
3438
|
-
|
|
3439
|
-
|
|
3552
|
+
const settled = marked === 'currentcolor' ? current() : marked;
|
|
3553
|
+
if (isPlatformColour(settled) && !whole)
|
|
3554
|
+
return UNSETTLED;
|
|
3440
3555
|
if (marked !== NOT_A_MARKER)
|
|
3441
|
-
return
|
|
3556
|
+
return settled ?? UNSETTLED;
|
|
3442
3557
|
const pending = value.__defer;
|
|
3443
3558
|
if (pending)
|
|
3444
3559
|
return this.computed({ ...declaration, compute: pending }, own, parentInherited);
|
|
@@ -3649,7 +3764,14 @@ const INVALID = Object.freeze({});
|
|
|
3649
3764
|
* percentage hue does, and unset only when a `var()` in it has nothing to be substituted with.
|
|
3650
3765
|
*/
|
|
3651
3766
|
function workedOut(token, tokens) {
|
|
3652
|
-
|
|
3767
|
+
const value = derived(token, tokens);
|
|
3768
|
+
if (value)
|
|
3769
|
+
return value;
|
|
3770
|
+
if (!substitutable(token, tokens))
|
|
3771
|
+
return undefined;
|
|
3772
|
+
// Made of a platform colour, which has no channels: invalid, and kept to say why.
|
|
3773
|
+
const from = platformColourRead(token, tokens, new Set());
|
|
3774
|
+
return from ? { platformColourIn: from } : INVALID;
|
|
3653
3775
|
}
|
|
3654
3776
|
/** Whether each `var()` in a token made of others names a token that is set, or has a fallback. */
|
|
3655
3777
|
function substitutable(token, tokens) {
|
|
@@ -3932,6 +4054,8 @@ function substituted(value, tokens, path, depth) {
|
|
|
3932
4054
|
function referenced(declaration, tokens) {
|
|
3933
4055
|
if (declaration.gradient)
|
|
3934
4056
|
return paintLayers(declaration.gradient, tokens);
|
|
4057
|
+
if (declaration.band)
|
|
4058
|
+
return settledBand(declaration.band, tokens);
|
|
3935
4059
|
// The first token set is substituted, whatever it holds: one of the wrong kind leaves the
|
|
3936
4060
|
// property unset rather than trying the next, or the fallback.
|
|
3937
4061
|
const names = [declaration.reference, ...(declaration.alternatives ?? [])];
|
|
@@ -4325,6 +4449,23 @@ function fromChannels(value, alpha, tokens, space) {
|
|
|
4325
4449
|
? `rgb(${r}, ${g}, ${b})`
|
|
4326
4450
|
: `rgba(${r}, ${g}, ${b}, ${Math.round(opacity * 1000) / 1000})`;
|
|
4327
4451
|
}
|
|
4452
|
+
/**
|
|
4453
|
+
* A band's clip with its edges settled, as `clipBand` is written: none where an edge is a token
|
|
4454
|
+
* that is no percentage of the box, or unset with nothing beside it, as CSS then has no clip.
|
|
4455
|
+
*/
|
|
4456
|
+
function settledBand(band, tokens) {
|
|
4457
|
+
const [from, to] = band.map((edge) => percentOf(typeof edge === 'string' ? edge : substitute(edge, tokens, (token) => token.length)));
|
|
4458
|
+
if (from === undefined || to === undefined)
|
|
4459
|
+
return undefined;
|
|
4460
|
+
return `polygon(${from}% 0%, ${to}% 0%, ${to}% 100%, ${from}% 100%)`;
|
|
4461
|
+
}
|
|
4462
|
+
/** A length as a percentage, 0 and one below it included, or undefined for any other. */
|
|
4463
|
+
function percentOf(length) {
|
|
4464
|
+
if (length === 0)
|
|
4465
|
+
return '0';
|
|
4466
|
+
const share = typeof length === 'string' ? /^(-?\d*\.?\d+)%$/.exec(length) : null;
|
|
4467
|
+
return share ? String(Number(share[1])) : undefined;
|
|
4468
|
+
}
|
|
4328
4469
|
/** One template, or a layered background of several: every layer painted, or, as CSS would, none. */
|
|
4329
4470
|
function paintLayers(gradient, tokens) {
|
|
4330
4471
|
if (!Array.isArray(gradient))
|
|
@@ -4364,6 +4505,9 @@ function paintedStops(template, tokens) {
|
|
|
4364
4505
|
for (const stop of template.colorStops) {
|
|
4365
4506
|
const token = stop.colour ? undefined : tokens[stop.reference];
|
|
4366
4507
|
const color = stop.colour ? resolveColour(stop.colour, tokens) : token?.color;
|
|
4508
|
+
// A platform colour is no stop: a gradient is drawn from channels, which it has none of.
|
|
4509
|
+
if (isPlatformColour(color))
|
|
4510
|
+
return undefined;
|
|
4367
4511
|
// `none` is how the Tailwind flattening writes `via-none`: the stop left out, not invalid.
|
|
4368
4512
|
if (color === undefined && token && token.keyword !== 'none')
|
|
4369
4513
|
return undefined;
|
|
@@ -4433,6 +4577,14 @@ function resolveColour(expression, tokens, current) {
|
|
|
4433
4577
|
}
|
|
4434
4578
|
/** A colour inside another: `currentColor` there, written or in a token, is the node's colour. */
|
|
4435
4579
|
function innerColour(expression, tokens, current) {
|
|
4580
|
+
return withChannels(colourWithin(expression, tokens, current));
|
|
4581
|
+
}
|
|
4582
|
+
/**
|
|
4583
|
+
* A colour something works another out of, which a platform colour cannot be: it has no channels.
|
|
4584
|
+
* Undefined for one, so what it was in is not settled either, as for a token that is not set.
|
|
4585
|
+
*/
|
|
4586
|
+
const withChannels = (colour) => isPlatformColour(colour) ? undefined : colour;
|
|
4587
|
+
function colourWithin(expression, tokens, current) {
|
|
4436
4588
|
if (!current)
|
|
4437
4589
|
return resolveColour(expression, tokens);
|
|
4438
4590
|
if ('reference' in expression) {
|
|
@@ -4441,7 +4593,7 @@ function innerColour(expression, tokens, current) {
|
|
|
4441
4593
|
return current();
|
|
4442
4594
|
}
|
|
4443
4595
|
const colour = resolveColour(expression, tokens, current);
|
|
4444
|
-
return colour
|
|
4596
|
+
return typeof colour === 'string' && colour.toLowerCase() === 'currentcolor' ? current() : colour;
|
|
4445
4597
|
}
|
|
4446
4598
|
/** A mix's two sides, a mix inside it unrounded, as CSS rounds only the colour at the end. */
|
|
4447
4599
|
function mixSides(mix, tokens, current) {
|
|
@@ -4696,7 +4848,8 @@ function tokenColour(expression, tokens) {
|
|
|
4696
4848
|
if (set)
|
|
4697
4849
|
return formOf(set, 'color');
|
|
4698
4850
|
const token = expression.fallbackToken;
|
|
4699
|
-
return expression.fallback ??
|
|
4851
|
+
return (expression.fallback ??
|
|
4852
|
+
(token && formOf(derived(token, tokens), 'color')));
|
|
4700
4853
|
}
|
|
4701
4854
|
/**
|
|
4702
4855
|
* A shadow's colour from a token that is the colour or the word `inset`: currentcolor, which the
|
|
@@ -4707,6 +4860,39 @@ function insetOrColour(token) {
|
|
|
4707
4860
|
return 'currentcolor';
|
|
4708
4861
|
return formOf(token, 'color');
|
|
4709
4862
|
}
|
|
4863
|
+
/** The kinds of token a colour is part of. */
|
|
4864
|
+
const COLOURED_KINDS = new Set(['color', 'shadow', 'filter']);
|
|
4865
|
+
/**
|
|
4866
|
+
* The first token a declaration or a token reads, at any depth and through the tokens those read,
|
|
4867
|
+
* that holds a platform colour. Asked only of one that came to nothing, in development.
|
|
4868
|
+
*/
|
|
4869
|
+
function platformColourRead(value, tokens, seen) {
|
|
4870
|
+
if (value === null || typeof value !== 'object')
|
|
4871
|
+
return undefined;
|
|
4872
|
+
const record = value;
|
|
4873
|
+
const names = [record['reference'], record['alias'], ...[record['alternatives']].flat()];
|
|
4874
|
+
for (const name of names) {
|
|
4875
|
+
const found = typeof name === 'string' ? platformColourNamed(name, tokens, seen) : undefined;
|
|
4876
|
+
if (found)
|
|
4877
|
+
return found;
|
|
4878
|
+
}
|
|
4879
|
+
for (const part of Object.values(record)) {
|
|
4880
|
+
const found = platformColourRead(part, tokens, seen);
|
|
4881
|
+
if (found)
|
|
4882
|
+
return found;
|
|
4883
|
+
}
|
|
4884
|
+
return undefined;
|
|
4885
|
+
}
|
|
4886
|
+
/** `platformColourRead` of the token `name`, which is the one when it holds a platform colour. */
|
|
4887
|
+
function platformColourNamed(name, tokens, seen) {
|
|
4888
|
+
if (seen.has(name))
|
|
4889
|
+
return undefined;
|
|
4890
|
+
seen.add(name);
|
|
4891
|
+
const token = tokens[name];
|
|
4892
|
+
if (isPlatformColour(token?.color))
|
|
4893
|
+
return name;
|
|
4894
|
+
return token?.platformColourIn ?? platformColourRead(token, tokens, seen);
|
|
4895
|
+
}
|
|
4710
4896
|
/** A marker the compiler leaves in a structured value for a colour only the device can settle. */
|
|
4711
4897
|
function colourMarker(value) {
|
|
4712
4898
|
return value?.__colour;
|
|
@@ -4737,8 +4923,9 @@ function withPercent(value, adjust) {
|
|
|
4737
4923
|
* the app meant, and turning it into NaN would be a silent layout rather than a visible one.
|
|
4738
4924
|
*/
|
|
4739
4925
|
function adjusted(value, adjust) {
|
|
4926
|
+
// A platform colour has no alpha to fade: unset, where it was painted as it stood.
|
|
4740
4927
|
if (adjust.alpha !== undefined)
|
|
4741
|
-
return faded(value, adjust.alpha);
|
|
4928
|
+
return isPlatformColour(value) ? undefined : faded(value, adjust.alpha);
|
|
4742
4929
|
const em = value?.__defer;
|
|
4743
4930
|
if (adjust.percent !== undefined)
|
|
4744
4931
|
return withPercent(value, adjust);
|