zyzz 0.0.20 → 0.0.21
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/Style.d.ts +7 -0
- package/dist/Style.d.ts.map +1 -1
- package/dist/Style.js +1 -5
- package/dist/Style.js.map +1 -1
- package/dist/compiler/Graph.d.ts +3 -0
- package/dist/compiler/Graph.d.ts.map +1 -1
- package/dist/compiler/Graph.js +44 -37
- package/dist/compiler/Graph.js.map +1 -1
- package/dist/compiler/Source.d.ts +4 -0
- package/dist/compiler/Source.d.ts.map +1 -1
- package/dist/compiler/Source.js +63 -6
- package/dist/compiler/Source.js.map +1 -1
- package/dist/compiler/Transform.d.ts +4 -1
- package/dist/compiler/Transform.d.ts.map +1 -1
- package/dist/compiler/Transform.js +32 -46
- package/dist/compiler/Transform.js.map +1 -1
- package/dist/compiler/internal/Catalogs.d.ts.map +1 -1
- package/dist/compiler/internal/Catalogs.js +6 -1
- package/dist/compiler/internal/Catalogs.js.map +1 -1
- package/dist/compiler/internal/Compositions.d.ts.map +1 -1
- package/dist/compiler/internal/Compositions.js +5 -0
- package/dist/compiler/internal/Compositions.js.map +1 -1
- package/dist/compiler/internal/Configurations.d.ts.map +1 -1
- package/dist/compiler/internal/Configurations.js +2 -1
- package/dist/compiler/internal/Configurations.js.map +1 -1
- package/dist/compiler/internal/Contract.d.ts +4 -1
- package/dist/compiler/internal/Contract.d.ts.map +1 -1
- package/dist/compiler/internal/Contract.js +56 -147
- package/dist/compiler/internal/Contract.js.map +1 -1
- package/dist/compiler/internal/Contributions.d.ts.map +1 -1
- package/dist/compiler/internal/Contributions.js +1 -3
- package/dist/compiler/internal/Contributions.js.map +1 -1
- package/dist/compiler/internal/Dynamic.d.ts +1 -1
- package/dist/compiler/internal/Dynamic.d.ts.map +1 -1
- package/dist/compiler/internal/Dynamic.js +5 -5
- package/dist/compiler/internal/Dynamic.js.map +1 -1
- package/dist/compiler/internal/Names.d.ts +5 -0
- package/dist/compiler/internal/Names.d.ts.map +1 -0
- package/dist/compiler/internal/Names.js +37 -0
- package/dist/compiler/internal/Names.js.map +1 -0
- package/dist/compiler/internal/Selectors.d.ts +1 -1
- package/dist/compiler/internal/Selectors.d.ts.map +1 -1
- package/dist/compiler/internal/Selectors.js +5 -2
- package/dist/compiler/internal/Selectors.js.map +1 -1
- package/dist/compiler/internal/Stylesheets.js +2 -2
- package/dist/compiler/internal/Stylesheets.js.map +1 -1
- package/dist/compiler/internal/Themes.d.ts.map +1 -1
- package/dist/compiler/internal/Themes.js +2 -1
- package/dist/compiler/internal/Themes.js.map +1 -1
- package/dist/compiler/internal/Vars.d.ts +2 -0
- package/dist/compiler/internal/Vars.d.ts.map +1 -1
- package/dist/compiler/internal/Vars.js +7 -1
- package/dist/compiler/internal/Vars.js.map +1 -1
- package/dist/default.d.ts +4 -4
- package/dist/default.d.ts.map +1 -1
- package/dist/default.js +9 -9
- package/dist/default.js.map +2 -2
- package/dist/default.js.zyzz.json +1 -1
- package/dist/internal/Authoring.d.ts.map +1 -1
- package/dist/internal/Authoring.js +8 -3
- package/dist/internal/Authoring.js.map +1 -1
- package/dist/internal/Binding.d.ts +4 -0
- package/dist/internal/Binding.d.ts.map +1 -1
- package/dist/internal/Binding.js +2 -0
- package/dist/internal/Binding.js.map +1 -1
- package/dist/internal/Configuration.d.ts +2 -2
- package/dist/internal/Configuration.d.ts.map +1 -1
- package/dist/internal/Configuration.js +4 -2
- package/dist/internal/Configuration.js.map +1 -1
- package/dist/internal/Identity.d.ts +3 -3
- package/dist/internal/Identity.d.ts.map +1 -1
- package/dist/internal/Identity.js +11 -9
- package/dist/internal/Identity.js.map +1 -1
- package/dist/internal/Theme.js +2 -2
- package/dist/internal/Theme.js.map +1 -1
- package/dist/internal/Token.d.ts +5 -1
- package/dist/internal/Token.d.ts.map +1 -1
- package/dist/internal/Token.js +9 -2
- package/dist/internal/Token.js.map +1 -1
- package/dist/internal/VariableSets.js +1 -1
- package/dist/internal/VariableSets.js.map +1 -1
- package/dist/node/Host.d.ts.map +1 -1
- package/dist/node/Host.js +2 -0
- package/dist/node/Host.js.map +1 -1
- package/dist/variable.js +1 -1
- package/dist/variable.js.map +1 -1
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +36 -12
- package/dist/vite/index.js.map +1 -1
- package/dist/web/Css.d.ts +7 -2
- package/dist/web/Css.d.ts.map +1 -1
- package/dist/web/Css.js +46 -39
- package/dist/web/Css.js.map +1 -1
- package/dist/web/internal/ClassName.d.ts +13 -2
- package/dist/web/internal/ClassName.d.ts.map +1 -1
- package/dist/web/internal/ClassName.js +17 -30
- package/dist/web/internal/ClassName.js.map +1 -1
- package/dist/web/internal/Themes.d.ts +3 -0
- package/dist/web/internal/Themes.d.ts.map +1 -1
- package/dist/web/internal/Themes.js +48 -24
- package/dist/web/internal/Themes.js.map +1 -1
- package/package.json +1 -1
- package/src/Style.ts +4 -1
- package/src/compiler/Graph.ts +60 -46
- package/src/compiler/Source.ts +83 -5
- package/src/compiler/Transform.ts +42 -60
- package/src/compiler/internal/Catalogs.ts +9 -1
- package/src/compiler/internal/Compositions.ts +7 -0
- package/src/compiler/internal/Configurations.ts +2 -1
- package/src/compiler/internal/Contract.ts +75 -253
- package/src/compiler/internal/Contributions.ts +1 -5
- package/src/compiler/internal/Dynamic.ts +14 -9
- package/src/compiler/internal/Names.ts +48 -0
- package/src/compiler/internal/Selectors.ts +6 -1
- package/src/compiler/internal/Stylesheets.ts +2 -2
- package/src/compiler/internal/Themes.ts +6 -1
- package/src/compiler/internal/Vars.ts +9 -1
- package/src/default.ts +9 -10
- package/src/internal/Authoring.ts +8 -2
- package/src/internal/Binding.ts +5 -0
- package/src/internal/Configuration.ts +7 -4
- package/src/internal/Identity.ts +14 -12
- package/src/internal/Theme.ts +2 -2
- package/src/internal/Token.ts +13 -1
- package/src/internal/VariableSets.ts +1 -1
- package/src/node/Host.ts +3 -0
- package/src/variable.ts +1 -1
- package/src/vite/index.ts +43 -18
- package/src/web/Css.ts +83 -49
- package/src/web/internal/ClassName.ts +31 -36
- package/src/web/internal/Themes.ts +75 -29
package/src/default.ts
CHANGED
|
@@ -41,11 +41,10 @@ void [spin, ping, pulse, bounce]
|
|
|
41
41
|
*/
|
|
42
42
|
export const tokens = {
|
|
43
43
|
animate: {
|
|
44
|
-
spin: 'z-kid-
|
|
45
|
-
ping: 'z-kid-
|
|
46
|
-
pulse:
|
|
47
|
-
|
|
48
|
-
bounce: 'z-kid-7a-79-7a-7a-2d-62-6f-75-6e-63-65 1s infinite',
|
|
44
|
+
spin: 'z-kid-zyzz_2d_spin 1s linear infinite',
|
|
45
|
+
ping: 'z-kid-zyzz_2d_ping 1s cubic-bezier(0, 0, 0.2, 1) infinite',
|
|
46
|
+
pulse: 'z-kid-zyzz_2d_pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
47
|
+
bounce: 'z-kid-zyzz_2d_bounce 1s infinite',
|
|
49
48
|
},
|
|
50
49
|
aspect: {
|
|
51
50
|
video: '16 / 9',
|
|
@@ -680,13 +679,13 @@ export const tokens = {
|
|
|
680
679
|
/** Default appearance, restoration script, and authoring helpers with bundled light/dark tokens. */
|
|
681
680
|
// Generated from tokens by scripts/default-theme.ts; edit tokens and regenerate.
|
|
682
681
|
const config = Config.create({
|
|
682
|
+
id: 'default',
|
|
683
683
|
vars: {
|
|
684
684
|
animate: {
|
|
685
|
-
spin: 'z-kid-
|
|
686
|
-
ping: 'z-kid-
|
|
687
|
-
pulse:
|
|
688
|
-
|
|
689
|
-
bounce: 'z-kid-7a-79-7a-7a-2d-62-6f-75-6e-63-65 1s infinite',
|
|
685
|
+
spin: 'z-kid-zyzz_2d_spin 1s linear infinite',
|
|
686
|
+
ping: 'z-kid-zyzz_2d_ping 1s cubic-bezier(0, 0, 0.2, 1) infinite',
|
|
687
|
+
pulse: 'z-kid-zyzz_2d_pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
688
|
+
bounce: 'z-kid-zyzz_2d_bounce 1s infinite',
|
|
690
689
|
},
|
|
691
690
|
aspect: {
|
|
692
691
|
video: '16 / 9',
|
|
@@ -3,6 +3,7 @@ import type { style } from '../styleFunction.js'
|
|
|
3
3
|
import * as Html from '../runtime/CompositionHtml.js'
|
|
4
4
|
import * as Identity from './Identity.js'
|
|
5
5
|
import * as Props from '../runtime/Props.js'
|
|
6
|
+
import * as Token from './Token.js'
|
|
6
7
|
import * as Style from '../Style.js'
|
|
7
8
|
import type * as Theme from './Theme.js'
|
|
8
9
|
|
|
@@ -66,10 +67,12 @@ export function create(
|
|
|
66
67
|
options: Options = {},
|
|
67
68
|
): style.ReturnType {
|
|
68
69
|
const dynamic = typeof input === 'function'
|
|
70
|
+
const identity = options.theme?.[Token.definition].contract[Token.identity]
|
|
71
|
+
const namespace = identity?.startsWith('id-') ? identity.slice(3) : undefined
|
|
69
72
|
const id =
|
|
70
73
|
options.id === undefined
|
|
71
74
|
? undefined
|
|
72
|
-
: Identity.requireId(options.id, 'style')
|
|
75
|
+
: `id-${namespace ? `${namespace}-` : ''}${Identity.requireId(options.id, 'style').slice(3)}`
|
|
73
76
|
if (dynamic && !id) Identity.requireId(undefined, 'Dynamic style')
|
|
74
77
|
if (!dynamic && !id && Object.keys(input as object).length === 0)
|
|
75
78
|
Identity.requireId(undefined, 'Empty style')
|
|
@@ -90,6 +93,7 @@ export function create(
|
|
|
90
93
|
{ style: body(input as Record<string, unknown>) },
|
|
91
94
|
{ vars: options.theme },
|
|
92
95
|
).styles[0]!,
|
|
96
|
+
namespace,
|
|
93
97
|
)
|
|
94
98
|
const props = Props.create({ className })
|
|
95
99
|
const apply = (values?: style.Options & Record<string, unknown>) => {
|
|
@@ -128,7 +132,9 @@ export function variants(
|
|
|
128
132
|
input: Record<string, unknown>,
|
|
129
133
|
options: Options = {},
|
|
130
134
|
): unknown {
|
|
131
|
-
const
|
|
135
|
+
const identity = options.theme?.[Token.definition].contract[Token.identity]
|
|
136
|
+
const namespace = identity?.startsWith('id-') ? identity.slice(3) : undefined
|
|
137
|
+
const id = `id-${namespace ? `${namespace}-` : ''}${Identity.requireId(options.id, 'variants').slice(3)}`
|
|
132
138
|
if (options.theme) {
|
|
133
139
|
const styles = [
|
|
134
140
|
input.base,
|
package/src/internal/Binding.ts
CHANGED
|
@@ -15,10 +15,15 @@ export type Kind =
|
|
|
15
15
|
| 'signedLength'
|
|
16
16
|
| 'signedPercentage'
|
|
17
17
|
|
|
18
|
+
/** Marks callback inputs that require an explicit custom token escape. */
|
|
19
|
+
export const dynamic = Symbol('zyzz.binding.dynamic')
|
|
20
|
+
|
|
18
21
|
/** A compiler-assigned web custom property with its scalar domain. */
|
|
19
22
|
export type Reference<kind extends Domain = Domain> = {
|
|
20
23
|
/** Fixed CSS custom-property name. */
|
|
21
24
|
readonly name: `--${string}`
|
|
25
|
+
/** Internal callback provenance, independent of the emitted variable name. */
|
|
26
|
+
readonly [dynamic]?: true | undefined
|
|
22
27
|
/** Scalar domain used by authoring types and runtime primitive checks. */
|
|
23
28
|
readonly type: kind
|
|
24
29
|
/** Distinguishes slots from theme references. */
|
|
@@ -163,6 +163,9 @@ export function create(
|
|
|
163
163
|
)
|
|
164
164
|
throw new InvalidError(`Unknown configuration option: ${key}`)
|
|
165
165
|
|
|
166
|
+
if (input.id !== undefined && (typeof input.id !== 'string' || !input.id))
|
|
167
|
+
throw new InvalidError('id must be a nonempty string.')
|
|
168
|
+
|
|
166
169
|
if (
|
|
167
170
|
input.storageKey !== undefined &&
|
|
168
171
|
(typeof input.storageKey !== 'string' || !input.storageKey)
|
|
@@ -291,7 +294,7 @@ export function create(
|
|
|
291
294
|
function handle(theme: Theme.Definition, name: string) {
|
|
292
295
|
const original = Token.bind(theme, contract)
|
|
293
296
|
const className = () =>
|
|
294
|
-
`
|
|
297
|
+
`z-theme-${Identity.requireId(typeof input.id === 'string' ? input.id : undefined, 'Config.create').slice(3)}-${Identity.name(name)}`
|
|
295
298
|
const select = (options: { colorScheme?: string } = {}) => {
|
|
296
299
|
const scheme = options.colorScheme
|
|
297
300
|
const selection =
|
|
@@ -433,7 +436,7 @@ export function create(
|
|
|
433
436
|
}
|
|
434
437
|
|
|
435
438
|
const theme =
|
|
436
|
-
shorthands || input.defaultLayer !== undefined
|
|
439
|
+
shorthands || input.defaultLayer !== undefined || input.id !== undefined
|
|
437
440
|
? Token.bind(Theme.define({}), contract)
|
|
438
441
|
: undefined
|
|
439
442
|
return finish({
|
|
@@ -452,7 +455,7 @@ export declare namespace create {
|
|
|
452
455
|
readonly cssOutput?: 'atomic' | 'grouped' | undefined
|
|
453
456
|
/** Fallback CSS layer for bound styles and variants; unlayered when omitted. */
|
|
454
457
|
readonly defaultLayer?: string | undefined
|
|
455
|
-
/**
|
|
458
|
+
/** Consumer-owned namespace; required for uncompiled variable configs. */
|
|
456
459
|
readonly id?: string | undefined
|
|
457
460
|
/** Explicit ordered property aliases; none are installed by default. */
|
|
458
461
|
readonly shorthands?: Shorthands.Map | undefined
|
|
@@ -839,7 +842,7 @@ export type VariableOptions = {
|
|
|
839
842
|
readonly defaultLayer?: string | undefined
|
|
840
843
|
/** Required default key when vars contains named sets. */
|
|
841
844
|
readonly defaultVars?: string | undefined
|
|
842
|
-
/**
|
|
845
|
+
/** Consumer-owned namespace; required for uncompiled variable configs. */
|
|
843
846
|
readonly id?: string | undefined
|
|
844
847
|
/** Ordered CSS layer names. */
|
|
845
848
|
readonly layers?: readonly string[] | undefined
|
package/src/internal/Identity.ts
CHANGED
|
@@ -25,13 +25,6 @@ export function compact(value: string): string {
|
|
|
25
25
|
return result
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/** Encodes an explicit identity without losing punctuation or Unicode distinctions. */
|
|
29
|
-
export function encode(value: string): string {
|
|
30
|
-
return Array.from(value, (character) =>
|
|
31
|
-
character.codePointAt(0)!.toString(16),
|
|
32
|
-
).join('-')
|
|
33
|
-
}
|
|
34
|
-
|
|
35
28
|
/** Keeps an authored label readable while its separate hash disambiguates spelling. */
|
|
36
29
|
export function label(value: string): string {
|
|
37
30
|
return (
|
|
@@ -42,18 +35,27 @@ export function label(value: string): string {
|
|
|
42
35
|
)
|
|
43
36
|
}
|
|
44
37
|
|
|
38
|
+
/** Encodes one name segment, reserving hyphens for path boundaries. */
|
|
39
|
+
export function name(value: string): string {
|
|
40
|
+
return Array.from(value, (character) =>
|
|
41
|
+
/^[a-zA-Z0-9]$/.test(character)
|
|
42
|
+
? character
|
|
43
|
+
: `_${character.codePointAt(0)!.toString(16)}_`,
|
|
44
|
+
).join('')
|
|
45
|
+
}
|
|
46
|
+
|
|
45
47
|
/** Requires an explicit identity at an uncompiled authoring boundary. */
|
|
46
48
|
export function requireId(id: string | undefined, kind: string): string {
|
|
47
49
|
if (!id)
|
|
48
50
|
throw new Error(
|
|
49
51
|
`${kind} requires an explicit id without the compiler plugin.`,
|
|
50
52
|
)
|
|
51
|
-
return `id-${
|
|
53
|
+
return `id-${name(id)}`
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
/** Names one callback input independently of its declaration order. */
|
|
55
57
|
export function slot(id: string, field: string): `--${string}` {
|
|
56
|
-
return `--z
|
|
58
|
+
return `--z-${id.startsWith('id-') ? id.slice(3) : id}-${name(field)}`
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
/** Hashes a canonical value using two independent 32-bit accumulators. */
|
|
@@ -69,7 +71,7 @@ export function hash(value: string): string {
|
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
/** Names ordered style data consistently in runtime and extraction. */
|
|
72
|
-
export function style(input: Style.NamedStyle): string {
|
|
74
|
+
export function style(input: Style.NamedStyle, namespace?: string): string {
|
|
73
75
|
function value(input: Style.Declaration['value']): unknown {
|
|
74
76
|
if (Binding.is(input)) return ['variable', input.name]
|
|
75
77
|
if (Token.is(input))
|
|
@@ -105,12 +107,12 @@ export function style(input: Style.NamedStyle): string {
|
|
|
105
107
|
!!declaration.important,
|
|
106
108
|
])
|
|
107
109
|
}
|
|
108
|
-
return `z
|
|
110
|
+
return `z-${namespace ? `${namespace}-` : ''}content-${name(JSON.stringify(shape(input)))}`
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
/** Names a complete ordered composition, including repeated definitions. */
|
|
112
114
|
export function composition(names: readonly string[]): string {
|
|
113
|
-
return `z-compose-${
|
|
115
|
+
return `z-compose-${name(JSON.stringify(names))}`
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
/** Names a stylesheet declaration with a caller-owned identity. */
|
package/src/internal/Theme.ts
CHANGED
|
@@ -599,10 +599,10 @@ function build(
|
|
|
599
599
|
Object.defineProperty(
|
|
600
600
|
{
|
|
601
601
|
get className(): string {
|
|
602
|
-
if (scope) return `
|
|
602
|
+
if (scope) return `z-theme-${scope}`
|
|
603
603
|
const id = contract[Token.identity]
|
|
604
604
|
if (!id?.startsWith('id-')) throw new MissingTransformError()
|
|
605
|
-
return `
|
|
605
|
+
return `z-theme-${id.slice(3)}`
|
|
606
606
|
},
|
|
607
607
|
style: (styles?: unknown, options: style.DefinitionOptions = {}) => {
|
|
608
608
|
if (!contract[Token.identity])
|
package/src/internal/Token.ts
CHANGED
|
@@ -333,6 +333,7 @@ export function acceptsReference(
|
|
|
333
333
|
export function bind<tokens extends Theme.Tokens>(
|
|
334
334
|
original: Theme.Definition<tokens>,
|
|
335
335
|
contract: Contract,
|
|
336
|
+
cssName?: string,
|
|
336
337
|
): Theme.Definition<tokens> {
|
|
337
338
|
type Tree = { [key: string]: Reference | Tree }
|
|
338
339
|
|
|
@@ -371,7 +372,14 @@ export function bind<tokens extends Theme.Tokens>(
|
|
|
371
372
|
vars: variables(tokens),
|
|
372
373
|
},
|
|
373
374
|
definition,
|
|
374
|
-
{
|
|
375
|
+
{
|
|
376
|
+
value: Object.freeze({
|
|
377
|
+
...metadata,
|
|
378
|
+
...(cssName !== undefined ? { cssName } : {}),
|
|
379
|
+
contract,
|
|
380
|
+
values,
|
|
381
|
+
}),
|
|
382
|
+
},
|
|
375
383
|
),
|
|
376
384
|
) as Theme.Definition<tokens>
|
|
377
385
|
}
|
|
@@ -383,6 +391,8 @@ export const complete = Symbol('zyzz.contract.complete')
|
|
|
383
391
|
export type Contract = {
|
|
384
392
|
/** Whether values belong to independent variables rather than fixed theme categories. */
|
|
385
393
|
readonly variableSet?: boolean | undefined
|
|
394
|
+
/** Custom-property spelling retained by older packed producers. */
|
|
395
|
+
readonly variableNaming?: 'legacy' | 'hashed' | undefined
|
|
386
396
|
/** Configuration-local category-to-property mappings. */
|
|
387
397
|
readonly mappings?: VariableSets.Mappings | false | undefined
|
|
388
398
|
/** Web emission mode retained by configuration-bound theme handles. */
|
|
@@ -520,6 +530,8 @@ export function is(value: unknown): value is Reference {
|
|
|
520
530
|
|
|
521
531
|
/** Immutable theme data carried directly by each definition. */
|
|
522
532
|
export type Metadata = {
|
|
533
|
+
/** Authored scope name, independent of private graph ownership. */
|
|
534
|
+
readonly cssName?: string | undefined
|
|
523
535
|
/** Original segments for typography paths containing query punctuation. */
|
|
524
536
|
readonly paths?: Readonly<Record<string, readonly string[]>> | undefined
|
|
525
537
|
readonly queries?: Query.Metadata | undefined
|
|
@@ -33,7 +33,7 @@ export function theme(
|
|
|
33
33
|
get: () => {
|
|
34
34
|
const identity = metadata.contract[Token.identity]
|
|
35
35
|
return identity
|
|
36
|
-
? `
|
|
36
|
+
? `z-theme-${identity.startsWith('id-') ? identity.slice(3) : Identity.name(identity)}`
|
|
37
37
|
: original.className
|
|
38
38
|
},
|
|
39
39
|
enumerable: true,
|
package/src/node/Host.ts
CHANGED
|
@@ -17,6 +17,7 @@ import * as Snapshot from './internal/Snapshot.js'
|
|
|
17
17
|
import * as Syntax from '../compiler/internal/Syntax.js'
|
|
18
18
|
import * as Source from '../compiler/Source.js'
|
|
19
19
|
import * as Transform from '../compiler/Transform.js'
|
|
20
|
+
import * as ThemeRules from '../web/internal/Themes.js'
|
|
20
21
|
|
|
21
22
|
/** A successful publication; paths are relative to the output directory. */
|
|
22
23
|
export type Build = {
|
|
@@ -458,6 +459,8 @@ export async function create(options: create.Options): Promise<Runtime> {
|
|
|
458
459
|
}
|
|
459
460
|
|
|
460
461
|
const graph = compiler.compile({
|
|
462
|
+
[ThemeRules.shared]:
|
|
463
|
+
options.modules === false && !native ? 'all' : undefined,
|
|
461
464
|
[Syntax.cache]: snapshot.programs(modules),
|
|
462
465
|
compiler: options.compiler,
|
|
463
466
|
native,
|
package/src/variable.ts
CHANGED
|
@@ -38,7 +38,7 @@ export function variable(
|
|
|
38
38
|
): unknown {
|
|
39
39
|
const id = typeof kind === 'object' ? kind.id : options?.id
|
|
40
40
|
return Variable.create({
|
|
41
|
-
name: `--z
|
|
41
|
+
name: `--z-${Identity.requireId(id, 'variable').slice(3)}`,
|
|
42
42
|
type: typeof kind === 'string' ? kind : '*',
|
|
43
43
|
variable: true,
|
|
44
44
|
})
|
package/src/vite/index.ts
CHANGED
|
@@ -1391,9 +1391,14 @@ export function zyzz(options: zyzz.Options = {}): Plugin {
|
|
|
1391
1391
|
await updateDiscovery(this.environment, file, change.event)
|
|
1392
1392
|
},
|
|
1393
1393
|
async hotUpdate({ file, modules, timestamp, type, server }) {
|
|
1394
|
-
await updateDiscovery(this.environment, file, type)
|
|
1395
|
-
|
|
1396
1394
|
const state = entries(this.environment)
|
|
1395
|
+
const previous = [...state.values()].map((entry) => ({
|
|
1396
|
+
code: entry.code,
|
|
1397
|
+
file: entry.file,
|
|
1398
|
+
imports: entry.imports,
|
|
1399
|
+
}))
|
|
1400
|
+
|
|
1401
|
+
await updateDiscovery(this.environment, file, type)
|
|
1397
1402
|
const first = [...state.values()].find(
|
|
1398
1403
|
(entry) => entry.files.has(file) || eager(file, this.environment),
|
|
1399
1404
|
)
|
|
@@ -1417,17 +1422,41 @@ export function zyzz(options: zyzz.Options = {}): Plugin {
|
|
|
1417
1422
|
true,
|
|
1418
1423
|
).catch(() => undefined)
|
|
1419
1424
|
: undefined
|
|
1420
|
-
const
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
entry.
|
|
1425
|
+
const javascriptChanged = await (async () => {
|
|
1426
|
+
if (!output) return true
|
|
1427
|
+
|
|
1428
|
+
// Portable build adapters share this module and do not require Vite.
|
|
1429
|
+
const { transformWithOxc } = await import('vite')
|
|
1430
|
+
const changed = await Promise.all(
|
|
1431
|
+
previous.map(async (entry) => {
|
|
1432
|
+
const code = output.modules[sourceId(entry.file)]?.code
|
|
1433
|
+
if (
|
|
1434
|
+
entry.imports !==
|
|
1428
1435
|
JSON.stringify(output.imports[sourceId(entry.file)])
|
|
1429
|
-
|
|
1430
|
-
|
|
1436
|
+
)
|
|
1437
|
+
return true
|
|
1438
|
+
if (entry.code === code) return false
|
|
1439
|
+
if (entry.code === undefined || code === undefined) return true
|
|
1440
|
+
|
|
1441
|
+
// Generated type assertions can change without changing runtime bindings.
|
|
1442
|
+
const [before, after] = await Promise.all([
|
|
1443
|
+
transformWithOxc(entry.code, entry.file, { sourcemap: false }),
|
|
1444
|
+
transformWithOxc(code, entry.file, { sourcemap: false }),
|
|
1445
|
+
])
|
|
1446
|
+
return before.code !== after.code
|
|
1447
|
+
}),
|
|
1448
|
+
)
|
|
1449
|
+
return changed.some(Boolean)
|
|
1450
|
+
})()
|
|
1451
|
+
// Compiler-only inputs have watch edges, but their stylesheets update separately.
|
|
1452
|
+
const affected = new Set(
|
|
1453
|
+
modules.filter(
|
|
1454
|
+
(module) =>
|
|
1455
|
+
javascriptChanged ||
|
|
1456
|
+
(module.id
|
|
1457
|
+
? !output?.modules[sourceId(module.id)]
|
|
1458
|
+
: module.type !== 'asset'),
|
|
1459
|
+
),
|
|
1431
1460
|
)
|
|
1432
1461
|
const ids = new Set<string>()
|
|
1433
1462
|
if (type === 'delete') ids.add(cssId(file))
|
|
@@ -1436,12 +1465,8 @@ export function zyzz(options: zyzz.Options = {}): Plugin {
|
|
|
1436
1465
|
if (!entry.files.has(file) && !eager(file, this.environment)) continue
|
|
1437
1466
|
|
|
1438
1467
|
// Theme scopes affect CSS even when Vite's JavaScript import was erased.
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
entry.code !== output.modules[sourceId(entry.file)]?.code ||
|
|
1442
|
-
entry.imports !== JSON.stringify(output.imports[sourceId(entry.file)])
|
|
1443
|
-
)
|
|
1444
|
-
ids.add(entry.file)
|
|
1468
|
+
// Rewritten importers can lose a source edge, so changed bindings must update together.
|
|
1469
|
+
if (javascriptChanged) ids.add(entry.file)
|
|
1445
1470
|
ids.add(cssId(entry.file))
|
|
1446
1471
|
ids.add(sharedId)
|
|
1447
1472
|
}
|
package/src/web/Css.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as Targets from '../internal/Targets.js'
|
|
6
6
|
import * as ClassName from './internal/ClassName.js'
|
|
7
|
+
import * as Identity from '../internal/Identity.js'
|
|
7
8
|
import * as Contributions from './internal/Contributions.js'
|
|
8
9
|
import * as Binding from '../internal/Binding.js'
|
|
9
10
|
import * as Cascade from '../internal/Cascade.js'
|
|
@@ -33,6 +34,7 @@ export function compile<
|
|
|
33
34
|
>(
|
|
34
35
|
options: compile.Options<name, themeName>,
|
|
35
36
|
): compile.ReturnType<name, themeName> {
|
|
37
|
+
const labels = options[ClassName.labels] ?? options.styles[ClassName.labels]
|
|
36
38
|
options = {
|
|
37
39
|
...options,
|
|
38
40
|
styles: { styles: options.styles.styles.map(Targets.web) },
|
|
@@ -417,6 +419,8 @@ export function compile<
|
|
|
417
419
|
|
|
418
420
|
const identities = new Map<string, string>()
|
|
419
421
|
const rules = new Map<string, string>()
|
|
422
|
+
type ConditionalRule = { conditions: readonly string[]; value: string }
|
|
423
|
+
const conditionalRules = new Map<string, ConditionalRule>()
|
|
420
424
|
const identical = new Map<string, string>()
|
|
421
425
|
const explicitBodies = new Map<string, string>()
|
|
422
426
|
const selectors = new Map<string, string>()
|
|
@@ -470,12 +474,18 @@ export function compile<
|
|
|
470
474
|
|
|
471
475
|
const names: string[] = explicit === undefined ? [] : [explicit]
|
|
472
476
|
let ordinal = 0
|
|
473
|
-
const
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
function emit(
|
|
477
|
+
const cssName = labels?.[style.name]?.name ?? encode(style.name)
|
|
478
|
+
const cssNamespace =
|
|
479
|
+
labels?.[style.name]?.namespace ??
|
|
480
|
+
(options.scope ? Identity.name(options.scope) : undefined)
|
|
481
|
+
|
|
482
|
+
function emit(
|
|
483
|
+
body: string,
|
|
484
|
+
label: string,
|
|
485
|
+
shared: boolean,
|
|
486
|
+
output = mode,
|
|
487
|
+
conditional?: ConditionalRule,
|
|
488
|
+
) {
|
|
479
489
|
if (!body) return
|
|
480
490
|
|
|
481
491
|
const independent =
|
|
@@ -483,12 +493,8 @@ export function compile<
|
|
|
483
493
|
!options.development &&
|
|
484
494
|
output === mode &&
|
|
485
495
|
options.composition === 'independent'
|
|
486
|
-
const key =
|
|
487
|
-
|
|
488
|
-
const reusable =
|
|
489
|
-
explicit === undefined &&
|
|
490
|
-
!options.development &&
|
|
491
|
-
(shared || independent)
|
|
496
|
+
const key = JSON.stringify([cssNamespace, output, body])
|
|
497
|
+
const reusable = explicit === undefined && (shared || independent)
|
|
492
498
|
const previous = reusable ? identical.get(key) : undefined
|
|
493
499
|
if (previous && !names.includes(previous)) {
|
|
494
500
|
names.push(previous)
|
|
@@ -498,43 +504,23 @@ export function compile<
|
|
|
498
504
|
if (previous) shared = false
|
|
499
505
|
|
|
500
506
|
// Contextual slots preserve authored ordering; development names survive value edits.
|
|
501
|
-
const
|
|
502
|
-
const slot = options.development ? (slots.get(label) ?? 0) : ordinalSlot
|
|
503
|
-
slots.set(label, slot + 1)
|
|
507
|
+
const slot = ordinal++
|
|
504
508
|
const identity = (() => {
|
|
505
509
|
if (explicit !== undefined)
|
|
506
510
|
return `${explicit}-${mode}-${encode(label)}-${slot}`
|
|
507
|
-
if (
|
|
508
|
-
output === 'grouped' &&
|
|
509
|
-
mode === 'grouped' &&
|
|
510
|
-
!options.development &&
|
|
511
|
-
options.composition === 'independent'
|
|
512
|
-
)
|
|
513
|
-
return `g_${rules.size.toString(36)}`
|
|
514
511
|
if (output === 'grouped' && mode === 'grouped') {
|
|
515
|
-
|
|
516
|
-
const scope =
|
|
517
|
-
options.development && options.scope
|
|
518
|
-
? `_m${encode(options.scope)}`
|
|
519
|
-
: ''
|
|
520
|
-
return `g-${encode(name)}${scope}${slot ? `_s${slot}` : ''}`
|
|
512
|
+
return `z-${cssNamespace ? `${cssNamespace}-` : ''}${cssName}${slot ? `__${slot}` : ''}`
|
|
521
513
|
}
|
|
522
514
|
return ClassName.create({
|
|
523
515
|
body,
|
|
524
|
-
context:
|
|
525
|
-
|
|
526
|
-
? JSON.stringify([
|
|
527
|
-
options.scope,
|
|
528
|
-
mode,
|
|
529
|
-
options.development ? developmentName : style.name,
|
|
530
|
-
])
|
|
531
|
-
: options.scope,
|
|
516
|
+
context: !shared ? cssName : undefined,
|
|
517
|
+
namespace: cssNamespace,
|
|
532
518
|
property: label,
|
|
533
|
-
slot: !shared
|
|
534
|
-
stable: options.development,
|
|
519
|
+
slot: !shared ? slot : undefined,
|
|
535
520
|
})
|
|
536
521
|
})()
|
|
537
|
-
const owner =
|
|
522
|
+
const owner =
|
|
523
|
+
mode === 'atomic' && !shared ? `${style.name}:${slot}` : undefined
|
|
538
524
|
if (
|
|
539
525
|
(rules.has(identity) && rules.get(identity) !== body) ||
|
|
540
526
|
(owner !== undefined &&
|
|
@@ -543,12 +529,19 @@ export function compile<
|
|
|
543
529
|
)
|
|
544
530
|
diagnostics.push({
|
|
545
531
|
code: 'identity_collision',
|
|
546
|
-
message:
|
|
532
|
+
message:
|
|
533
|
+
'Generated class names conflict. Supply distinct config or style ids.',
|
|
547
534
|
path: [style.name],
|
|
548
535
|
})
|
|
549
536
|
|
|
550
537
|
if (owner !== undefined) identities.set(identity, owner)
|
|
551
538
|
rules.set(identity, body)
|
|
539
|
+
if (
|
|
540
|
+
conditional?.conditions.some((condition) =>
|
|
541
|
+
/^@(media|supports)\b/.test(condition),
|
|
542
|
+
)
|
|
543
|
+
)
|
|
544
|
+
conditionalRules.set(identity, conditional)
|
|
552
545
|
if (explicit !== undefined) selectors.set(identity, explicit)
|
|
553
546
|
else {
|
|
554
547
|
if (reusable) identical.set(key, identity)
|
|
@@ -611,7 +604,7 @@ export function compile<
|
|
|
611
604
|
!nestedComposition &&
|
|
612
605
|
!conditions.length &&
|
|
613
606
|
groups.get(conflict(property)) !== false
|
|
614
|
-
emit(body, property, shared)
|
|
607
|
+
emit(body, property, shared, mode, { conditions, value })
|
|
615
608
|
}
|
|
616
609
|
}
|
|
617
610
|
|
|
@@ -673,7 +666,7 @@ export function compile<
|
|
|
673
666
|
options.schemes ?? false,
|
|
674
667
|
options[Themes.shared],
|
|
675
668
|
)
|
|
676
|
-
: { classes: Object.freeze({}), css: '', resources: [] }
|
|
669
|
+
: { classes: Object.freeze({}), css: '', resources: [], rules: [] }
|
|
677
670
|
} catch (error) {
|
|
678
671
|
throw new CompileError([
|
|
679
672
|
{
|
|
@@ -686,20 +679,57 @@ export function compile<
|
|
|
686
679
|
|
|
687
680
|
const scopedCss = [
|
|
688
681
|
scopes.css,
|
|
689
|
-
...[...rules].map(
|
|
690
|
-
|
|
691
|
-
|
|
682
|
+
...[...rules].map((entry) => {
|
|
683
|
+
const [name, body] = entry
|
|
684
|
+
const selector = `.${ClassName.selector(selectors.get(name) ?? name)}`
|
|
685
|
+
const conditional = conditionalRules.get(name)
|
|
686
|
+
if (
|
|
687
|
+
!conditional ||
|
|
688
|
+
conditional.conditions.some(
|
|
689
|
+
(condition) =>
|
|
690
|
+
condition.startsWith('@') &&
|
|
691
|
+
!/^@(media|supports)\b/.test(condition),
|
|
692
|
+
)
|
|
693
|
+
)
|
|
694
|
+
return `${selector}{${body}}`
|
|
695
|
+
|
|
696
|
+
// Inactive conditions must surround the class rather than leave a matched empty wrapper.
|
|
697
|
+
const conditions = conditional.conditions.filter((condition) =>
|
|
698
|
+
condition.startsWith('@'),
|
|
699
|
+
)
|
|
700
|
+
const nested = conditional.conditions
|
|
701
|
+
.filter((condition) => !condition.startsWith('@'))
|
|
702
|
+
.reduceRight(
|
|
703
|
+
(body, condition) => `${condition}{${body}}`,
|
|
704
|
+
conditional.value,
|
|
705
|
+
)
|
|
706
|
+
return conditions.reduceRight(
|
|
707
|
+
(body, condition) => `${condition}{${body}}`,
|
|
708
|
+
`${selector}{${nested}}`,
|
|
709
|
+
)
|
|
710
|
+
}),
|
|
692
711
|
]
|
|
693
712
|
.filter(Boolean)
|
|
694
713
|
.join('\n')
|
|
695
714
|
|
|
696
|
-
|
|
715
|
+
const result = {
|
|
697
716
|
...(scopes.resources.length ? { [Themes.shared]: scopes.resources } : {}),
|
|
698
717
|
...(contributionCss ? { contributionCss, scopedCss } : {}),
|
|
718
|
+
[ClassName.rules]: Object.freeze({
|
|
719
|
+
...Object.fromEntries(rules),
|
|
720
|
+
...Object.fromEntries(
|
|
721
|
+
scopes.rules.map((rule) => [
|
|
722
|
+
`@scope:${rule.selector.slice(1)}:${Identity.name(rule.property)}:${Identity.name(JSON.stringify(rule.conditions))}`,
|
|
723
|
+
rule.value,
|
|
724
|
+
]),
|
|
725
|
+
),
|
|
726
|
+
}),
|
|
699
727
|
classes: Object.freeze(classes),
|
|
700
728
|
css: [contributionCss, scopedCss].filter(Boolean).join('\n'),
|
|
701
729
|
vars: scopes.classes as Readonly<Record<themeName, string>>,
|
|
702
|
-
}
|
|
730
|
+
}
|
|
731
|
+
Object.defineProperty(result, ClassName.rules, { enumerable: false })
|
|
732
|
+
return Object.freeze(result)
|
|
703
733
|
}
|
|
704
734
|
|
|
705
735
|
/** Input and output contracts for literal compilation. */
|
|
@@ -714,6 +744,8 @@ export declare namespace compile {
|
|
|
714
744
|
> = {
|
|
715
745
|
/** Separates generated token rules for hosts with independent CSS resources. */
|
|
716
746
|
readonly [Themes.shared]?: 'all' | 'defaults' | undefined
|
|
747
|
+
/** Readable source bindings and consumer-owned configuration namespaces. */
|
|
748
|
+
readonly [ClassName.labels]?: ClassName.Labels | undefined
|
|
717
749
|
/** Fixed class identities used by CSS-only consumers. */
|
|
718
750
|
readonly names?: Readonly<Record<string, string>> | undefined
|
|
719
751
|
/**
|
|
@@ -726,14 +758,14 @@ export declare namespace compile {
|
|
|
726
758
|
/** CSS representation; atomic declarations are the default. */
|
|
727
759
|
readonly cssOutput?: 'atomic' | 'grouped' | undefined
|
|
728
760
|
readonly composition?: 'independent' | 'ordered' | undefined
|
|
729
|
-
/**
|
|
761
|
+
/** Retains live definitions for development updates. */
|
|
730
762
|
readonly development?: boolean | undefined
|
|
731
763
|
/**
|
|
732
764
|
* Emit the `color-scheme` selection classes. Set by modules whose runtime
|
|
733
765
|
* helpers can apply a scheme, so lowered `light-dark()` resolves there.
|
|
734
766
|
*/
|
|
735
767
|
readonly schemes?: boolean | undefined
|
|
736
|
-
/**
|
|
768
|
+
/** Explicit consumer-owned namespace for independently delivered stylesheets. */
|
|
737
769
|
readonly scope?: string | undefined
|
|
738
770
|
/** Ordered definitions; no themes or source adapter is required. */
|
|
739
771
|
readonly styles: Style.Definition<name>
|
|
@@ -748,6 +780,8 @@ export declare namespace compile {
|
|
|
748
780
|
name extends string = string,
|
|
749
781
|
themeName extends string = string,
|
|
750
782
|
> = {
|
|
783
|
+
/** Exact emitted rule bodies retained for graph-wide collision diagnostics. */
|
|
784
|
+
readonly [ClassName.rules]: Readonly<Record<string, string>>
|
|
751
785
|
/** Shared token resources omitted from this module's stylesheet. */
|
|
752
786
|
readonly [Themes.shared]?: readonly Themes.Resource[] | undefined
|
|
753
787
|
/** Contribution text separated for graph-wide hoisting. */
|