@astryxdesign/core 0.6.3-canary.f22695a → 0.6.3
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/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +28 -13
- package/dist/Chat/ChatLayout.d.ts +0 -19
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +0 -19
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +34 -44
- package/dist/Citation/Citation.d.ts +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +2 -3
- package/dist/CodeBlock/highlightRanges.d.ts.map +1 -1
- package/dist/CodeBlock/highlightRanges.js +3 -14
- package/dist/Icon/Icon.d.ts +31 -6
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +71 -8
- package/dist/Link/useLinkComponent.d.ts +15 -5
- package/dist/Link/useLinkComponent.d.ts.map +1 -1
- package/dist/Link/useLinkComponent.js +51 -34
- package/dist/Markdown/Markdown.js +2 -2
- package/dist/Markdown/url.d.ts +0 -2
- package/dist/Markdown/url.d.ts.map +1 -1
- package/dist/Markdown/url.js +2 -8
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +0 -5
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +2 -3
- package/dist/astryx.css +4 -2
- package/dist/hooks/useClickableContainer.d.ts +1 -10
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +4 -15
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -3
- package/dist/theme/generateThemeRules.d.ts +7 -13
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +35 -131
- package/package.json +4 -9
- package/src/Button/Button.doc.mjs +5 -5
- package/src/Button/Button.tsx +13 -15
- package/src/Chat/ChatLayout.doc.mjs +4 -12
- package/src/Chat/ChatLayout.test.tsx +0 -28
- package/src/Chat/ChatLayout.tsx +0 -19
- package/src/Chat/ChatLayoutScrollButton.test.tsx +0 -31
- package/src/Chat/ChatLayoutScrollButton.tsx +14 -31
- package/src/Citation/Citation.doc.mjs +2 -2
- package/src/Citation/Citation.test.tsx +0 -17
- package/src/Citation/Citation.tsx +2 -4
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
- package/src/CodeBlock/highlightRanges.test.ts +1 -143
- package/src/CodeBlock/highlightRanges.ts +5 -15
- package/src/Icon/Icon.doc.mjs +5 -7
- package/src/Icon/Icon.spec.md +40 -81
- package/src/Icon/Icon.test.tsx +3 -6
- package/src/Icon/Icon.tsx +68 -20
- package/src/IconButton/IconButton.doc.mjs +3 -3
- package/src/IconButton/IconButton.test.tsx +0 -40
- package/src/Item/Item.doc.mjs +2 -2
- package/src/Link/Link.doc.mjs +4 -6
- package/src/Link/LinkProvider.doc.mjs +2 -2
- package/src/Link/useLinkComponent.test.tsx +0 -333
- package/src/Link/useLinkComponent.ts +57 -29
- package/src/List/ListItem.doc.mjs +2 -2
- package/src/Markdown/Markdown.doc.mjs +2 -2
- package/src/Markdown/Markdown.spec.md +15 -19
- package/src/Markdown/Markdown.test.tsx +0 -52
- package/src/Markdown/Markdown.tsx +2 -2
- package/src/Markdown/parser.test.ts +0 -20
- package/src/Markdown/url.ts +3 -9
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +0 -51
- package/src/PowerSearch/PowerSearchValueEditor.tsx +0 -4
- package/src/Token/Token.doc.mjs +2 -2
- package/src/TopNav/TopNavMenu.doc.mjs +2 -2
- package/src/TopNav/TopNavMenu.test.tsx +0 -30
- package/src/TopNav/TopNavMenu.tsx +2 -7
- package/src/hooks/useClickableContainer.ts +4 -20
- package/src/index.ts +0 -3
- package/src/tailwind-theme.css +6 -0
- package/src/theme/Theme.test.tsx +0 -32
- package/src/theme/generateThemeRules.test.ts +2 -470
- package/src/theme/generateThemeRules.ts +51 -219
- package/src/theme/tokenValueCompat.test.ts +1 -4
- package/dist/Icon/IconDefaultSizeContext.d.ts +0 -4
- package/dist/Icon/IconDefaultSizeContext.d.ts.map +0 -1
- package/dist/Icon/IconDefaultSizeContext.js +0 -18
- package/dist/Icon/IconSize.stylex.d.ts +0 -65
- package/dist/Icon/IconSize.stylex.d.ts.map +0 -1
- package/dist/Icon/IconSize.stylex.js +0 -75
- package/dist/Timer/Timer.d.ts +0 -49
- package/dist/Timer/Timer.d.ts.map +0 -1
- package/dist/Timer/Timer.js +0 -158
- package/dist/Timer/index.d.ts +0 -9
- package/dist/Timer/index.d.ts.map +0 -1
- package/dist/Timer/index.js +0 -10
- package/dist/theme/declarationBoundary.d.ts +0 -17
- package/dist/theme/declarationBoundary.d.ts.map +0 -1
- package/dist/theme/declarationBoundary.js +0 -343
- package/dist/utils/safeUrl.d.ts +0 -11
- package/dist/utils/safeUrl.d.ts.map +0 -1
- package/dist/utils/safeUrl.js +0 -78
- package/src/Chat/ChatLayout.spec.md +0 -271
- package/src/Chat/ChatLayoutScrollButton.spec.md +0 -338
- package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +0 -514
- package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +0 -740
- package/src/Icon/IconDefaultSizeContext.ts +0 -23
- package/src/Icon/IconSize.stylex.ts +0 -70
- package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +0 -261
- package/src/Markdown/Markdown.renderBoundary.test.tsx +0 -72
- package/src/Timer/Timer.doc.mjs +0 -183
- package/src/Timer/Timer.spec.md +0 -215
- package/src/Timer/Timer.test.tsx +0 -302
- package/src/Timer/Timer.tsx +0 -258
- package/src/Timer/index.ts +0 -11
- package/src/hooks/useClickableContainer.test.tsx +0 -236
- package/src/theme/declarationBoundary.test.ts +0 -126
- package/src/theme/declarationBoundary.ts +0 -347
- package/src/utils/safeUrl.test.ts +0 -88
- package/src/utils/safeUrl.ts +0 -85
|
@@ -9,17 +9,11 @@
|
|
|
9
9
|
* Used by both the runtime path (Theme injects <style>) and the build
|
|
10
10
|
* path (`astryx theme build` pre-compiles to CSS files).
|
|
11
11
|
*
|
|
12
|
-
* Every consumer-supplied declaration is checked by declarationBoundary.ts
|
|
13
|
-
* before it is emitted, so a value can never end its declaration or rule
|
|
14
|
-
* early. A refused declaration is dropped and reported in the supplied
|
|
15
|
-
* warnings array (build receipts), or through `console.warn` (runtime).
|
|
16
|
-
*
|
|
17
12
|
* Extracted from defineTheme.ts to reduce cyclomatic complexity and provide
|
|
18
13
|
* a clear single-responsibility module for CSS generation.
|
|
19
14
|
*
|
|
20
|
-
* @input DefinedTheme (resolved theme object from defineTheme)
|
|
21
|
-
* @output CSS rule strings, split by layer (component vs prose)
|
|
22
|
-
* for each dropped declaration
|
|
15
|
+
* @input DefinedTheme (resolved theme object from defineTheme)
|
|
16
|
+
* @output CSS rule strings, split by layer (component vs prose)
|
|
23
17
|
* @position packages/core/src/theme/generateThemeRules.ts
|
|
24
18
|
*/
|
|
25
19
|
|
|
@@ -32,10 +26,6 @@ import {parseStyleKey} from '../utils/parseStyleKey';
|
|
|
32
26
|
import {getDerivedVars} from './derivedVarRegistry';
|
|
33
27
|
import {dataTokenDefaults} from './domainTokens/dataTokens';
|
|
34
28
|
import {cssVar, classPrefix, dataAttrNamespace} from '../naming';
|
|
35
|
-
import {
|
|
36
|
-
checkDeclarationName,
|
|
37
|
-
checkDeclarationValue,
|
|
38
|
-
} from './declarationBoundary';
|
|
39
29
|
|
|
40
30
|
/**
|
|
41
31
|
* Theme @scope selectors.
|
|
@@ -376,117 +366,6 @@ function expandContainerPadding(
|
|
|
376
366
|
return tokens;
|
|
377
367
|
}
|
|
378
368
|
|
|
379
|
-
// =============================================================================
|
|
380
|
-
// Declaration assembly: a declaration always stays one declaration
|
|
381
|
-
// =============================================================================
|
|
382
|
-
|
|
383
|
-
type DiagnosticSink = (message: string) => void;
|
|
384
|
-
|
|
385
|
-
const warnToConsole: DiagnosticSink = message => {
|
|
386
|
-
console.warn(`[astryx theme] ${message}`);
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
/** Build receipts collect warning text; runtime callers warn by default. */
|
|
390
|
-
function diagnosticSink(warnings: string[] | undefined): DiagnosticSink {
|
|
391
|
-
return warnings ? message => warnings.push(message) : warnToConsole;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/** Shorten an authored value for a one-line message. */
|
|
395
|
-
function previewValue(value: string): string {
|
|
396
|
-
const oneLine = JSON.stringify(value);
|
|
397
|
-
return oneLine.length > 80 ? `${oneLine.slice(0, 77)}..."` : oneLine;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
function reportDrop(
|
|
401
|
-
sink: DiagnosticSink,
|
|
402
|
-
property: string,
|
|
403
|
-
value: string,
|
|
404
|
-
location: string,
|
|
405
|
-
reason: string,
|
|
406
|
-
): void {
|
|
407
|
-
sink(
|
|
408
|
-
`dropped "${property}" in ${location}: ${reason} (value: ${previewValue(value)})`,
|
|
409
|
-
);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* True when `name: value;` stays exactly one declaration; otherwise reports
|
|
414
|
-
* the drop and returns false. Both checks follow CSS syntax, so valid CSS a
|
|
415
|
-
* browser keeps inside one declaration (a `data:` URI, `Gill\ Sans`, a closed
|
|
416
|
-
* comment, a vendor-prefixed property) is never refused; see
|
|
417
|
-
* declarationBoundary.ts for the rules.
|
|
418
|
-
*/
|
|
419
|
-
function acceptDeclaration(
|
|
420
|
-
property: string,
|
|
421
|
-
value: string,
|
|
422
|
-
location: string,
|
|
423
|
-
sink: DiagnosticSink,
|
|
424
|
-
): boolean {
|
|
425
|
-
const reason = checkDeclarationName(property) ?? checkDeclarationValue(value);
|
|
426
|
-
if (reason === null) {
|
|
427
|
-
return true;
|
|
428
|
-
}
|
|
429
|
-
reportDrop(sink, property, value, location, reason);
|
|
430
|
-
return false;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Assemble `prop: value;` lines, dropping (and reporting) any entry whose
|
|
435
|
-
* property or value could not stay a single declaration. Theme definitions
|
|
436
|
-
* are code, but apps do assemble them from stored input (brand colors,
|
|
437
|
-
* white-labeling), so the generated stylesheet must never extend beyond the
|
|
438
|
-
* declarations it means to emit.
|
|
439
|
-
*/
|
|
440
|
-
function joinDeclarations(
|
|
441
|
-
entries: [string, string][],
|
|
442
|
-
location: string,
|
|
443
|
-
sink: DiagnosticSink,
|
|
444
|
-
mapProp: (prop: string) => string = p => p,
|
|
445
|
-
): string {
|
|
446
|
-
const lines: string[] = [];
|
|
447
|
-
for (const [rawProp, rawValue] of entries) {
|
|
448
|
-
// Legacy unenrolled tokens retain non-string values. Scan the same text
|
|
449
|
-
// interpolation has always emitted, without changing the normalized theme.
|
|
450
|
-
const value = `${rawValue}`;
|
|
451
|
-
const prop = mapProp(rawProp);
|
|
452
|
-
if (acceptDeclaration(prop, value, location, sink)) {
|
|
453
|
-
lines.push(` ${prop}: ${value};`);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
return lines.join('\n');
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/** The `:scope` token block for portable and theme-local token values. */
|
|
460
|
-
function tokenBlock(
|
|
461
|
-
source: ThemeRuleSource,
|
|
462
|
-
location: string,
|
|
463
|
-
sink: DiagnosticSink,
|
|
464
|
-
): string | null {
|
|
465
|
-
const declarations = [
|
|
466
|
-
joinDeclarations(Object.entries(source.tokens), `${location}tokens`, sink),
|
|
467
|
-
joinDeclarations(
|
|
468
|
-
Object.entries(source.localTokens ?? {}),
|
|
469
|
-
`${location}localTokens`,
|
|
470
|
-
sink,
|
|
471
|
-
),
|
|
472
|
-
]
|
|
473
|
-
.filter(block => block.length > 0)
|
|
474
|
-
.join('\n');
|
|
475
|
-
const hasEntries =
|
|
476
|
-
Object.keys(source.tokens).length > 0 ||
|
|
477
|
-
Object.keys(source.localTokens ?? {}).length > 0;
|
|
478
|
-
return hasEntries ? ` :scope {\n${declarations}\n }` : null;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/** `components.button["variant:secondary"]`-style location for a rule. */
|
|
482
|
-
function componentLocation(
|
|
483
|
-
prefix: string,
|
|
484
|
-
component: string,
|
|
485
|
-
key: string,
|
|
486
|
-
): string {
|
|
487
|
-
return `${prefix}components.${component}[${JSON.stringify(key)}]`;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
369
|
// =============================================================================
|
|
491
370
|
// Public API
|
|
492
371
|
// =============================================================================
|
|
@@ -514,12 +393,9 @@ export interface ThemeRuleSource {
|
|
|
514
393
|
components?: ComponentStyleMap;
|
|
515
394
|
}
|
|
516
395
|
|
|
517
|
-
export function generateThemeRules(
|
|
518
|
-
theme: ThemeRuleSource,
|
|
519
|
-
warnings?: string[],
|
|
520
|
-
): string[] {
|
|
396
|
+
export function generateThemeRules(theme: ThemeRuleSource): string[] {
|
|
521
397
|
const parts: string[] = [];
|
|
522
|
-
const
|
|
398
|
+
const tokens = theme.tokens;
|
|
523
399
|
|
|
524
400
|
// Bare prose rules reference semantic variables instead of baking the root
|
|
525
401
|
// value. That lets adaptation token writes take effect through CSS alone
|
|
@@ -527,9 +403,15 @@ export function generateThemeRules(
|
|
|
527
403
|
const val = (key: string): string => `var(${key})`;
|
|
528
404
|
|
|
529
405
|
// 1. Token block — CSS custom properties on :scope
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
406
|
+
const tokenEntries = [
|
|
407
|
+
...Object.entries(tokens),
|
|
408
|
+
...Object.entries(theme.localTokens ?? {}),
|
|
409
|
+
];
|
|
410
|
+
if (tokenEntries.length > 0) {
|
|
411
|
+
const declarations = tokenEntries
|
|
412
|
+
.map(([prop, value]) => ` ${prop}: ${value};`)
|
|
413
|
+
.join('\n');
|
|
414
|
+
parts.push(` :scope {\n${declarations}\n }`);
|
|
533
415
|
}
|
|
534
416
|
|
|
535
417
|
// 1b. Base font — apply the theme's declared body font to the scope root.
|
|
@@ -538,14 +420,14 @@ export function generateThemeRules(
|
|
|
538
420
|
// sets a page font. `font-family` inherits, so one rule on :scope covers
|
|
539
421
|
// the tree. Only emitted when the theme declares a body font, so a bare
|
|
540
422
|
// theme still contributes no scope rules of its own.
|
|
541
|
-
if (
|
|
423
|
+
if (tokens['--font-family-body']) {
|
|
542
424
|
parts.push(` :scope {\n font-family: var(--font-family-body);\n }`);
|
|
543
425
|
}
|
|
544
426
|
|
|
545
427
|
// 2. Component overrides: stable .astryx-* target classes combined with
|
|
546
428
|
// reflected data-* selectors for visual props and runtime states.
|
|
547
429
|
if (theme.components) {
|
|
548
|
-
generateComponentRules(theme.components, parts
|
|
430
|
+
generateComponentRules(theme.components, parts);
|
|
549
431
|
}
|
|
550
432
|
|
|
551
433
|
// 3. Prose HTML element rules (h1-h6, p, small, code, hr)
|
|
@@ -641,13 +523,6 @@ function generateHeadingWeightOverrides(
|
|
|
641
523
|
}
|
|
642
524
|
}
|
|
643
525
|
|
|
644
|
-
/**
|
|
645
|
-
* The `fontWeight` a heading rule authors for `styleKey`, or undefined when
|
|
646
|
-
* it has none. A value that cannot stay one declaration is treated as not
|
|
647
|
-
* authored, so the override falls back to the inherited or token weight
|
|
648
|
-
* instead of interpolating it; the drop itself is reported where that same
|
|
649
|
-
* rule's declarations are emitted, so it is not reported twice here.
|
|
650
|
-
*/
|
|
651
526
|
function getAuthoredHeadingWeight(
|
|
652
527
|
headingRuleMap: Record<string, unknown>,
|
|
653
528
|
styleKey: string,
|
|
@@ -657,20 +532,13 @@ function getAuthoredHeadingWeight(
|
|
|
657
532
|
return undefined;
|
|
658
533
|
}
|
|
659
534
|
const fontWeight = (rule as Record<string, unknown>).fontWeight;
|
|
660
|
-
return typeof fontWeight === 'string'
|
|
661
|
-
checkDeclarationValue(fontWeight) === null
|
|
662
|
-
? fontWeight
|
|
663
|
-
: undefined;
|
|
535
|
+
return typeof fontWeight === 'string' ? fontWeight : undefined;
|
|
664
536
|
}
|
|
665
537
|
|
|
666
538
|
/** Options shared by root, adaptation, and media-surface component lowering. */
|
|
667
539
|
interface ComponentRuleOptions {
|
|
668
540
|
resetInheritedPaddingSpecificity?: boolean;
|
|
669
541
|
surface?: MediaSurface;
|
|
670
|
-
/** Receives dropped declarations; defaults to `console.warn`. */
|
|
671
|
-
sink?: DiagnosticSink;
|
|
672
|
-
/** Location prefix for diagnostics, e.g. `onDark.` or `adaptations[0].`. */
|
|
673
|
-
location?: string;
|
|
674
542
|
}
|
|
675
543
|
|
|
676
544
|
/**
|
|
@@ -687,8 +555,6 @@ function generateComponentRules(
|
|
|
687
555
|
{
|
|
688
556
|
resetInheritedPaddingSpecificity = false,
|
|
689
557
|
surface,
|
|
690
|
-
sink = warnToConsole,
|
|
691
|
-
location: locationPrefix = '',
|
|
692
558
|
}: ComponentRuleOptions = {},
|
|
693
559
|
): void {
|
|
694
560
|
for (const [component, rules] of Object.entries(components)) {
|
|
@@ -700,7 +566,6 @@ function generateComponentRules(
|
|
|
700
566
|
|
|
701
567
|
const suffix = parseStyleKey(key);
|
|
702
568
|
const baseSelector = componentSelector(component, suffix, surface);
|
|
703
|
-
const location = componentLocation(locationPrefix, component, key);
|
|
704
569
|
|
|
705
570
|
// Separate regular properties from pseudo-class overrides
|
|
706
571
|
const props: [string, string][] = [];
|
|
@@ -709,14 +574,7 @@ function generateComponentRules(
|
|
|
709
574
|
for (const [prop, value] of entries) {
|
|
710
575
|
if (prop.startsWith(':') && typeof value === 'object') {
|
|
711
576
|
pseudos.push([prop, value]);
|
|
712
|
-
} else
|
|
713
|
-
acceptDeclaration(
|
|
714
|
-
toKebabCase(prop),
|
|
715
|
-
`${value as string}`,
|
|
716
|
-
location,
|
|
717
|
-
sink,
|
|
718
|
-
)
|
|
719
|
-
) {
|
|
577
|
+
} else {
|
|
720
578
|
props.push([prop, value as string]);
|
|
721
579
|
}
|
|
722
580
|
}
|
|
@@ -796,12 +654,9 @@ function generateComponentRules(
|
|
|
796
654
|
|
|
797
655
|
// Emit base rule
|
|
798
656
|
if (finalProps.length > 0) {
|
|
799
|
-
const declarations =
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
sink,
|
|
803
|
-
toKebabCase,
|
|
804
|
-
);
|
|
657
|
+
const declarations = finalProps
|
|
658
|
+
.map(([prop, value]) => ` ${toKebabCase(prop)}: ${value};`)
|
|
659
|
+
.join('\n');
|
|
805
660
|
parts.push(` ${baseSelector} {\n${declarations}\n }`);
|
|
806
661
|
}
|
|
807
662
|
|
|
@@ -809,12 +664,9 @@ function generateComponentRules(
|
|
|
809
664
|
for (const [pseudo, pseudoStyles] of pseudos) {
|
|
810
665
|
const pseudoEntries = Object.entries(pseudoStyles);
|
|
811
666
|
if (pseudoEntries.length > 0) {
|
|
812
|
-
const declarations =
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
sink,
|
|
816
|
-
toKebabCase,
|
|
817
|
-
);
|
|
667
|
+
const declarations = pseudoEntries
|
|
668
|
+
.map(([prop, value]) => ` ${toKebabCase(prop)}: ${value};`)
|
|
669
|
+
.join('\n');
|
|
818
670
|
parts.push(
|
|
819
671
|
` ${appendPseudoToSelectorList(baseSelector, pseudo)} {\n${declarations}\n }`,
|
|
820
672
|
);
|
|
@@ -980,11 +832,8 @@ function generateSizeOverrides(
|
|
|
980
832
|
* Component rules (tokens, stable .astryx-* targets plus data-* selectors) are
|
|
981
833
|
* that need to beat StyleX — they stay in astryx-theme (above StyleX layers).
|
|
982
834
|
*/
|
|
983
|
-
export function generateThemeRulesSplit(
|
|
984
|
-
theme
|
|
985
|
-
warnings?: string[],
|
|
986
|
-
): ThemeRulesSplit {
|
|
987
|
-
const allRules = generateThemeRules(theme, warnings);
|
|
835
|
+
export function generateThemeRulesSplit(theme: DefinedTheme): ThemeRulesSplit {
|
|
836
|
+
const allRules = generateThemeRules(theme);
|
|
988
837
|
|
|
989
838
|
const prose: string[] = [];
|
|
990
839
|
const component: string[] = [];
|
|
@@ -1008,29 +857,22 @@ export function generateThemeRulesSplit(
|
|
|
1008
857
|
* to media contexts — only tokens change. Themes can further customize
|
|
1009
858
|
* via onDark.components / onLight.components.
|
|
1010
859
|
*/
|
|
1011
|
-
export function generateOnMediaCSS(
|
|
1012
|
-
theme: DefinedTheme,
|
|
1013
|
-
warnings?: string[],
|
|
1014
|
-
): string {
|
|
860
|
+
export function generateOnMediaCSS(theme: DefinedTheme): string {
|
|
1015
861
|
const parts: string[] = [];
|
|
1016
862
|
const scopeSelector = themeScopeStart(theme.name);
|
|
1017
|
-
const sink = diagnosticSink(warnings);
|
|
1018
863
|
|
|
1019
864
|
for (const surface of ['dark', 'light'] as const) {
|
|
1020
865
|
const onMedia = surface === 'dark' ? theme.__onDark : theme.__onLight;
|
|
1021
866
|
if (!onMedia) {
|
|
1022
867
|
continue;
|
|
1023
868
|
}
|
|
1024
|
-
const location = surface === 'dark' ? 'onDark.' : 'onLight.';
|
|
1025
869
|
|
|
1026
870
|
// Token overrides
|
|
1027
871
|
const tokenEntries = Object.entries(onMedia.tokens);
|
|
1028
872
|
if (tokenEntries.length > 0) {
|
|
1029
|
-
const declarations =
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
sink,
|
|
1033
|
-
);
|
|
873
|
+
const declarations = tokenEntries
|
|
874
|
+
.map(([prop, value]) => ` ${prop}: ${value};`)
|
|
875
|
+
.join('\n');
|
|
1034
876
|
parts.push(` ${mediaSelector(surface)} {\n${declarations}\n }`);
|
|
1035
877
|
}
|
|
1036
878
|
|
|
@@ -1040,8 +882,6 @@ export function generateOnMediaCSS(
|
|
|
1040
882
|
generateComponentRules(onMedia.components, parts, {
|
|
1041
883
|
resetInheritedPaddingSpecificity: true,
|
|
1042
884
|
surface,
|
|
1043
|
-
sink,
|
|
1044
|
-
location,
|
|
1045
885
|
});
|
|
1046
886
|
generateColorOverrides(onMedia.components, parts, surface);
|
|
1047
887
|
generateSizeOverrides(onMedia.components, parts, surface);
|
|
@@ -1065,22 +905,22 @@ export function generateOnMediaCSS(
|
|
|
1065
905
|
}
|
|
1066
906
|
|
|
1067
907
|
/** Generate only the declarations one adaptation rule writes. */
|
|
1068
|
-
function generateAdaptationRuleRules(
|
|
1069
|
-
rule: ThemeRuleSource,
|
|
1070
|
-
location: string,
|
|
1071
|
-
sink: DiagnosticSink,
|
|
1072
|
-
): string[] {
|
|
908
|
+
function generateAdaptationRuleRules(rule: ThemeRuleSource): string[] {
|
|
1073
909
|
const parts: string[] = [];
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1076
|
-
|
|
910
|
+
const tokenEntries = [
|
|
911
|
+
...Object.entries(rule.tokens),
|
|
912
|
+
...Object.entries(rule.localTokens ?? {}),
|
|
913
|
+
];
|
|
914
|
+
if (tokenEntries.length > 0) {
|
|
915
|
+
const declarations = tokenEntries
|
|
916
|
+
.map(([prop, value]) => ` ${prop}: ${value};`)
|
|
917
|
+
.join('\n');
|
|
918
|
+
parts.push(` :scope {\n${declarations}\n }`);
|
|
1077
919
|
}
|
|
1078
920
|
|
|
1079
921
|
if (rule.components) {
|
|
1080
922
|
generateComponentRules(rule.components, parts, {
|
|
1081
923
|
resetInheritedPaddingSpecificity: true,
|
|
1082
|
-
sink,
|
|
1083
|
-
location,
|
|
1084
924
|
});
|
|
1085
925
|
generateColorOverrides(rule.components, parts);
|
|
1086
926
|
generateSizeOverrides(rule.components, parts);
|
|
@@ -1118,11 +958,7 @@ function generateAdaptationMediaBlock(
|
|
|
1118
958
|
* rule. Bare prose follows semantic variables, so token writes need no duplicate
|
|
1119
959
|
* prose selectors here.
|
|
1120
960
|
*/
|
|
1121
|
-
export function generateAdaptationCSS(
|
|
1122
|
-
theme: DefinedTheme,
|
|
1123
|
-
warnings?: string[],
|
|
1124
|
-
): ThemeCSSOutput {
|
|
1125
|
-
const sink = diagnosticSink(warnings);
|
|
961
|
+
export function generateAdaptationCSS(theme: DefinedTheme): ThemeCSSOutput {
|
|
1126
962
|
// Built themes can reach this compiler without passing through defineTheme.
|
|
1127
963
|
// Validate retained metadata even when it has no rules (and therefore emits
|
|
1128
964
|
// no CSS): width points remain observable through AppShell and inheritance.
|
|
@@ -1156,12 +992,8 @@ export function generateAdaptationCSS(
|
|
|
1156
992
|
// active whenever the later condition matches, even if the earlier condition
|
|
1157
993
|
// does not. Pairwise merging cannot repair that: multiple mutually exclusive
|
|
1158
994
|
// earlier rules can each overlap one broad later rule.
|
|
1159
|
-
for (const
|
|
1160
|
-
const parts = generateAdaptationRuleRules(
|
|
1161
|
-
rule,
|
|
1162
|
-
`adaptations[${index}].`,
|
|
1163
|
-
sink,
|
|
1164
|
-
);
|
|
995
|
+
for (const rule of rules) {
|
|
996
|
+
const parts = generateAdaptationRuleRules(rule);
|
|
1165
997
|
if (parts.length === 0) {
|
|
1166
998
|
continue;
|
|
1167
999
|
}
|
|
@@ -1207,9 +1039,12 @@ export function generateAdaptationCSS(
|
|
|
1207
1039
|
return {prose: '', component: blocks.join('\n\n')};
|
|
1208
1040
|
}
|
|
1209
1041
|
|
|
1210
|
-
/** Indent
|
|
1042
|
+
/** Indent a generated rule one level further, for nesting inside `@media`. */
|
|
1211
1043
|
function indentRule(rule: string): string {
|
|
1212
|
-
return
|
|
1044
|
+
return rule
|
|
1045
|
+
.split('\n')
|
|
1046
|
+
.map(line => (line.length > 0 ? ` ${line}` : line))
|
|
1047
|
+
.join('\n');
|
|
1213
1048
|
}
|
|
1214
1049
|
|
|
1215
1050
|
/**
|
|
@@ -1250,11 +1085,8 @@ export function generateDataTokenDefaultsCSS(): string {
|
|
|
1250
1085
|
* The theme-independent `--color-data-*` defaults are not part of this output:
|
|
1251
1086
|
* see `generateDataTokenDefaultsCSS`.
|
|
1252
1087
|
*/
|
|
1253
|
-
export function generateThemeCSS(
|
|
1254
|
-
|
|
1255
|
-
warnings?: string[],
|
|
1256
|
-
): ThemeCSSOutput {
|
|
1257
|
-
const {component, prose} = generateThemeRulesSplit(theme, warnings);
|
|
1088
|
+
export function generateThemeCSS(theme: DefinedTheme): ThemeCSSOutput {
|
|
1089
|
+
const {component, prose} = generateThemeRulesSplit(theme);
|
|
1258
1090
|
const scopeSelector = themeScopeStart(theme.name);
|
|
1259
1091
|
const scopeTo = THEME_SCOPE_TO;
|
|
1260
1092
|
|
|
@@ -1274,14 +1106,14 @@ export function generateThemeCSS(
|
|
|
1274
1106
|
|
|
1275
1107
|
// Adaptations follow the root theme in authored order. Media-surface rules
|
|
1276
1108
|
// follow adaptations so onDark/onLight keep their specified precedence.
|
|
1277
|
-
const adaptationCss = generateAdaptationCSS(theme
|
|
1109
|
+
const adaptationCss = generateAdaptationCSS(theme);
|
|
1278
1110
|
if (adaptationCss.component) {
|
|
1279
1111
|
componentCss = componentCss
|
|
1280
1112
|
? `${componentCss}\n\n${adaptationCss.component}`
|
|
1281
1113
|
: adaptationCss.component;
|
|
1282
1114
|
}
|
|
1283
1115
|
|
|
1284
|
-
const onMediaCss = generateOnMediaCSS(theme
|
|
1116
|
+
const onMediaCss = generateOnMediaCSS(theme);
|
|
1285
1117
|
if (onMediaCss) {
|
|
1286
1118
|
componentCss = componentCss
|
|
1287
1119
|
? `${componentCss}\n\n${onMediaCss}`
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import {describe, expect, it} from 'vitest';
|
|
25
|
-
import {defineTheme
|
|
25
|
+
import {defineTheme} from './defineTheme';
|
|
26
26
|
import {resolveTokenValue} from './resolveThemeValues';
|
|
27
27
|
|
|
28
28
|
/** Exactly what the pre-extraction implementation did with each shape. */
|
|
@@ -43,9 +43,6 @@ describe('root token values keep their historical acceptance', () => {
|
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
expect(theme.tokens['--color-background-body']).toBe(expected);
|
|
46
|
-
expect(generateThemeCSS(theme).component).toContain(
|
|
47
|
-
`--color-background-body: ${String(expected)};`,
|
|
48
|
-
);
|
|
49
46
|
});
|
|
50
47
|
|
|
51
48
|
it('still resolves the documented shapes', () => {
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { IconSize } from './IconSize.stylex';
|
|
2
|
-
export declare const IconDefaultSizeProvider: import("react").Provider<"xsm" | "sm" | "lg" | "md" | null>;
|
|
3
|
-
export declare function useIconSize(size: IconSize | undefined): IconSize;
|
|
4
|
-
//# sourceMappingURL=IconDefaultSizeContext.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IconDefaultSizeContext.d.ts","sourceRoot":"","sources":["../../src/Icon/IconDefaultSizeContext.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAKhD,eAAO,MAAM,uBAAuB,6DAAkC,CAAC;AAEvE,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAGhE"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @file IconDefaultSizeContext.ts
|
|
7
|
-
* @input Uses React context and an optional Icon size prop
|
|
8
|
-
* @output Supplies a component-owned default size to descendant Icon instances
|
|
9
|
-
* @position Internal Icon sizing context; consumed by Icon and icon-slot owners
|
|
10
|
-
*/
|
|
11
|
-
import { createContext, use } from 'react';
|
|
12
|
-
const IconDefaultSizeContext = /*#__PURE__*/createContext(null);
|
|
13
|
-
IconDefaultSizeContext.displayName = 'IconDefaultSizeContext';
|
|
14
|
-
export const IconDefaultSizeProvider = IconDefaultSizeContext.Provider;
|
|
15
|
-
export function useIconSize(size) {
|
|
16
|
-
const contextualSize = use(IconDefaultSizeContext);
|
|
17
|
-
return size ?? contextualSize ?? 'md';
|
|
18
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file IconSize.stylex.ts
|
|
3
|
-
* @input Defines the Icon size scale
|
|
4
|
-
* @output Exports shared Icon size types and StyleX styles
|
|
5
|
-
* @position Internal Icon sizing source; consumed by Icon and icon-slot owners
|
|
6
|
-
*/
|
|
7
|
-
import * as stylex from '@stylexjs/stylex';
|
|
8
|
-
/**
|
|
9
|
-
* Icon sizes are expressed in `rem` so they scale with the root font-size.
|
|
10
|
-
* Values are the px-equivalents at a 16px root: 12, 16, 20, and 24px.
|
|
11
|
-
*/
|
|
12
|
-
declare const iconSizeValues: {
|
|
13
|
-
readonly xsm: "0.75rem";
|
|
14
|
-
readonly sm: "1rem";
|
|
15
|
-
readonly md: "1.25rem";
|
|
16
|
-
readonly lg: "1.5rem";
|
|
17
|
-
};
|
|
18
|
-
export type IconSize = keyof typeof iconSizeValues;
|
|
19
|
-
/** Size styles for direct SVG icon components. */
|
|
20
|
-
export declare const iconSizeStyles: Readonly<{
|
|
21
|
-
readonly xsm: Readonly<{
|
|
22
|
-
readonly width: stylex.StyleXClassNameFor<"width", "0.75rem">;
|
|
23
|
-
readonly height: stylex.StyleXClassNameFor<"height", "0.75rem">;
|
|
24
|
-
}>;
|
|
25
|
-
readonly sm: Readonly<{
|
|
26
|
-
readonly width: stylex.StyleXClassNameFor<"width", "1rem">;
|
|
27
|
-
readonly height: stylex.StyleXClassNameFor<"height", "1rem">;
|
|
28
|
-
}>;
|
|
29
|
-
readonly md: Readonly<{
|
|
30
|
-
readonly width: stylex.StyleXClassNameFor<"width", "1.25rem">;
|
|
31
|
-
readonly height: stylex.StyleXClassNameFor<"height", "1.25rem">;
|
|
32
|
-
}>;
|
|
33
|
-
readonly lg: Readonly<{
|
|
34
|
-
readonly width: stylex.StyleXClassNameFor<"width", "1.5rem">;
|
|
35
|
-
readonly height: stylex.StyleXClassNameFor<"height", "1.5rem">;
|
|
36
|
-
}>;
|
|
37
|
-
}>;
|
|
38
|
-
/**
|
|
39
|
-
* Size styles for icon boxes and string-based registry icons. `fontSize`
|
|
40
|
-
* keeps 1em-based icons in step with the box.
|
|
41
|
-
*/
|
|
42
|
-
export declare const iconBoxSizeStyles: Readonly<{
|
|
43
|
-
readonly xsm: Readonly<{
|
|
44
|
-
readonly width: stylex.StyleXClassNameFor<"width", "0.75rem">;
|
|
45
|
-
readonly height: stylex.StyleXClassNameFor<"height", "0.75rem">;
|
|
46
|
-
readonly fontSize: stylex.StyleXClassNameFor<"fontSize", "0.75rem">;
|
|
47
|
-
}>;
|
|
48
|
-
readonly sm: Readonly<{
|
|
49
|
-
readonly width: stylex.StyleXClassNameFor<"width", "1rem">;
|
|
50
|
-
readonly height: stylex.StyleXClassNameFor<"height", "1rem">;
|
|
51
|
-
readonly fontSize: stylex.StyleXClassNameFor<"fontSize", "1rem">;
|
|
52
|
-
}>;
|
|
53
|
-
readonly md: Readonly<{
|
|
54
|
-
readonly width: stylex.StyleXClassNameFor<"width", "1.25rem">;
|
|
55
|
-
readonly height: stylex.StyleXClassNameFor<"height", "1.25rem">;
|
|
56
|
-
readonly fontSize: stylex.StyleXClassNameFor<"fontSize", "1.25rem">;
|
|
57
|
-
}>;
|
|
58
|
-
readonly lg: Readonly<{
|
|
59
|
-
readonly width: stylex.StyleXClassNameFor<"width", "1.5rem">;
|
|
60
|
-
readonly height: stylex.StyleXClassNameFor<"height", "1.5rem">;
|
|
61
|
-
readonly fontSize: stylex.StyleXClassNameFor<"fontSize", "1.5rem">;
|
|
62
|
-
}>;
|
|
63
|
-
}>;
|
|
64
|
-
export {};
|
|
65
|
-
//# sourceMappingURL=IconSize.stylex.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IconSize.stylex.d.ts","sourceRoot":"","sources":["../../src/Icon/IconSize.stylex.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAE3C;;;GAGG;AACH,QAAA,MAAM,cAAc;;;;;CAKV,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,cAAc,CAAC;AAEnD,kDAAkD;AAClD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;EAiBzB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;EAqB5B,CAAC"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file IconSize.stylex.ts
|
|
5
|
-
* @input Defines the Icon size scale
|
|
6
|
-
* @output Exports shared Icon size types and StyleX styles
|
|
7
|
-
* @position Internal Icon sizing source; consumed by Icon and icon-slot owners
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import * as stylex from '@stylexjs/stylex';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Icon sizes are expressed in `rem` so they scale with the root font-size.
|
|
14
|
-
* Values are the px-equivalents at a 16px root: 12, 16, 20, and 24px.
|
|
15
|
-
*/
|
|
16
|
-
const iconSizeValues = {
|
|
17
|
-
xsm: '0.75rem',
|
|
18
|
-
sm: '1rem',
|
|
19
|
-
md: '1.25rem',
|
|
20
|
-
lg: '1.5rem'
|
|
21
|
-
};
|
|
22
|
-
/** Size styles for direct SVG icon components. */
|
|
23
|
-
export const iconSizeStyles = {
|
|
24
|
-
xsm: {
|
|
25
|
-
kzqmXN: "x1jw3ynk",
|
|
26
|
-
kZKoxP: "xvle69y",
|
|
27
|
-
$$css: true
|
|
28
|
-
},
|
|
29
|
-
sm: {
|
|
30
|
-
kzqmXN: "xcdlrvm",
|
|
31
|
-
kZKoxP: "x1l36t39",
|
|
32
|
-
$$css: true
|
|
33
|
-
},
|
|
34
|
-
md: {
|
|
35
|
-
kzqmXN: "xwqq7k2",
|
|
36
|
-
kZKoxP: "xmll18r",
|
|
37
|
-
$$css: true
|
|
38
|
-
},
|
|
39
|
-
lg: {
|
|
40
|
-
kzqmXN: "xp8d6y2",
|
|
41
|
-
kZKoxP: "xam5rvr",
|
|
42
|
-
$$css: true
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Size styles for icon boxes and string-based registry icons. `fontSize`
|
|
48
|
-
* keeps 1em-based icons in step with the box.
|
|
49
|
-
*/
|
|
50
|
-
export const iconBoxSizeStyles = {
|
|
51
|
-
xsm: {
|
|
52
|
-
kzqmXN: "x1jw3ynk",
|
|
53
|
-
kZKoxP: "xvle69y",
|
|
54
|
-
kGuDYH: "xboafo0",
|
|
55
|
-
$$css: true
|
|
56
|
-
},
|
|
57
|
-
sm: {
|
|
58
|
-
kzqmXN: "xcdlrvm",
|
|
59
|
-
kZKoxP: "x1l36t39",
|
|
60
|
-
kGuDYH: "x1jchvi3",
|
|
61
|
-
$$css: true
|
|
62
|
-
},
|
|
63
|
-
md: {
|
|
64
|
-
kzqmXN: "xwqq7k2",
|
|
65
|
-
kZKoxP: "xmll18r",
|
|
66
|
-
kGuDYH: "x1603h9y",
|
|
67
|
-
$$css: true
|
|
68
|
-
},
|
|
69
|
-
lg: {
|
|
70
|
-
kzqmXN: "xp8d6y2",
|
|
71
|
-
kZKoxP: "xam5rvr",
|
|
72
|
-
kGuDYH: "xngnso2",
|
|
73
|
-
$$css: true
|
|
74
|
-
}
|
|
75
|
-
};
|