@elastic/distillate 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/LICENSE.txt +93 -0
  2. package/NOTICE.txt +30 -0
  3. package/README.md +142 -0
  4. package/THIRD_PARTY_LICENSES.md +768 -0
  5. package/dist/cjs/collector.js +420 -0
  6. package/dist/cjs/collector.js.map +1 -0
  7. package/dist/cjs/css_scan.js +186 -0
  8. package/dist/cjs/css_scan.js.map +1 -0
  9. package/dist/cjs/dom_sink.js +40 -0
  10. package/dist/cjs/dom_sink.js.map +1 -0
  11. package/dist/cjs/emotion.js +189 -0
  12. package/dist/cjs/emotion.js.map +1 -0
  13. package/dist/cjs/engine.js +79 -0
  14. package/dist/cjs/engine.js.map +1 -0
  15. package/dist/cjs/environment.js +9 -0
  16. package/dist/cjs/environment.js.map +1 -0
  17. package/dist/cjs/hash.js +86 -0
  18. package/dist/cjs/hash.js.map +1 -0
  19. package/dist/cjs/idents.js +23 -0
  20. package/dist/cjs/idents.js.map +1 -0
  21. package/dist/cjs/index.js +42 -0
  22. package/dist/cjs/index.js.map +1 -0
  23. package/dist/cjs/instance.js +34 -0
  24. package/dist/cjs/instance.js.map +1 -0
  25. package/dist/cjs/local_vars.js +100 -0
  26. package/dist/cjs/local_vars.js.map +1 -0
  27. package/dist/cjs/minify.js +77 -0
  28. package/dist/cjs/minify.js.map +1 -0
  29. package/dist/cjs/names.js +77 -0
  30. package/dist/cjs/names.js.map +1 -0
  31. package/dist/cjs/nesting.js +406 -0
  32. package/dist/cjs/nesting.js.map +1 -0
  33. package/dist/cjs/package.json +3 -0
  34. package/dist/cjs/runtime.js +257 -0
  35. package/dist/cjs/runtime.js.map +1 -0
  36. package/dist/cjs/styles/authoring.js +169 -0
  37. package/dist/cjs/styles/authoring.js.map +1 -0
  38. package/dist/cjs/styles/declarations.js +139 -0
  39. package/dist/cjs/styles/declarations.js.map +1 -0
  40. package/dist/cjs/styles/index.js +32 -0
  41. package/dist/cjs/styles/index.js.map +1 -0
  42. package/dist/cjs/styles/module.js +233 -0
  43. package/dist/cjs/styles/module.js.map +1 -0
  44. package/dist/cjs/styles/registry.js +187 -0
  45. package/dist/cjs/styles/registry.js.map +1 -0
  46. package/dist/cjs/styles/types.js +9 -0
  47. package/dist/cjs/styles/types.js.map +1 -0
  48. package/dist/cjs/testing.js +37 -0
  49. package/dist/cjs/testing.js.map +1 -0
  50. package/dist/cjs/theme.js +249 -0
  51. package/dist/cjs/theme.js.map +1 -0
  52. package/dist/cjs/tokens/contextual_var.js +39 -0
  53. package/dist/cjs/tokens/contextual_var.js.map +1 -0
  54. package/dist/cjs/tokens/index.js +24 -0
  55. package/dist/cjs/tokens/index.js.map +1 -0
  56. package/dist/cjs/tokens/kind.js +14 -0
  57. package/dist/cjs/tokens/kind.js.map +1 -0
  58. package/dist/cjs/tokens/light_dark.js +42 -0
  59. package/dist/cjs/tokens/light_dark.js.map +1 -0
  60. package/dist/cjs/tokens/scale_token.js +28 -0
  61. package/dist/cjs/tokens/scale_token.js.map +1 -0
  62. package/dist/cjs/tokens/theme_token.js +28 -0
  63. package/dist/cjs/tokens/theme_token.js.map +1 -0
  64. package/dist/cjs/var_invariant.js +115 -0
  65. package/dist/cjs/var_invariant.js.map +1 -0
  66. package/dist/collector.d.ts +84 -0
  67. package/dist/collector.d.ts.map +1 -0
  68. package/dist/collector.js +416 -0
  69. package/dist/collector.js.map +1 -0
  70. package/dist/css_scan.d.ts +57 -0
  71. package/dist/css_scan.d.ts.map +1 -0
  72. package/dist/css_scan.js +180 -0
  73. package/dist/css_scan.js.map +1 -0
  74. package/dist/dom_sink.d.ts +27 -0
  75. package/dist/dom_sink.d.ts.map +1 -0
  76. package/dist/dom_sink.js +36 -0
  77. package/dist/dom_sink.js.map +1 -0
  78. package/dist/emotion.d.ts +47 -0
  79. package/dist/emotion.d.ts.map +1 -0
  80. package/dist/emotion.js +184 -0
  81. package/dist/emotion.js.map +1 -0
  82. package/dist/engine.d.ts +41 -0
  83. package/dist/engine.d.ts.map +1 -0
  84. package/dist/engine.js +75 -0
  85. package/dist/engine.js.map +1 -0
  86. package/dist/environment.d.ts +43 -0
  87. package/dist/environment.d.ts.map +1 -0
  88. package/dist/environment.js +8 -0
  89. package/dist/environment.js.map +1 -0
  90. package/dist/hash.d.ts +2 -0
  91. package/dist/hash.d.ts.map +1 -0
  92. package/dist/hash.js +82 -0
  93. package/dist/hash.js.map +1 -0
  94. package/dist/idents.d.ts +9 -0
  95. package/dist/idents.d.ts.map +1 -0
  96. package/dist/idents.js +19 -0
  97. package/dist/idents.js.map +1 -0
  98. package/dist/index.d.ts +9 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +14 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/instance.d.ts +16 -0
  103. package/dist/instance.d.ts.map +1 -0
  104. package/dist/instance.js +30 -0
  105. package/dist/instance.js.map +1 -0
  106. package/dist/local_vars.d.ts +75 -0
  107. package/dist/local_vars.d.ts.map +1 -0
  108. package/dist/local_vars.js +92 -0
  109. package/dist/local_vars.js.map +1 -0
  110. package/dist/minify.d.ts +11 -0
  111. package/dist/minify.d.ts.map +1 -0
  112. package/dist/minify.js +73 -0
  113. package/dist/minify.js.map +1 -0
  114. package/dist/names.d.ts +39 -0
  115. package/dist/names.d.ts.map +1 -0
  116. package/dist/names.js +70 -0
  117. package/dist/names.js.map +1 -0
  118. package/dist/nesting.d.ts +59 -0
  119. package/dist/nesting.d.ts.map +1 -0
  120. package/dist/nesting.js +400 -0
  121. package/dist/nesting.js.map +1 -0
  122. package/dist/runtime.d.ts +36 -0
  123. package/dist/runtime.d.ts.map +1 -0
  124. package/dist/runtime.js +252 -0
  125. package/dist/runtime.js.map +1 -0
  126. package/dist/styles/authoring.d.ts +59 -0
  127. package/dist/styles/authoring.d.ts.map +1 -0
  128. package/dist/styles/authoring.js +155 -0
  129. package/dist/styles/authoring.js.map +1 -0
  130. package/dist/styles/declarations.d.ts +10 -0
  131. package/dist/styles/declarations.d.ts.map +1 -0
  132. package/dist/styles/declarations.js +132 -0
  133. package/dist/styles/declarations.js.map +1 -0
  134. package/dist/styles/index.d.ts +7 -0
  135. package/dist/styles/index.d.ts.map +1 -0
  136. package/dist/styles/index.js +12 -0
  137. package/dist/styles/index.js.map +1 -0
  138. package/dist/styles/module.d.ts +5 -0
  139. package/dist/styles/module.d.ts.map +1 -0
  140. package/dist/styles/module.js +229 -0
  141. package/dist/styles/module.js.map +1 -0
  142. package/dist/styles/registry.d.ts +48 -0
  143. package/dist/styles/registry.d.ts.map +1 -0
  144. package/dist/styles/registry.js +182 -0
  145. package/dist/styles/registry.js.map +1 -0
  146. package/dist/styles/types.d.ts +211 -0
  147. package/dist/styles/types.d.ts.map +1 -0
  148. package/dist/styles/types.js +8 -0
  149. package/dist/styles/types.js.map +1 -0
  150. package/dist/testing.d.ts +10 -0
  151. package/dist/testing.d.ts.map +1 -0
  152. package/dist/testing.js +31 -0
  153. package/dist/testing.js.map +1 -0
  154. package/dist/theme.d.ts +85 -0
  155. package/dist/theme.d.ts.map +1 -0
  156. package/dist/theme.js +240 -0
  157. package/dist/theme.js.map +1 -0
  158. package/dist/tokens/contextual_var.d.ts +35 -0
  159. package/dist/tokens/contextual_var.d.ts.map +1 -0
  160. package/dist/tokens/contextual_var.js +33 -0
  161. package/dist/tokens/contextual_var.js.map +1 -0
  162. package/dist/tokens/index.d.ts +5 -0
  163. package/dist/tokens/index.d.ts.map +1 -0
  164. package/dist/tokens/index.js +11 -0
  165. package/dist/tokens/index.js.map +1 -0
  166. package/dist/tokens/kind.d.ts +2 -0
  167. package/dist/tokens/kind.d.ts.map +1 -0
  168. package/dist/tokens/kind.js +10 -0
  169. package/dist/tokens/kind.js.map +1 -0
  170. package/dist/tokens/light_dark.d.ts +20 -0
  171. package/dist/tokens/light_dark.d.ts.map +1 -0
  172. package/dist/tokens/light_dark.js +37 -0
  173. package/dist/tokens/light_dark.js.map +1 -0
  174. package/dist/tokens/scale_token.d.ts +20 -0
  175. package/dist/tokens/scale_token.d.ts.map +1 -0
  176. package/dist/tokens/scale_token.js +23 -0
  177. package/dist/tokens/scale_token.js.map +1 -0
  178. package/dist/tokens/theme_token.d.ts +20 -0
  179. package/dist/tokens/theme_token.d.ts.map +1 -0
  180. package/dist/tokens/theme_token.js +23 -0
  181. package/dist/tokens/theme_token.js.map +1 -0
  182. package/dist/var_invariant.d.ts +25 -0
  183. package/dist/var_invariant.d.ts.map +1 -0
  184. package/dist/var_invariant.js +108 -0
  185. package/dist/var_invariant.js.map +1 -0
  186. package/docs/concepts/authoring.md +115 -0
  187. package/docs/concepts/collection.md +66 -0
  188. package/docs/concepts/distillery.md +47 -0
  189. package/docs/concepts/index.md +18 -0
  190. package/docs/concepts/naming-and-output.md +123 -0
  191. package/docs/concepts/ordering.md +61 -0
  192. package/docs/concepts/single-copy.md +103 -0
  193. package/docs/concepts/tokens.md +99 -0
  194. package/docs/docset.yml +53 -0
  195. package/docs/examples/01-stylesheet.ts +20 -0
  196. package/docs/examples/02-artifact.ts +26 -0
  197. package/docs/examples/03-variants.ts +40 -0
  198. package/docs/examples/04-emotion.ts +33 -0
  199. package/docs/examples/05-var-invariant.ts +31 -0
  200. package/docs/examples/06-payload.ts +85 -0
  201. package/docs/examples/fixture.ts +22 -0
  202. package/docs/getting-started/index.md +14 -0
  203. package/docs/getting-started/installation.md +30 -0
  204. package/docs/getting-started/quick-start.md +61 -0
  205. package/docs/getting-started/your-first-stylesheet.md +57 -0
  206. package/docs/guides/compact-artifacts.md +87 -0
  207. package/docs/guides/emotion-migration.md +60 -0
  208. package/docs/guides/index.md +17 -0
  209. package/docs/guides/name-collisions.md +37 -0
  210. package/docs/guides/non-css-surfaces.md +73 -0
  211. package/docs/guides/react-renderer.md +158 -0
  212. package/docs/guides/theming.md +107 -0
  213. package/docs/guides/var-invariant.md +24 -0
  214. package/docs/guides/vs-emotion.md +61 -0
  215. package/docs/index.md +73 -0
  216. package/docs/logo.svg +7 -0
  217. package/docs/playground/index.html +12 -0
  218. package/docs/playground/package.json +23 -0
  219. package/docs/playground/src/app/app.tsx +109 -0
  220. package/docs/playground/src/app/css_panel.tsx +119 -0
  221. package/docs/playground/src/app/editor_panel.tsx +87 -0
  222. package/docs/playground/src/app/index.ts +8 -0
  223. package/docs/playground/src/app/monaco_css_editor.tsx +84 -0
  224. package/docs/playground/src/app/monaco_source_editor.tsx +132 -0
  225. package/docs/playground/src/app/preview_panel.tsx +99 -0
  226. package/docs/playground/src/app/tokens_panel.tsx +117 -0
  227. package/docs/playground/src/app/types.ts +10 -0
  228. package/docs/playground/src/examples/snippets.test.ts +28 -0
  229. package/docs/playground/src/examples/snippets.ts +418 -0
  230. package/docs/playground/src/lib/compile.test.ts +157 -0
  231. package/docs/playground/src/lib/compile.ts +242 -0
  232. package/docs/playground/src/lib/demo_environment.test.ts +123 -0
  233. package/docs/playground/src/lib/demo_environment.ts +140 -0
  234. package/docs/playground/src/lib/editor_lib.test.ts +39 -0
  235. package/docs/playground/src/lib/editor_lib.ts +142 -0
  236. package/docs/playground/src/lib/format_css.test.ts +41 -0
  237. package/docs/playground/src/lib/format_css.ts +71 -0
  238. package/docs/playground/src/main.tsx +25 -0
  239. package/docs/playground/src/setup/chrome.test.ts +47 -0
  240. package/docs/playground/src/setup/chrome.ts +365 -0
  241. package/docs/playground/src/setup/monaco_env.ts +64 -0
  242. package/docs/playground/tsconfig.json +22 -0
  243. package/docs/playground/vite.config.ts +37 -0
  244. package/docs/playground/vitest.config.ts +35 -0
  245. package/docs/playground.md +28 -0
  246. package/docs/reference/api/emotion.md +372 -0
  247. package/docs/reference/api/index-1.md +2180 -0
  248. package/docs/reference/api/index.md +9 -0
  249. package/docs/reference/api/testing.md +92 -0
  250. package/docs/reference/api.md +12 -0
  251. package/docs/reference/entry-points.md +125 -0
  252. package/docs/reference/environment.md +60 -0
  253. package/docs/reference/index.md +11 -0
  254. package/docs/reference/okf-map.md +92 -0
  255. package/package.json +127 -4
  256. package/src/collector.ts +526 -0
  257. package/src/css_scan.ts +263 -0
  258. package/src/dom_sink.ts +65 -0
  259. package/src/emotion.ts +311 -0
  260. package/src/engine.ts +191 -0
  261. package/src/environment.ts +56 -0
  262. package/src/hash.ts +111 -0
  263. package/src/idents.ts +21 -0
  264. package/src/index.ts +93 -0
  265. package/src/instance.ts +49 -0
  266. package/src/local_vars.ts +220 -0
  267. package/src/minify.ts +87 -0
  268. package/src/names.ts +129 -0
  269. package/src/nesting.ts +596 -0
  270. package/src/runtime.ts +428 -0
  271. package/src/styles/authoring.ts +244 -0
  272. package/src/styles/declarations.ts +172 -0
  273. package/src/styles/index.ts +58 -0
  274. package/src/styles/module.ts +396 -0
  275. package/src/styles/registry.ts +261 -0
  276. package/src/styles/types.ts +283 -0
  277. package/src/testing.ts +48 -0
  278. package/src/theme.ts +454 -0
  279. package/src/tokens/contextual_var.ts +72 -0
  280. package/src/tokens/index.ts +17 -0
  281. package/src/tokens/kind.ts +13 -0
  282. package/src/tokens/light_dark.ts +58 -0
  283. package/src/tokens/scale_token.ts +41 -0
  284. package/src/tokens/theme_token.ts +42 -0
  285. package/src/var_invariant.ts +147 -0
@@ -0,0 +1,220 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3
+ * or more contributor license agreements. Licensed under the Elastic License
4
+ * 2.0; you may not use this file except in compliance with the Elastic License
5
+ * 2.0.
6
+ */
7
+
8
+ import { assertCssIdentSegment } from './idents';
9
+ import { cssVarName } from './names';
10
+ import type { ContextualVarPath, CssValue } from './styles/types';
11
+
12
+ const RESERVED_DEFAULT_KEYS = new Set(['set', 'toString', 'valueOf', 'toJSON']);
13
+
14
+ const isReservedKey = (key: string): boolean =>
15
+ RESERVED_DEFAULT_KEYS.has(key) || key.startsWith('__');
16
+
17
+ /** Reference to a local CSS variable. Stringifies to `var(--...)`. */
18
+ export interface LocalVarRef {
19
+ /** Brand distinguishing a local-var ref from other interpolations. */
20
+ readonly __kind: 'local-var-ref';
21
+ /** Canonical group/key path. */
22
+ readonly path: ContextualVarPath;
23
+ /** Actual emitted CSS custom property name. */
24
+ readonly propName: `--${string}`;
25
+ /** Usable CSS `var(...)` reference string. */
26
+ readonly ref: `var(--${string})`;
27
+ /** Stringifies to {@link LocalVarRef.ref}. */
28
+ toString(): string;
29
+ /** Template interpolation; same as {@link LocalVarRef.toString}. */
30
+ [Symbol.toPrimitive](hint: string): string;
31
+ }
32
+
33
+ /** Interpolation marker representing `.set(...)` overrides. */
34
+ export interface LocalVarOverrideMarker {
35
+ /** Brand distinguishing a `.set(...)` override marker. */
36
+ readonly __kind: 'local-var-override-marker';
37
+ /** Unique ID for the group. */
38
+ readonly groupId: string;
39
+ /** Ordered list of variable overrides. */
40
+ readonly overrides: ReadonlyArray<{
41
+ /** Variable key within the group. */
42
+ readonly key: string;
43
+ /** Canonical group/key path. */
44
+ readonly path: ContextualVarPath;
45
+ /** Actual emitted CSS custom property name. */
46
+ readonly propName: `--${string}`;
47
+ /** Override value written at this interpolation site. */
48
+ readonly value: CssValue;
49
+ }>;
50
+ }
51
+
52
+ /** Interpolation marker representing `${group}` defaults. */
53
+ export interface LocalVarDefaultMarker {
54
+ /** Brand distinguishing a `${group}` default marker. */
55
+ readonly __kind: 'local-var-default-marker';
56
+ /** Unique ID for the group. */
57
+ readonly groupId: string;
58
+ /** Group prefix path. */
59
+ readonly groupPath: `vars/${string}`;
60
+ /** Ordered list of variable defaults. */
61
+ readonly defaults: ReadonlyArray<{
62
+ /** Variable key within the group. */
63
+ readonly key: string;
64
+ /** Canonical group/key path. */
65
+ readonly path: ContextualVarPath;
66
+ /** Actual emitted CSS custom property name. */
67
+ readonly propName: `--${string}`;
68
+ /** Default value emitted when this key is reachable. */
69
+ readonly value: CssValue;
70
+ }>;
71
+ }
72
+
73
+ /** Interpolation marker: `${group}` defaults or `${group.set(...)}` overrides. */
74
+ export type LocalVarMarker = LocalVarOverrideMarker | LocalVarDefaultMarker;
75
+
76
+ /**
77
+ * Value returned by `t.vars(...)`. Interpolate `${group}`, `${group.key}`, or `${group.set({...})}`.
78
+ */
79
+ export type LocalVarGroup<TKey extends string> = {
80
+ readonly [P in TKey]: LocalVarRef;
81
+ } & {
82
+ /** Builds a marker that writes the given keys at the interpolation site. */
83
+ set(overrides: Partial<Record<TKey, CssValue>>): LocalVarOverrideMarker;
84
+ };
85
+
86
+ /** `true` when `value` is a {@link LocalVarRef}. */
87
+ export const isLocalVarRef = (value: unknown): value is LocalVarRef =>
88
+ Boolean(
89
+ value &&
90
+ typeof value === 'object' &&
91
+ (value as { __kind?: string }).__kind === 'local-var-ref'
92
+ );
93
+
94
+ /** `true` when `value` is a {@link LocalVarDefaultMarker}. */
95
+ export const isLocalVarDefaultMarker = (
96
+ value: unknown
97
+ ): value is LocalVarDefaultMarker =>
98
+ Boolean(
99
+ value &&
100
+ typeof value === 'object' &&
101
+ (value as { __kind?: string }).__kind === 'local-var-default-marker'
102
+ );
103
+
104
+ /** `true` when `value` is a {@link LocalVarOverrideMarker}. */
105
+ export const isLocalVarOverrideMarker = (
106
+ value: unknown
107
+ ): value is LocalVarOverrideMarker =>
108
+ Boolean(
109
+ value &&
110
+ typeof value === 'object' &&
111
+ (value as { __kind?: string }).__kind === 'local-var-override-marker'
112
+ );
113
+
114
+ /** `true` when `value` is a {@link LocalVarDefaultMarker} or {@link LocalVarOverrideMarker}. */
115
+ export const isLocalVarMarker = (value: unknown): value is LocalVarMarker =>
116
+ isLocalVarDefaultMarker(value) || isLocalVarOverrideMarker(value);
117
+
118
+ const cssVarPath = (
119
+ moduleName: string,
120
+ group: string,
121
+ key: string
122
+ ): ContextualVarPath => `vars/${moduleName}/${group}/${key}`;
123
+
124
+ const buildLocalVarRef = (
125
+ path: ContextualVarPath,
126
+ propName: `--${string}`
127
+ ): LocalVarRef => {
128
+ const ref: `var(--${string})` = `var(${propName})`;
129
+ const refToString = (): string => ref;
130
+ return {
131
+ __kind: 'local-var-ref',
132
+ path,
133
+ propName,
134
+ ref,
135
+ toString: refToString,
136
+ [Symbol.toPrimitive]: refToString,
137
+ };
138
+ };
139
+
140
+ const reservedKeyError = (key: string): Error =>
141
+ new Error(
142
+ `t.vars(...) defaults key "${key}" is reserved. Reserved: ${[...RESERVED_DEFAULT_KEYS].join(', ')} plus any "__"-prefixed key.`
143
+ );
144
+
145
+ export const createLocalVarGroup = <TKey extends string>(
146
+ prefix: string,
147
+ moduleName: string,
148
+ group: string,
149
+ defaults: Record<TKey, CssValue>
150
+ ): LocalVarGroup<TKey> => {
151
+ assertCssIdentSegment(group, 't.vars(...) group');
152
+ const groupId = `${moduleName}/${group}`;
153
+ const groupPath = `vars/${groupId}`;
154
+ const refs = new Map<TKey, LocalVarRef>();
155
+ const defaultsList: Array<{
156
+ readonly key: string;
157
+ readonly path: ContextualVarPath;
158
+ readonly propName: `--${string}`;
159
+ readonly value: CssValue;
160
+ }> = [];
161
+
162
+ for (const [key, value] of Object.entries(defaults) as Array<
163
+ [TKey, CssValue]
164
+ >) {
165
+ if (isReservedKey(key)) {
166
+ throw reservedKeyError(key);
167
+ }
168
+ assertCssIdentSegment(key, `t.vars("${group}") key`);
169
+ const path = cssVarPath(moduleName, group, key);
170
+ const propName = cssVarName(prefix, path);
171
+ refs.set(key, buildLocalVarRef(path, propName));
172
+ defaultsList.push({ key, path, propName, value });
173
+ }
174
+
175
+ const setOverrides = (
176
+ overrides: Partial<Record<TKey, CssValue>>
177
+ ): LocalVarOverrideMarker => {
178
+ const list: Array<LocalVarOverrideMarker['overrides'][number]> = [];
179
+ for (const [key, value] of Object.entries(overrides) as Array<
180
+ [TKey, CssValue | undefined]
181
+ >) {
182
+ if (value === undefined) {
183
+ continue;
184
+ }
185
+ const ref = refs.get(key);
186
+ if (!ref) {
187
+ throw new Error(
188
+ `t.vars("${group}").set: unknown key "${key}". Declared keys: ${defaultsList
189
+ .map((entry) => entry.key)
190
+ .join(', ')}.`
191
+ );
192
+ }
193
+ list.push({ key, path: ref.path, propName: ref.propName, value });
194
+ }
195
+ return {
196
+ __kind: 'local-var-override-marker',
197
+ groupId,
198
+ overrides: list,
199
+ };
200
+ };
201
+
202
+ const group_ = {
203
+ __kind: 'local-var-default-marker',
204
+ groupId,
205
+ groupPath,
206
+ defaults: defaultsList,
207
+ set: setOverrides,
208
+ } as unknown as LocalVarGroup<TKey>;
209
+
210
+ for (const [key, ref] of refs) {
211
+ Object.defineProperty(group_, key, {
212
+ value: ref,
213
+ enumerable: true,
214
+ writable: false,
215
+ configurable: false,
216
+ });
217
+ }
218
+
219
+ return group_;
220
+ };
package/src/minify.ts ADDED
@@ -0,0 +1,87 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3
+ * or more contributor license agreements. Licensed under the Elastic License
4
+ * 2.0; you may not use this file except in compliance with the Elastic License
5
+ * 2.0.
6
+ */
7
+
8
+ import { type CssSpan, scanCss } from './css_scan';
9
+
10
+ /**
11
+ * A space between two non-structural spans is significant wherever it sits: a
12
+ * descendant combinator in a selector (`.a .b`), a token separator in a value
13
+ * (`margin:0 auto`). Beside a structural character it is noise, except before
14
+ * a pseudo-class colon in a rules block — `.menu :hover` is not `.menu:hover`,
15
+ * while `color : red` is `color:red`.
16
+ */
17
+ const spaceIsSignificant = (
18
+ before: CssSpan | undefined,
19
+ after: CssSpan | undefined
20
+ ): boolean => {
21
+ if (!before || !after) {
22
+ return false;
23
+ }
24
+ if (before.kind === 'structural') {
25
+ return false;
26
+ }
27
+ if (after.kind === 'structural') {
28
+ // Only a pseudo-class colon in a selector keeps the space in front of it.
29
+ // Space before `{`, `}`, `;`, `,`, or `>` is never significant.
30
+ return after.text === ':' && after.block === 'rules';
31
+ }
32
+ return true;
33
+ };
34
+
35
+ /**
36
+ * Strips comments and insignificant whitespace from CSS.
37
+ *
38
+ * Strings, unquoted `url(…)` tokens, and backslash escapes pass through
39
+ * untouched: their contents are literal, so a `/*` or a `;` inside one is data
40
+ * rather than syntax.
41
+ *
42
+ * @param value Raw CSS text.
43
+ */
44
+ export const minifyCss = (value: string): string => {
45
+ // Dropping comments can leave two whitespace spans adjacent — `.a /*c*/ .b`
46
+ // — and emitting one space per span would keep both. Coalescing after the
47
+ // filter makes the run a single decision.
48
+ const spans = scanCss(value)
49
+ .filter((span) => span.kind !== 'comment')
50
+ .filter(
51
+ (span, index, all) =>
52
+ span.kind !== 'whitespace' || all[index - 1]?.kind !== 'whitespace'
53
+ );
54
+ const out: string[] = [];
55
+ // Indices into `spans` of what has been emitted, so lookaround skips the
56
+ // whitespace being decided about.
57
+ const significant = spans.filter((span) => span.kind !== 'whitespace');
58
+ let significantIndex = 0;
59
+
60
+ spans.forEach((span) => {
61
+ if (span.kind === 'whitespace') {
62
+ const before = significant[significantIndex - 1];
63
+ const after = significant[significantIndex];
64
+ if (spaceIsSignificant(before, after)) {
65
+ out.push(' ');
66
+ }
67
+ return;
68
+ }
69
+
70
+ // A declaration's terminator is redundant against the block's own close.
71
+ // Only a bare `;` qualifies: an escaped one is part of a value, and it
72
+ // arrives as an `escape` span rather than a structural `;`.
73
+ if (
74
+ span.kind === 'structural' &&
75
+ span.text === '}' &&
76
+ significant[significantIndex - 1]?.kind === 'structural' &&
77
+ significant[significantIndex - 1]?.text === ';'
78
+ ) {
79
+ out.pop();
80
+ }
81
+
82
+ out.push(span.text);
83
+ significantIndex += 1;
84
+ });
85
+
86
+ return out.join('').trim();
87
+ };
package/src/names.ts ADDED
@@ -0,0 +1,129 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3
+ * or more contributor license agreements. Licensed under the Elastic License
4
+ * 2.0; you may not use this file except in compliance with the Elastic License
5
+ * 2.0.
6
+ */
7
+
8
+ /** Naming scheme: `compact` assigns sequential identifiers by sorted key index, `readable` emits descriptive ones. */
9
+ export type StyleNameMode = 'compact' | 'readable';
10
+ /** Destination format for the CSS collection. */
11
+ export type StyleTarget = 'artifact' | 'stylesheet';
12
+
13
+ /** Context for resolving keys into final class or custom-property names. */
14
+ export interface StyleNameResolver {
15
+ /** The naming mode used by this resolver. */
16
+ readonly names: StyleNameMode;
17
+ /** Resolves a handle key into a CSS class name. */
18
+ className(key: string, readableName?: string): string;
19
+ /** Resolves a variable key into a custom property name. */
20
+ cssVar(key: string): `--${string}`;
21
+ /** Resolves a variable key into a `var(...)` reference. */
22
+ cssVarRef(key: string): `var(--${string})`;
23
+ }
24
+
25
+ /** Inputs for {@link createStyleNameResolver}. */
26
+ export interface StyleNameResolverOptions {
27
+ /** Naming strategy (`compact` or `readable`). */
28
+ names: StyleNameMode;
29
+ /** Brand prefix for readable names (`<prefix>-<key>` / `--<prefix>-<key>`), e.g. `'aui'`. */
30
+ prefix: string;
31
+ /** Keys defining the compact class-name domain. */
32
+ classKeys?: Iterable<string>;
33
+ /** Keys defining the compact custom-property domain. */
34
+ cssVarKeys?: Iterable<string>;
35
+ }
36
+
37
+ const compactAlphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
38
+
39
+ export const compactNameForIndex = (index: number): string => {
40
+ if (!Number.isInteger(index) || index < 0) {
41
+ throw new Error(`Compact name index must be a non-negative integer.`);
42
+ }
43
+
44
+ const base = compactAlphabet.length;
45
+ let remaining = index;
46
+ let length = 1;
47
+
48
+ while (remaining >= base ** length) {
49
+ remaining -= base ** length;
50
+ length += 1;
51
+ }
52
+
53
+ let name = '';
54
+ for (let position = length - 1; position >= 0; position -= 1) {
55
+ const divisor = base ** position;
56
+ const digit = Math.floor(remaining / divisor);
57
+ name += compactAlphabet[digit] ?? '';
58
+ remaining %= divisor;
59
+ }
60
+
61
+ return name;
62
+ };
63
+
64
+ /** Compact names are assigned from sorted keys so emission is deterministic. */
65
+ export const createCompactNameMap = (
66
+ keys: Iterable<string>
67
+ ): ReadonlyMap<string, string> => {
68
+ const uniqueKeys = [...new Set(keys)].sort();
69
+ return new Map(
70
+ uniqueKeys.map((key, index) => [key, compactNameForIndex(index)])
71
+ );
72
+ };
73
+
74
+ const readableClassName = (
75
+ prefix: string,
76
+ key: string,
77
+ fallback?: string
78
+ ): string => fallback ?? `${prefix}-${key.replaceAll('/', '-')}`;
79
+
80
+ /**
81
+ * Readable custom-property name: `--${prefix}-${path}` with `/` joined on `-` and a leading `vars/` stripped.
82
+ *
83
+ * @param prefix Brand prefix (e.g. `'eui'`).
84
+ * @param path Theme or contextual-var path (e.g. `'colors/ink'`, `'vars/chip/look/bg'`).
85
+ */
86
+ export const cssVarName = (prefix: string, path: string): `--${string}` =>
87
+ `--${prefix}-${path.replace(/^vars\//, '').replaceAll('/', '-')}`;
88
+
89
+ const compactLookup = (
90
+ map: ReadonlyMap<string, string>,
91
+ key: string,
92
+ kind: 'class' | 'CSS variable'
93
+ ): string => {
94
+ const name = map.get(key);
95
+ if (!name) {
96
+ throw new Error(`No compact ${kind} name registered for "${key}".`);
97
+ }
98
+ return name;
99
+ };
100
+
101
+ /** Maps semantic keys to readable (`<prefix>-<key>`) or compact (`a`, `b`, …) names. */
102
+ export const createStyleNameResolver = ({
103
+ names,
104
+ prefix,
105
+ classKeys = [],
106
+ cssVarKeys = [],
107
+ }: StyleNameResolverOptions): StyleNameResolver => {
108
+ const classMap = createCompactNameMap(classKeys);
109
+ const cssVarMap = createCompactNameMap(cssVarKeys);
110
+
111
+ const cssVar = (key: string): `--${string}` => {
112
+ if (names === 'readable') {
113
+ return cssVarName(prefix, key);
114
+ }
115
+ return `--${compactLookup(cssVarMap, key, 'CSS variable')}`;
116
+ };
117
+
118
+ return {
119
+ names,
120
+ className: (key, fallback) => {
121
+ if (names === 'readable') {
122
+ return readableClassName(prefix, key, fallback);
123
+ }
124
+ return compactLookup(classMap, key, 'class');
125
+ },
126
+ cssVar,
127
+ cssVarRef: (key) => `var(${cssVar(key)})`,
128
+ };
129
+ };