zyzz 0.0.21 → 0.0.23
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/Zyzz.podspec +16 -0
- package/dist/Style.d.ts +3 -1
- package/dist/Style.d.ts.map +1 -1
- package/dist/Style.js.map +1 -1
- package/dist/babel/NativeJsx.d.ts.map +1 -1
- package/dist/babel/NativeJsx.js +217 -15
- package/dist/babel/NativeJsx.js.map +1 -1
- package/dist/babel/index.d.ts +6 -2
- package/dist/babel/index.d.ts.map +1 -1
- package/dist/babel/index.js +10 -1
- package/dist/babel/index.js.map +1 -1
- package/dist/compiler/Graph.d.ts.map +1 -1
- package/dist/compiler/Graph.js +107 -0
- package/dist/compiler/Graph.js.map +1 -1
- package/dist/compiler/Native.d.ts +6 -3
- package/dist/compiler/Native.d.ts.map +1 -1
- package/dist/compiler/Native.js +142 -24
- package/dist/compiler/Native.js.map +1 -1
- package/dist/compiler/Source.d.ts +2 -0
- package/dist/compiler/Source.d.ts.map +1 -1
- package/dist/compiler/Source.js +17 -5
- package/dist/compiler/Source.js.map +1 -1
- package/dist/compiler/internal/Configurations.d.ts +2 -0
- package/dist/compiler/internal/Configurations.d.ts.map +1 -1
- package/dist/compiler/internal/Configurations.js +21 -3
- package/dist/compiler/internal/Configurations.js.map +1 -1
- package/dist/compiler/internal/Contract.d.ts.map +1 -1
- package/dist/compiler/internal/Contract.js +75 -38
- 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 +7 -1
- package/dist/compiler/internal/Contributions.js.map +1 -1
- package/dist/compiler/internal/Descriptors.d.ts.map +1 -1
- package/dist/compiler/internal/Descriptors.js +11 -2
- package/dist/compiler/internal/Descriptors.js.map +1 -1
- package/dist/compiler/internal/Dynamic.d.ts.map +1 -1
- package/dist/compiler/internal/Dynamic.js +3 -0
- package/dist/compiler/internal/Dynamic.js.map +1 -1
- package/dist/compiler/internal/Expression.js +2 -2
- package/dist/compiler/internal/Expression.js.map +1 -1
- package/dist/compiler/internal/NativeBindings.d.ts +24 -26
- package/dist/compiler/internal/NativeBindings.d.ts.map +1 -1
- package/dist/compiler/internal/NativeBindings.js +62 -8
- package/dist/compiler/internal/NativeBindings.js.map +1 -1
- package/dist/compiler/internal/NativeMedia.d.ts +14 -0
- package/dist/compiler/internal/NativeMedia.d.ts.map +1 -0
- package/dist/compiler/internal/NativeMedia.js +287 -0
- package/dist/compiler/internal/NativeMedia.js.map +1 -0
- package/dist/compiler/internal/NativeVars.d.ts +28 -0
- package/dist/compiler/internal/NativeVars.d.ts.map +1 -0
- package/dist/compiler/internal/NativeVars.js +160 -0
- package/dist/compiler/internal/NativeVars.js.map +1 -0
- package/dist/compiler/internal/PackedStyles.d.ts +2 -0
- package/dist/compiler/internal/PackedStyles.d.ts.map +1 -1
- package/dist/compiler/internal/PackedStyles.js +2 -0
- package/dist/compiler/internal/PackedStyles.js.map +1 -1
- package/dist/compiler/internal/Themes.d.ts +24 -1
- package/dist/compiler/internal/Themes.d.ts.map +1 -1
- package/dist/compiler/internal/Themes.js +120 -3
- package/dist/compiler/internal/Themes.js.map +1 -1
- package/dist/compiler/internal/Vars.d.ts +1 -1
- package/dist/compiler/internal/Vars.d.ts.map +1 -1
- package/dist/compiler/internal/Vars.js +7 -2
- package/dist/compiler/internal/Vars.js.map +1 -1
- package/dist/default.js.zyzz.json +1 -1
- package/dist/internal/Completion.d.ts +1 -1
- package/dist/internal/Completion.d.ts.map +1 -1
- package/dist/internal/Targets.d.ts.map +1 -1
- package/dist/internal/Targets.js +2 -0
- package/dist/internal/Targets.js.map +1 -1
- package/dist/internal/Token.d.ts +0 -2
- package/dist/internal/Token.d.ts.map +1 -1
- package/dist/internal/Token.js.map +1 -1
- package/dist/internal/Value.d.ts +7 -0
- package/dist/internal/Value.d.ts.map +1 -1
- package/dist/internal/Value.js.map +1 -1
- package/dist/metro/Graph.d.ts +22 -7
- package/dist/metro/Graph.d.ts.map +1 -1
- package/dist/metro/Graph.js +188 -42
- package/dist/metro/Graph.js.map +1 -1
- package/dist/metro/Watch.d.ts +28 -4
- package/dist/metro/Watch.d.ts.map +1 -1
- package/dist/metro/Watch.js +39 -7
- package/dist/metro/Watch.js.map +1 -1
- package/dist/metro/index.d.ts +15 -4
- package/dist/metro/index.d.ts.map +1 -1
- package/dist/metro/index.js +27 -0
- package/dist/metro/index.js.map +1 -1
- package/dist/metro/transformer.d.ts +5 -1
- package/dist/metro/transformer.d.ts.map +1 -1
- package/dist/metro/transformer.js +5 -3
- package/dist/metro/transformer.js.map +1 -1
- package/dist/react-native/StyleSheet.d.ts +8 -3
- package/dist/react-native/StyleSheet.d.ts.map +1 -1
- package/dist/react-native/StyleSheet.js +25 -34
- package/dist/react-native/StyleSheet.js.map +1 -1
- package/dist/react-native/index.d.ts +1 -1
- package/dist/react-native/index.d.ts.map +1 -1
- package/dist/react-native/index.js +1 -1
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native/index.native.d.ts +5 -0
- package/dist/react-native/index.native.js +20 -0
- package/dist/react-native/index.native.js.map +7 -0
- package/dist/react-native/internal/Calculation.d.ts +7 -0
- package/dist/react-native/internal/Calculation.d.ts.map +1 -0
- package/dist/react-native/internal/Calculation.js +134 -0
- package/dist/react-native/internal/Calculation.js.map +1 -0
- package/dist/react-native/internal/Device.js +218 -0
- package/dist/react-native/internal/Device.js.map +7 -0
- package/dist/react-native/internal/NativeZyzz.js +7 -0
- package/dist/react-native/internal/NativeZyzz.js.map +7 -0
- package/dist/react-native/internal/Scalar.d.ts +16 -0
- package/dist/react-native/internal/Scalar.d.ts.map +1 -1
- package/dist/react-native/internal/Scalar.js +62 -4
- package/dist/react-native/internal/Scalar.js.map +1 -1
- package/dist/react-native/internal/Store.d.ts +32 -0
- package/dist/react-native/internal/Store.d.ts.map +1 -0
- package/dist/react-native/internal/Store.js +57 -0
- package/dist/react-native/internal/Store.js.map +1 -0
- package/dist/react-native/internal/Styles.d.ts +19 -0
- package/dist/react-native/internal/Styles.d.ts.map +1 -0
- package/dist/react-native/internal/Styles.js +35 -0
- package/dist/react-native/internal/Styles.js.map +1 -0
- package/dist/react-native/internal/Tokens.d.ts +21 -0
- package/dist/react-native/internal/Tokens.d.ts.map +1 -0
- package/dist/react-native/internal/Tokens.js +58 -0
- package/dist/react-native/internal/Tokens.js.map +1 -0
- package/dist/react-native/internal/Viewport.d.ts +6 -0
- package/dist/react-native/internal/Viewport.d.ts.map +1 -0
- package/dist/react-native/internal/Viewport.js +4 -0
- package/dist/react-native/internal/Viewport.js.map +1 -0
- package/dist/react-native/react.d.ts +102 -14
- package/dist/react-native/react.d.ts.map +1 -1
- package/dist/react-native/react.js +86 -18
- package/dist/react-native/react.js.map +1 -1
- package/dist/react-native/reanimated.d.ts +39 -0
- package/dist/react-native/reanimated.d.ts.map +1 -0
- package/dist/react-native/reanimated.js +76 -0
- package/dist/react-native/reanimated.js.map +1 -0
- package/dist/runtime/NativeContext.d.ts +10 -1
- package/dist/runtime/NativeContext.d.ts.map +1 -1
- package/dist/runtime/NativeContext.js +67 -14
- package/dist/runtime/NativeContext.js.map +1 -1
- package/dist/runtime/NativeDynamic.d.ts +3 -2
- package/dist/runtime/NativeDynamic.d.ts.map +1 -1
- package/dist/runtime/NativeDynamic.js +37 -7
- package/dist/runtime/NativeDynamic.js.map +1 -1
- package/dist/runtime/NativeStatic.d.ts +23 -0
- package/dist/runtime/NativeStatic.d.ts.map +1 -0
- package/dist/runtime/NativeStatic.js +106 -0
- package/dist/runtime/NativeStatic.js.map +1 -0
- package/dist/runtime/NativeVars.d.ts +53 -0
- package/dist/runtime/NativeVars.d.ts.map +1 -0
- package/dist/runtime/NativeVars.js +77 -0
- package/dist/runtime/NativeVars.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/internal/NativeMedia.d.ts +25 -0
- package/dist/runtime/internal/NativeMedia.d.ts.map +1 -0
- package/dist/runtime/internal/NativeMedia.js +36 -0
- package/dist/runtime/internal/NativeMedia.js.map +1 -0
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +7 -35
- package/dist/vite/index.js.map +1 -1
- package/dist/web/Css.d.ts.map +1 -1
- package/dist/web/Css.js +31 -19
- package/dist/web/Css.js.map +1 -1
- package/dist/web/internal/Themes.d.ts +0 -2
- package/dist/web/internal/Themes.d.ts.map +1 -1
- package/dist/web/internal/Themes.js +30 -28
- package/dist/web/internal/Themes.js.map +1 -1
- package/dist/web/page.d.ts +2 -0
- package/dist/web/page.d.ts.map +1 -1
- package/native/NativeZyzz.cpp +215 -0
- package/native/NativeZyzz.h +52 -0
- package/native/ZyzzSpecJSI.h +65 -0
- package/native/android/CMakeLists.txt +8 -0
- package/native/android/ZyzzSpec-generated.cpp +50 -0
- package/native/android/ZyzzSpec.h +31 -0
- package/native/ios/ZyzzModuleProvider.mm +13 -0
- package/package.json +39 -1
- package/react-native.config.ts +14 -0
- package/src/Style.ts +11 -8
- package/src/babel/NativeJsx.ts +319 -33
- package/src/babel/index.ts +21 -3
- package/src/compiler/Graph.ts +126 -0
- package/src/compiler/Native.ts +158 -26
- package/src/compiler/Source.ts +32 -5
- package/src/compiler/internal/Configurations.ts +25 -3
- package/src/compiler/internal/Contract.ts +98 -50
- package/src/compiler/internal/Contributions.ts +7 -1
- package/src/compiler/internal/Descriptors.ts +12 -8
- package/src/compiler/internal/Dynamic.ts +4 -0
- package/src/compiler/internal/Expression.ts +2 -2
- package/src/compiler/internal/NativeBindings.ts +99 -15
- package/src/compiler/internal/NativeMedia.ts +342 -0
- package/src/compiler/internal/NativeVars.ts +231 -0
- package/src/compiler/internal/PackedStyles.ts +4 -0
- package/src/compiler/internal/Themes.ts +193 -2
- package/src/compiler/internal/Vars.ts +12 -1
- package/src/internal/Completion.ts +6 -3
- package/src/internal/Targets.ts +2 -0
- package/src/internal/Token.ts +0 -2
- package/src/internal/Value.ts +20 -0
- package/src/metro/Graph.ts +250 -50
- package/src/metro/Watch.ts +95 -10
- package/src/metro/index.ts +62 -4
- package/src/metro/transformer.ts +21 -11
- package/src/react-native/StyleSheet.ts +56 -49
- package/src/react-native/index.native.ts +10 -0
- package/src/react-native/index.ts +1 -1
- package/src/react-native/internal/Calculation.ts +159 -0
- package/src/react-native/internal/Device.ts +297 -0
- package/src/react-native/internal/NativeZyzz.ts +20 -0
- package/src/react-native/internal/Scalar.ts +86 -4
- package/src/react-native/internal/Store.ts +78 -0
- package/src/react-native/internal/Styles.ts +77 -0
- package/src/react-native/internal/Tokens.ts +85 -0
- package/src/react-native/internal/Viewport.ts +8 -0
- package/src/react-native/react.ts +218 -26
- package/src/react-native/reanimated.ts +162 -0
- package/src/runtime/NativeContext.ts +88 -17
- package/src/runtime/NativeDynamic.ts +42 -10
- package/src/runtime/NativeStatic.ts +145 -0
- package/src/runtime/NativeVars.ts +189 -0
- package/src/runtime/index.ts +6 -0
- package/src/runtime/internal/NativeMedia.ts +63 -0
- package/src/vite/index.ts +9 -42
- package/src/web/Css.ts +42 -27
- package/src/web/internal/Themes.ts +34 -57
- package/src/web/page.ts +2 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/** Selects immutable native variable tables emitted by the compiler. @module */
|
|
2
|
+
import type * as Literal from '../internal/Literal.js'
|
|
3
|
+
import * as Media from './internal/NativeMedia.js'
|
|
4
|
+
import type * as StyleSheet from '../react-native/StyleSheet.js'
|
|
5
|
+
import type * as Vars from '../Vars.js'
|
|
6
|
+
|
|
7
|
+
const binding = Symbol('zyzz.native.vars')
|
|
8
|
+
|
|
9
|
+
/** Static values with deferred diagnostics for unsupported native leaves. */
|
|
10
|
+
export type EncodedTree = {
|
|
11
|
+
readonly [key: string]: string | number | EncodedTree | readonly [string]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Resolves portable reference domains to readonly native value types. */
|
|
15
|
+
export type Values<
|
|
16
|
+
values,
|
|
17
|
+
category = undefined,
|
|
18
|
+
root extends boolean = true,
|
|
19
|
+
> = {
|
|
20
|
+
readonly [key in Exclude<
|
|
21
|
+
keyof values,
|
|
22
|
+
root extends true ? 'breakpoint' | 'containerNames' : never
|
|
23
|
+
>]: values[key] extends Vars.Value
|
|
24
|
+
? category extends 'fontWeight'
|
|
25
|
+
? Exclude<StyleSheet.NativeStyle['fontWeight'], undefined>
|
|
26
|
+
: category extends 'typography'
|
|
27
|
+
? key extends 'fontWeight'
|
|
28
|
+
? Exclude<StyleSheet.NativeStyle['fontWeight'], undefined>
|
|
29
|
+
: key extends 'lineHeight'
|
|
30
|
+
? number
|
|
31
|
+
: Scalar<Vars.Scalar<values[key]>>
|
|
32
|
+
: Scalar<Vars.Scalar<values[key]>>
|
|
33
|
+
: Values<values[key], root extends true ? key : category, false>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Native scalar values nested under their authored variable paths. */
|
|
37
|
+
export type Tree = { readonly [key: string]: string | number | Tree }
|
|
38
|
+
|
|
39
|
+
type Scalar<value> = value extends number | Literal.Length ? number : string
|
|
40
|
+
|
|
41
|
+
type Definition = {
|
|
42
|
+
readonly defaultVars: string
|
|
43
|
+
readonly media?:
|
|
44
|
+
| {
|
|
45
|
+
readonly profiles: Readonly<Record<string, Definition['profiles']>>
|
|
46
|
+
readonly queries: readonly Media.Query[]
|
|
47
|
+
}
|
|
48
|
+
| undefined
|
|
49
|
+
readonly profiles: Readonly<
|
|
50
|
+
Record<string, Readonly<Record<'dark' | 'light', Tree>>>
|
|
51
|
+
>
|
|
52
|
+
readonly unnamed: boolean
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Copies and shares equal branches across the compiled profiles. */
|
|
56
|
+
export function create(options: create.Options): object {
|
|
57
|
+
const shared = new Map<string, Tree>()
|
|
58
|
+
|
|
59
|
+
function freeze(tree: EncodedTree): Tree {
|
|
60
|
+
const key = JSON.stringify(tree)
|
|
61
|
+
const previous = shared.get(key)
|
|
62
|
+
if (previous) return previous
|
|
63
|
+
|
|
64
|
+
const value: Tree = {}
|
|
65
|
+
for (const [name, entry] of Object.entries(tree)) {
|
|
66
|
+
const diagnostic = Array.isArray(entry) ? String(entry[0]) : undefined
|
|
67
|
+
Object.defineProperty(
|
|
68
|
+
value,
|
|
69
|
+
name,
|
|
70
|
+
diagnostic !== undefined
|
|
71
|
+
? {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
get() {
|
|
74
|
+
throw new Error(diagnostic)
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
: {
|
|
78
|
+
enumerable: true,
|
|
79
|
+
value:
|
|
80
|
+
typeof entry === 'object'
|
|
81
|
+
? freeze(entry as EncodedTree)
|
|
82
|
+
: entry,
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
Object.freeze(value)
|
|
87
|
+
shared.set(key, value)
|
|
88
|
+
return value
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function profiles(value: create.Options['profiles']): Definition['profiles'] {
|
|
92
|
+
return Object.freeze(
|
|
93
|
+
Object.fromEntries(
|
|
94
|
+
Object.entries(value).map(([name, schemes]) => [
|
|
95
|
+
name,
|
|
96
|
+
Object.freeze({
|
|
97
|
+
dark: freeze(schemes.dark),
|
|
98
|
+
light: freeze(schemes.light),
|
|
99
|
+
}),
|
|
100
|
+
]),
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return Object.freeze({
|
|
106
|
+
[binding]: Object.freeze({
|
|
107
|
+
defaultVars: options.defaultVars,
|
|
108
|
+
...(options.media
|
|
109
|
+
? {
|
|
110
|
+
media: Object.freeze({
|
|
111
|
+
profiles: Object.freeze(
|
|
112
|
+
Object.fromEntries(
|
|
113
|
+
Object.entries(options.media.profiles).map(([key, value]) => [
|
|
114
|
+
key,
|
|
115
|
+
profiles(value),
|
|
116
|
+
]),
|
|
117
|
+
),
|
|
118
|
+
),
|
|
119
|
+
queries: options.media.queries,
|
|
120
|
+
}),
|
|
121
|
+
}
|
|
122
|
+
: {}),
|
|
123
|
+
profiles: profiles(options.profiles),
|
|
124
|
+
unnamed: options.unnamed,
|
|
125
|
+
}),
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Compiler-generated native profiles. */
|
|
130
|
+
export declare namespace create {
|
|
131
|
+
/** Static tables and the owning configuration's default name. */
|
|
132
|
+
type Options = {
|
|
133
|
+
/** Fallback when the Provider omits its selection. */
|
|
134
|
+
readonly defaultVars: string
|
|
135
|
+
/** Precompiled alternatives for supported window queries. */
|
|
136
|
+
readonly media?:
|
|
137
|
+
| {
|
|
138
|
+
readonly profiles: Readonly<Record<string, Options['profiles']>>
|
|
139
|
+
readonly queries: readonly Media.Query[]
|
|
140
|
+
}
|
|
141
|
+
| undefined
|
|
142
|
+
/** Native values for every configured name and scheme. */
|
|
143
|
+
readonly profiles: Readonly<
|
|
144
|
+
Record<string, Readonly<Record<'dark' | 'light', EncodedTree>>>
|
|
145
|
+
>
|
|
146
|
+
/** A standalone definition whose values do not depend on the selected name. */
|
|
147
|
+
readonly unnamed: boolean
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Reads a compiled profile without evaluating authoring or accessing device state. */
|
|
152
|
+
export function read(value: object, selection: read.Options): Tree {
|
|
153
|
+
if (
|
|
154
|
+
!value ||
|
|
155
|
+
(typeof value !== 'object' && typeof value !== 'function') ||
|
|
156
|
+
!Object.hasOwn(value, binding)
|
|
157
|
+
)
|
|
158
|
+
throw new Error(
|
|
159
|
+
'useVars requires variables compiled by the native adapter.',
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
const definition = (value as { readonly [binding]: Definition })[binding]
|
|
163
|
+
const profiles =
|
|
164
|
+
definition.media && selection.viewport
|
|
165
|
+
? definition.media.profiles[
|
|
166
|
+
Media.select(definition.media.queries, selection.viewport)
|
|
167
|
+
]!
|
|
168
|
+
: definition.profiles
|
|
169
|
+
const name = selection.set ?? definition.defaultVars
|
|
170
|
+
const profile =
|
|
171
|
+
(Object.hasOwn(profiles, name) ? profiles[name] : undefined) ??
|
|
172
|
+
(definition.unnamed ? profiles.default : undefined)
|
|
173
|
+
if (!profile) throw new Error(`Unknown native vars: ${name}.`)
|
|
174
|
+
|
|
175
|
+
return profile[selection.colorScheme]
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Selection supplied by the nearest native Provider. */
|
|
179
|
+
export declare namespace read {
|
|
180
|
+
/** Resolved appearance and an optional variable name. */
|
|
181
|
+
type Options = {
|
|
182
|
+
/** Resolved native color scheme. */
|
|
183
|
+
readonly colorScheme: 'dark' | 'light'
|
|
184
|
+
/** Selected name, or the configuration default when omitted. */
|
|
185
|
+
readonly set?: string | undefined
|
|
186
|
+
/** Native window dimensions; unsupported leaves remain lazy when absent. */
|
|
187
|
+
readonly viewport?: Media.Viewport | undefined
|
|
188
|
+
}
|
|
189
|
+
}
|
package/src/runtime/index.ts
CHANGED
|
@@ -29,6 +29,12 @@ export * as NativeContext from './NativeContext.js'
|
|
|
29
29
|
/** Ordered native scalar bindings for generated dynamic callables. */
|
|
30
30
|
export * as NativeDynamic from './NativeDynamic.js'
|
|
31
31
|
|
|
32
|
+
/** Finite native selection without dynamic value conversion. */
|
|
33
|
+
export * as NativeStatic from './NativeStatic.js'
|
|
34
|
+
|
|
35
|
+
/** Readonly native variable selection for compiled hooks. */
|
|
36
|
+
export * as NativeVars from './NativeVars.js'
|
|
37
|
+
|
|
32
38
|
/** Scoped recipe inputs bound to fixed variable slots. */
|
|
33
39
|
export * as PayloadRecipe from './PayloadRecipe.js'
|
|
34
40
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Selects precompiled media alternatives using native logical dimensions. @module */
|
|
2
|
+
|
|
3
|
+
/** Comparison data emitted by the compiler, with no CSS parsing at application time. */
|
|
4
|
+
export type Query =
|
|
5
|
+
| { readonly kind: 'and'; readonly queries: readonly Query[] }
|
|
6
|
+
| {
|
|
7
|
+
readonly kind: 'compare'
|
|
8
|
+
readonly left: number | 'height' | 'width'
|
|
9
|
+
readonly operator: '<' | '<=' | '=' | '>' | '>='
|
|
10
|
+
readonly right: number | 'height' | 'width'
|
|
11
|
+
}
|
|
12
|
+
| { readonly kind: 'not'; readonly query: Query }
|
|
13
|
+
| { readonly kind: 'or'; readonly queries: readonly Query[] }
|
|
14
|
+
|
|
15
|
+
/** Window measurements supplied by the native React adapter. */
|
|
16
|
+
export type Viewport = {
|
|
17
|
+
readonly height: number
|
|
18
|
+
readonly width: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Computes the selected alternative without interpreting authoring code. */
|
|
22
|
+
export function select(
|
|
23
|
+
queries: readonly Query[],
|
|
24
|
+
viewport: Viewport | undefined,
|
|
25
|
+
): string {
|
|
26
|
+
if (!viewport)
|
|
27
|
+
throw new Error(
|
|
28
|
+
'Native media queries require the native Provider window dimensions.',
|
|
29
|
+
)
|
|
30
|
+
if (
|
|
31
|
+
!Number.isFinite(viewport.height) ||
|
|
32
|
+
viewport.height < 0 ||
|
|
33
|
+
!Number.isFinite(viewport.width) ||
|
|
34
|
+
viewport.width < 0
|
|
35
|
+
)
|
|
36
|
+
throw new Error('Native window dimensions must be finite and nonnegative.')
|
|
37
|
+
|
|
38
|
+
const dimensions = viewport
|
|
39
|
+
function matches(query: Query): boolean {
|
|
40
|
+
if (query.kind === 'and') return query.queries.every(matches)
|
|
41
|
+
if (query.kind === 'or') return query.queries.some(matches)
|
|
42
|
+
if (query.kind === 'not') return !matches(query.query)
|
|
43
|
+
|
|
44
|
+
const left =
|
|
45
|
+
typeof query.left === 'number' ? query.left : dimensions[query.left]
|
|
46
|
+
const right =
|
|
47
|
+
typeof query.right === 'number' ? query.right : dimensions[query.right]
|
|
48
|
+
switch (query.operator) {
|
|
49
|
+
case '<':
|
|
50
|
+
return left < right
|
|
51
|
+
case '<=':
|
|
52
|
+
return left <= right
|
|
53
|
+
case '=':
|
|
54
|
+
return left === right
|
|
55
|
+
case '>':
|
|
56
|
+
return left > right
|
|
57
|
+
case '>=':
|
|
58
|
+
return left >= right
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return queries.map((query) => (matches(query) ? '1' : '0')).join('')
|
|
63
|
+
}
|
package/src/vite/index.ts
CHANGED
|
@@ -20,6 +20,7 @@ import * as Scope from '../compiler/internal/Scope.js'
|
|
|
20
20
|
import type { Environment, Plugin, Rollup, ViteDevServer } from 'vite'
|
|
21
21
|
import * as Graph from '../compiler/Graph.js'
|
|
22
22
|
import * as Source from '../compiler/Source.js'
|
|
23
|
+
import * as ThemeRules from '../web/internal/Themes.js'
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Compiles physical project source without executing authoring code.
|
|
@@ -749,6 +750,7 @@ export function zyzz(options: zyzz.Options = {}): Plugin {
|
|
|
749
750
|
)
|
|
750
751
|
|
|
751
752
|
const result = entry.compiler.compile({
|
|
753
|
+
[ThemeRules.shared]: native ? undefined : 'all',
|
|
752
754
|
[Syntax.cache]: snapshot(entry.environment).programs(modules),
|
|
753
755
|
compiler: options.compiler,
|
|
754
756
|
reset: options.reset ? Reset.read() : undefined,
|
|
@@ -812,46 +814,6 @@ export function zyzz(options: zyzz.Options = {}): Plugin {
|
|
|
812
814
|
configurations.set(key, configuration)
|
|
813
815
|
}
|
|
814
816
|
|
|
815
|
-
const map = new Mapping.GenMapping()
|
|
816
|
-
const styles: string[] = []
|
|
817
|
-
let line = 0
|
|
818
|
-
|
|
819
|
-
for (const [id, output] of Object.entries(result.modules)) {
|
|
820
|
-
if (!connected.has(sourceFile(id)!)) continue
|
|
821
|
-
if (!output.css) continue
|
|
822
|
-
|
|
823
|
-
for (const mapping of Mapping.allMappings(
|
|
824
|
-
Mapping.fromMap(JSON.stringify(output.cssMap)),
|
|
825
|
-
)) {
|
|
826
|
-
const generated = {
|
|
827
|
-
column: mapping.generated.column,
|
|
828
|
-
line: mapping.generated.line + line,
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
if (mapping.source !== undefined && mapping.original !== undefined) {
|
|
832
|
-
const location = {
|
|
833
|
-
generated,
|
|
834
|
-
original: mapping.original,
|
|
835
|
-
source: sourceFile(mapping.source) ?? mapping.source,
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
if (mapping.name === undefined) Mapping.addMapping(map, location)
|
|
839
|
-
else Mapping.addMapping(map, { ...location, name: mapping.name })
|
|
840
|
-
} else Mapping.addMapping(map, { generated })
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
for (const [index, source] of output.cssMap.sources.entries())
|
|
844
|
-
if (source !== null)
|
|
845
|
-
Mapping.setSourceContent(
|
|
846
|
-
map,
|
|
847
|
-
sourceFile(source) ?? source,
|
|
848
|
-
output.cssMap.sourcesContent?.[index] ?? null,
|
|
849
|
-
)
|
|
850
|
-
|
|
851
|
-
styles.push(output.css)
|
|
852
|
-
line += output.css.split('\n').length
|
|
853
|
-
}
|
|
854
|
-
|
|
855
817
|
const owners = new Map<string, string>()
|
|
856
818
|
|
|
857
819
|
for (const id of new Set(Object.values(result.sharedAssetOwners ?? {}))) {
|
|
@@ -1018,10 +980,15 @@ export function zyzz(options: zyzz.Options = {}): Plugin {
|
|
|
1018
980
|
contractIds: Object.keys(compiled),
|
|
1019
981
|
configurations,
|
|
1020
982
|
connections: staged,
|
|
1021
|
-
css:
|
|
983
|
+
css: output.css,
|
|
1022
984
|
sharedCss: new TextDecoder().decode(shared.code),
|
|
1023
985
|
sharedCssMap: sharedMap,
|
|
1024
|
-
cssMap:
|
|
986
|
+
cssMap: {
|
|
987
|
+
...output.cssMap,
|
|
988
|
+
sources: output.cssMap.sources.map((source) =>
|
|
989
|
+
source === null ? null : (sourceFile(source) ?? source),
|
|
990
|
+
),
|
|
991
|
+
},
|
|
1025
992
|
map: {
|
|
1026
993
|
...output.map,
|
|
1027
994
|
sources: output.map.sources.map((source) =>
|
package/src/web/Css.ts
CHANGED
|
@@ -56,7 +56,18 @@ export function compile<
|
|
|
56
56
|
return result
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
const bodies = new Map<Style.NamedStyle, string>()
|
|
60
|
+
const declarations = new Map<Style.Declaration, string>()
|
|
61
|
+
type Property = {
|
|
62
|
+
readonly important: Map<Style.Declaration['value'], string>
|
|
63
|
+
readonly name: string
|
|
64
|
+
readonly normal: Map<Style.Declaration['value'], string>
|
|
65
|
+
}
|
|
66
|
+
const declarationProperties = new Map<string, Property>()
|
|
67
|
+
const serialized = new Map<object, string>()
|
|
68
|
+
|
|
59
69
|
// Only primitive declaration lists can be interned without erasing token identity.
|
|
70
|
+
// Reuse their emitted bodies throughout analysis and output.
|
|
60
71
|
const repeated = new Map<string, Style.NamedStyle>()
|
|
61
72
|
|
|
62
73
|
const canonicalStyles = options.styles.styles.map((style) => {
|
|
@@ -68,13 +79,7 @@ export function compile<
|
|
|
68
79
|
)
|
|
69
80
|
return style
|
|
70
81
|
|
|
71
|
-
const key =
|
|
72
|
-
style.declarations.map(({ important, property, value }) => [
|
|
73
|
-
property,
|
|
74
|
-
value,
|
|
75
|
-
important,
|
|
76
|
-
]),
|
|
77
|
-
)
|
|
82
|
+
const key = nested(style)
|
|
78
83
|
const previous = repeated.get(key)
|
|
79
84
|
if (previous) return previous
|
|
80
85
|
|
|
@@ -269,8 +274,6 @@ export function compile<
|
|
|
269
274
|
if (Object.hasOwn(Cascade.shorthands, property))
|
|
270
275
|
join(property, domain(property))
|
|
271
276
|
|
|
272
|
-
const serialized = new Map<object, string>()
|
|
273
|
-
|
|
274
277
|
function serialize(input: Style.Declaration['value']): number | string {
|
|
275
278
|
if (typeof input !== 'object' || input === null) return input
|
|
276
279
|
|
|
@@ -298,22 +301,32 @@ export function compile<
|
|
|
298
301
|
return input as number | string
|
|
299
302
|
}
|
|
300
303
|
|
|
301
|
-
const declarations = new Map<Style.Declaration, string>()
|
|
302
|
-
const propertyNames = new Map<string, string>()
|
|
303
|
-
|
|
304
304
|
function declarationBody(declaration: Style.Declaration): string {
|
|
305
305
|
const previous = declarations.get(declaration)
|
|
306
306
|
if (previous !== undefined) return previous
|
|
307
|
+
|
|
307
308
|
const { important, property, value } = declaration
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
309
|
+
let entry = declarationProperties.get(property)
|
|
310
|
+
if (!entry) {
|
|
311
|
+
entry = {
|
|
312
|
+
important: new Map(),
|
|
313
|
+
name: Literal.name(property),
|
|
314
|
+
normal: new Map(),
|
|
315
|
+
}
|
|
316
|
+
declarationProperties.set(property, entry)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const values = important ? entry.important : entry.normal
|
|
320
|
+
let body = values.get(value)
|
|
321
|
+
if (body === undefined) {
|
|
322
|
+
body = `${entry.name}:${serialize(value)}${important ? '!important' : ''};`
|
|
323
|
+
values.set(value, body)
|
|
324
|
+
}
|
|
325
|
+
|
|
311
326
|
declarations.set(declaration, body)
|
|
312
327
|
return body
|
|
313
328
|
}
|
|
314
329
|
|
|
315
|
-
const bodies = new Map<Style.NamedStyle, string>()
|
|
316
|
-
|
|
317
330
|
function nested(style: Style.NamedStyle): string {
|
|
318
331
|
const previous = bodies.get(style)
|
|
319
332
|
if (previous !== undefined) return previous
|
|
@@ -401,11 +414,8 @@ export function compile<
|
|
|
401
414
|
}
|
|
402
415
|
|
|
403
416
|
function validate(style: Style.NamedStyle) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
outputMode(style) !== 'atomic' &&
|
|
407
|
-
outputMode(style) !== 'grouped'
|
|
408
|
-
)
|
|
417
|
+
const mode = outputMode(style)
|
|
418
|
+
if (mode !== undefined && mode !== 'atomic' && mode !== 'grouped')
|
|
409
419
|
throw new CompileError([
|
|
410
420
|
{
|
|
411
421
|
code: 'invalid_output',
|
|
@@ -421,7 +431,8 @@ export function compile<
|
|
|
421
431
|
const rules = new Map<string, string>()
|
|
422
432
|
type ConditionalRule = { conditions: readonly string[]; value: string }
|
|
423
433
|
const conditionalRules = new Map<string, ConditionalRule>()
|
|
424
|
-
|
|
434
|
+
type SharedRules = Record<'atomic' | 'grouped', Map<string, string>>
|
|
435
|
+
const identical = new Map<string | undefined, SharedRules>()
|
|
425
436
|
const explicitBodies = new Map<string, string>()
|
|
426
437
|
const selectors = new Map<string, string>()
|
|
427
438
|
const explicitModes = new Set<string>()
|
|
@@ -465,7 +476,7 @@ export function compile<
|
|
|
465
476
|
explicit === undefined &&
|
|
466
477
|
options.composition === 'independent' &&
|
|
467
478
|
!options.development
|
|
468
|
-
? `${mode}:${JSON.stringify(representation(style))}:${nested(canonicalStyles[styleIndex]!)}`
|
|
479
|
+
? `${mode}:${style.rules ? JSON.stringify(representation(style)) : ''}:${nested(canonicalStyles[styleIndex]!)}`
|
|
469
480
|
: undefined
|
|
470
481
|
if (application !== undefined && applications.has(application)) {
|
|
471
482
|
classes[style.name] = applications.get(application)!
|
|
@@ -478,6 +489,11 @@ export function compile<
|
|
|
478
489
|
const cssNamespace =
|
|
479
490
|
labels?.[style.name]?.namespace ??
|
|
480
491
|
(options.scope ? Identity.name(options.scope) : undefined)
|
|
492
|
+
let sharedRules = identical.get(cssNamespace)
|
|
493
|
+
if (!sharedRules) {
|
|
494
|
+
sharedRules = { atomic: new Map(), grouped: new Map() }
|
|
495
|
+
identical.set(cssNamespace, sharedRules)
|
|
496
|
+
}
|
|
481
497
|
|
|
482
498
|
function emit(
|
|
483
499
|
body: string,
|
|
@@ -493,9 +509,8 @@ export function compile<
|
|
|
493
509
|
!options.development &&
|
|
494
510
|
output === mode &&
|
|
495
511
|
options.composition === 'independent'
|
|
496
|
-
const key = JSON.stringify([cssNamespace, output, body])
|
|
497
512
|
const reusable = explicit === undefined && (shared || independent)
|
|
498
|
-
const previous = reusable ?
|
|
513
|
+
const previous = reusable ? sharedRules![output].get(body) : undefined
|
|
499
514
|
if (previous && !names.includes(previous)) {
|
|
500
515
|
names.push(previous)
|
|
501
516
|
return
|
|
@@ -544,7 +559,7 @@ export function compile<
|
|
|
544
559
|
conditionalRules.set(identity, conditional)
|
|
545
560
|
if (explicit !== undefined) selectors.set(identity, explicit)
|
|
546
561
|
else {
|
|
547
|
-
if (reusable)
|
|
562
|
+
if (reusable) sharedRules![output].set(body, identity)
|
|
548
563
|
names.push(identity)
|
|
549
564
|
}
|
|
550
565
|
}
|
|
@@ -15,6 +15,24 @@ export function create() {
|
|
|
15
15
|
{ identity: string | undefined; paths: Map<string, string> }
|
|
16
16
|
>()
|
|
17
17
|
|
|
18
|
+
const anonymous = new Map<Token.Contract, Map<string, string>>()
|
|
19
|
+
let nextVariable = 0
|
|
20
|
+
function property(contract: Token.Contract, path: string): string {
|
|
21
|
+
const identity = contract[Token.identity]
|
|
22
|
+
if (identity) return variable(identity, path)
|
|
23
|
+
let paths = anonymous.get(contract)
|
|
24
|
+
if (!paths) {
|
|
25
|
+
paths = new Map()
|
|
26
|
+
anonymous.set(contract, paths)
|
|
27
|
+
}
|
|
28
|
+
let name = paths.get(path)
|
|
29
|
+
if (!name) {
|
|
30
|
+
name = `--z${(nextVariable++).toString(36)}`
|
|
31
|
+
paths.set(path, name)
|
|
32
|
+
}
|
|
33
|
+
return name
|
|
34
|
+
}
|
|
35
|
+
|
|
18
36
|
const defaults = new Map<string, readonly Rule[]>()
|
|
19
37
|
const defaultGroups = new Map<Token.Contract, Set<string>>()
|
|
20
38
|
|
|
@@ -33,11 +51,7 @@ export function create() {
|
|
|
33
51
|
let name = contract.paths.get(token.path)
|
|
34
52
|
|
|
35
53
|
if (!name) {
|
|
36
|
-
name =
|
|
37
|
-
contract.identity,
|
|
38
|
-
token.path,
|
|
39
|
-
token.contract.variableNaming,
|
|
40
|
-
)
|
|
54
|
+
name = property(token.contract, token.path)
|
|
41
55
|
contract.paths.set(token.path, name)
|
|
42
56
|
}
|
|
43
57
|
|
|
@@ -51,6 +65,7 @@ export function create() {
|
|
|
51
65
|
separate?: 'all' | 'defaults',
|
|
52
66
|
) {
|
|
53
67
|
const classes: Record<string, string> = Object.create(null)
|
|
68
|
+
let nextScope = 0
|
|
54
69
|
const scopeBodies = new Map<string, string>()
|
|
55
70
|
const completeDefaults = new Set<Token.Contract>()
|
|
56
71
|
const empty: string[] = []
|
|
@@ -68,14 +83,17 @@ export function create() {
|
|
|
68
83
|
|
|
69
84
|
// Anonymous contracts are graph-local. Source-owned contracts retain stable
|
|
70
85
|
// identities across separately compiled components and theme scopes.
|
|
71
|
-
const className =
|
|
72
|
-
data.cssName
|
|
73
|
-
(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
86
|
+
const className =
|
|
87
|
+
data.contract[Token.identity] || data.cssName
|
|
88
|
+
? scope(
|
|
89
|
+
data.cssName ??
|
|
90
|
+
(data.contract[Token.identity] &&
|
|
91
|
+
name.startsWith(`${data.contract[Token.identity]}-`)
|
|
92
|
+
? name.slice(data.contract[Token.identity]!.length + 1)
|
|
93
|
+
: name),
|
|
94
|
+
data.contract[Token.identity],
|
|
95
|
+
)
|
|
96
|
+
: `z${(nextScope++).toString(36)}`
|
|
79
97
|
|
|
80
98
|
classes[name] = className
|
|
81
99
|
|
|
@@ -91,10 +109,7 @@ export function create() {
|
|
|
91
109
|
for (const path of Object.keys(data.values)) {
|
|
92
110
|
if (contract.paths.has(path)) continue
|
|
93
111
|
|
|
94
|
-
contract.paths.set(
|
|
95
|
-
path,
|
|
96
|
-
variable(contract.identity, path, data.contract.variableNaming),
|
|
97
|
-
)
|
|
112
|
+
contract.paths.set(path, property(data.contract, path))
|
|
98
113
|
}
|
|
99
114
|
|
|
100
115
|
contracts.set(data.contract, contract)
|
|
@@ -125,28 +140,6 @@ export function create() {
|
|
|
125
140
|
selector: `.${className}`,
|
|
126
141
|
value: literal(value, label, data.contract),
|
|
127
142
|
})
|
|
128
|
-
// Standalone styles have no contract metadata to select their original spelling.
|
|
129
|
-
if (
|
|
130
|
-
contract.identity?.startsWith('id-') &&
|
|
131
|
-
data.contract.variableNaming === undefined
|
|
132
|
-
)
|
|
133
|
-
declarations.push({
|
|
134
|
-
conditions: [],
|
|
135
|
-
property: variable(
|
|
136
|
-
`id-${Array.from(
|
|
137
|
-
contract.identity
|
|
138
|
-
.slice(3)
|
|
139
|
-
.replace(/_([0-9a-f]+)_/g, (_, code: string) =>
|
|
140
|
-
String.fromCodePoint(Number.parseInt(code, 16)),
|
|
141
|
-
),
|
|
142
|
-
(character) => character.codePointAt(0)!.toString(16),
|
|
143
|
-
).join('-')}`,
|
|
144
|
-
path,
|
|
145
|
-
'legacy',
|
|
146
|
-
),
|
|
147
|
-
selector: `.${className}`,
|
|
148
|
-
value: `var(${name})`,
|
|
149
|
-
})
|
|
150
143
|
}
|
|
151
144
|
|
|
152
145
|
rules.push(...declarations)
|
|
@@ -266,7 +259,7 @@ export function create() {
|
|
|
266
259
|
const base = literal(value.default, label, owner)
|
|
267
260
|
// Rule consolidation must not change existing variable identities.
|
|
268
261
|
const css = `:where(*){--fallback:${base};}${conditionalCss(value, '--fallback', ':where(*)', label, owner)}`
|
|
269
|
-
const name = `${
|
|
262
|
+
const name = `${owner ? property(owner, label ?? 'value') : variable(undefined, label ?? 'value')}-fallback-${Identity.name(css)}`
|
|
270
263
|
const emitted: Rule[] = [
|
|
271
264
|
{ conditions: [], property: name, selector: ':where(*)', value: base },
|
|
272
265
|
]
|
|
@@ -341,14 +334,6 @@ export function create() {
|
|
|
341
334
|
return { emit, serialize }
|
|
342
335
|
}
|
|
343
336
|
|
|
344
|
-
/** Escapes a scope key into the identifier segment of its compiled class. */
|
|
345
|
-
export function encode(value: string): string {
|
|
346
|
-
return value.replace(
|
|
347
|
-
/[^a-zA-Z0-9-]/g,
|
|
348
|
-
(character) => `_${character.charCodeAt(0).toString(16)}_`,
|
|
349
|
-
)
|
|
350
|
-
}
|
|
351
|
-
|
|
352
337
|
/** Combines generated declarations without crossing competing declarations of the same property. */
|
|
353
338
|
export function render(rules: readonly Rule[]): string {
|
|
354
339
|
const groups: {
|
|
@@ -424,15 +409,7 @@ export function scope(value: string, identity?: string): string {
|
|
|
424
409
|
return `z-theme-${namespace}${Identity.name(value)}`
|
|
425
410
|
}
|
|
426
411
|
|
|
427
|
-
function variable(
|
|
428
|
-
identity: string | undefined,
|
|
429
|
-
path: string,
|
|
430
|
-
naming?: 'legacy' | 'hashed',
|
|
431
|
-
): string {
|
|
432
|
-
if (naming === 'legacy' && identity)
|
|
433
|
-
return `--z-t${encode(identity)}-${encode(path)}`
|
|
434
|
-
if (naming === 'hashed')
|
|
435
|
-
return `--z-${Identity.label(path)}-${Identity.compact(JSON.stringify([identity, path]))}`
|
|
412
|
+
function variable(identity: string | undefined, path: string): string {
|
|
436
413
|
const namespace = identity?.startsWith('id-') ? `${identity.slice(3)}-` : ''
|
|
437
414
|
return `--z-${namespace}${path.split('.').map(Identity.name).join('-')}`
|
|
438
415
|
}
|
package/src/web/page.ts
CHANGED
|
@@ -35,6 +35,8 @@ export declare namespace page {
|
|
|
35
35
|
| 'crop cross'
|
|
36
36
|
| 'cross crop'
|
|
37
37
|
| undefined
|
|
38
|
+
/** Handling of page margins that exceed the printer's printable area. */
|
|
39
|
+
readonly pageMarginSafety?: 'none' | 'clamp' | 'add' | undefined
|
|
38
40
|
/** Rotation applied to a laid-out page. */
|
|
39
41
|
readonly pageOrientation?:
|
|
40
42
|
| 'upright'
|