@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,41 @@
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 { describe, expect, it } from 'vitest';
9
+
10
+ import { formatCss } from './format_css';
11
+
12
+ describe('formatCss', () => {
13
+ it('expands a minified rule into indented lines', () => {
14
+ expect(formatCss('.a{color:red;padding:8px}')).toBe(
15
+ ['.a {', ' color:red;', ' padding:8px;', '}'].join('\n')
16
+ );
17
+ });
18
+
19
+ it('nests at-rule blocks', () => {
20
+ const input = '@media (min-width:400px){.a{color:red}}';
21
+ expect(formatCss(input)).toBe(
22
+ [
23
+ '@media (min-width:400px) {',
24
+ ' .a {',
25
+ ' color:red;',
26
+ ' }',
27
+ '}',
28
+ ].join('\n')
29
+ );
30
+ });
31
+
32
+ it('leaves braces inside string literals untouched', () => {
33
+ expect(formatCss('.a{content:"}"}')).toBe(
34
+ ['.a {', ' content:"}";', '}'].join('\n')
35
+ );
36
+ });
37
+
38
+ it('returns an empty string for empty input', () => {
39
+ expect(formatCss('')).toBe('');
40
+ });
41
+ });
@@ -0,0 +1,71 @@
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
+ export const formatCss = (css: string): string => {
9
+ if (!css) {
10
+ return '';
11
+ }
12
+ const lines: string[] = [];
13
+ let current = '';
14
+ let depth = 0;
15
+ let quote: '"' | "'" | null = null;
16
+
17
+ const indent = (level: number): string => ' '.repeat(Math.max(level, 0));
18
+ const flush = (level: number): void => {
19
+ const trimmed = current.trim();
20
+ if (trimmed) {
21
+ lines.push(indent(level) + trimmed);
22
+ }
23
+ current = '';
24
+ };
25
+
26
+ for (let i = 0; i < css.length; i += 1) {
27
+ const char = css[i];
28
+
29
+ if (quote) {
30
+ current += char;
31
+ if (char === quote && css[i - 1] !== '\\') {
32
+ quote = null;
33
+ }
34
+ continue;
35
+ }
36
+
37
+ if (char === '"' || char === "'") {
38
+ quote = char;
39
+ current += char;
40
+ continue;
41
+ }
42
+
43
+ if (char === '{') {
44
+ current += ' {';
45
+ flush(depth);
46
+ depth += 1;
47
+ continue;
48
+ }
49
+
50
+ if (char === '}') {
51
+ if (current.trim()) {
52
+ current += ';';
53
+ }
54
+ flush(depth);
55
+ depth -= 1;
56
+ lines.push(indent(depth) + '}');
57
+ continue;
58
+ }
59
+
60
+ if (char === ';') {
61
+ current += ';';
62
+ flush(depth);
63
+ continue;
64
+ }
65
+
66
+ current += char;
67
+ }
68
+
69
+ flush(depth);
70
+ return lines.join('\n');
71
+ };
@@ -0,0 +1,25 @@
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 { StrictMode } from 'react';
9
+ import { createRoot } from 'react-dom/client';
10
+
11
+ import { App } from './app';
12
+ import { mountChromeStyles } from './setup/chrome';
13
+
14
+ const root = document.getElementById('root');
15
+ if (!root) {
16
+ throw new Error('Missing #root');
17
+ }
18
+
19
+ mountChromeStyles(document);
20
+
21
+ createRoot(root).render(
22
+ <StrictMode>
23
+ <App />
24
+ </StrictMode>
25
+ );
@@ -0,0 +1,47 @@
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 { describe, expect, it } from 'vitest';
9
+
10
+ import { distillery, ui } from './chrome';
11
+
12
+ describe('playground chrome stylesheet', () => {
13
+ const css = distillery.renderStyles(distillery.stylesheetCollector());
14
+
15
+ it('emits theme vars on :root with the playground prefix, not the snippet prefix', () => {
16
+ expect(css).toContain(':root{');
17
+ expect(css).toContain('--pg-color-accent:');
18
+ expect(css).not.toContain('--dstl-');
19
+ });
20
+
21
+ it('emits readable chrome classes and nested chrome selectors', () => {
22
+ expect(css).toContain(`.${ui.handles.shell.readableName}{`);
23
+ expect(css).toContain(
24
+ `.${ui.handles.segmented.readableName} button[aria-pressed='true']`
25
+ );
26
+ expect(css).toContain('@media (min-width:800px)');
27
+ expect(css).toContain('grid-area:source');
28
+ expect(css).toContain('grid-area:output');
29
+ expect(css).toContain(`.${ui.handles.dockOutput.readableName}{`);
30
+ expect(css).toContain('box-sizing:border-box');
31
+ expect(css).toMatch(
32
+ new RegExp(
33
+ `\\.${ui.handles.editor.readableName} \\[data-pg-monaco\\]\\{[^}]*background:var\\(--pg-color-code\\)`
34
+ )
35
+ );
36
+ expect(css).toContain('@media (min-width:1100px)');
37
+ expect(css).toMatch(
38
+ new RegExp(
39
+ `\\.${ui.handles.cssOut.readableName}\\{[^}]*background:var\\(--pg-color-bg\\)`
40
+ )
41
+ );
42
+ expect(css).toContain(`.${ui.handles.cssStats.readableName}{`);
43
+ expect(css).toContain(`.${ui.handles.tokenTable.readableName} code{`);
44
+ expect(css).toContain(`.${ui.handles.swatch.readableName}[data-active]{`);
45
+ expect(css).toContain(`.${ui.handles.dockSource.readableName}{`);
46
+ });
47
+ });
@@ -0,0 +1,365 @@
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 {
9
+ cq,
10
+ createDistillery,
11
+ type Distillery,
12
+ lightDark,
13
+ type StyleHandle,
14
+ type TokensOf,
15
+ } from '@elastic/distillate';
16
+ import { createDomSink, createEmotion } from '@elastic/distillate/emotion';
17
+
18
+ const sansStack = 'system-ui, -apple-system, "Segoe UI", sans-serif';
19
+ const monoStack = 'ui-monospace, SFMono-Regular, Menlo, Monaco, monospace';
20
+
21
+ const chromeTheme = {
22
+ color: {
23
+ bg: lightDark('#f4f6f8', '#0f1218'),
24
+ panel: lightDark('#ffffff', '#171b24'),
25
+ ink: lightDark('#1b1e28', '#e6e8f0'),
26
+ muted: lightDark('#5a6472', '#9aa4b6'),
27
+ line: lightDark('#dce2ea', '#2b3242'),
28
+ accent: lightDark('#0b64dd', '#7aa7ff'),
29
+ danger: lightDark('#b42318', '#ff8a80'),
30
+ code: lightDark('#0f141c', '#0b0e14'),
31
+ },
32
+ space: {
33
+ s: cq('8px', '2cqi'),
34
+ m: cq('16px', '4cqi'),
35
+ l: cq('24px', '6cqi'),
36
+ },
37
+ radius: {
38
+ s: cq('8px', '8px'),
39
+ m: cq('12px', '12px'),
40
+ },
41
+ font: {
42
+ sans: sansStack,
43
+ mono: monoStack,
44
+ },
45
+ };
46
+
47
+ export type ChromeTokens = TokensOf<typeof chromeTheme>;
48
+
49
+ export const distillery: Distillery<ChromeTokens> = createDistillery({
50
+ prefix: 'pg',
51
+ themeScope: ':root',
52
+ theme: chromeTheme,
53
+ });
54
+
55
+ const barHeight = '40px';
56
+ const controlHeight = '28px';
57
+
58
+ export const ui = distillery.createStyleModule('ui', (t) => ({
59
+ shell: t.css`
60
+ display: flex;
61
+ flex-direction: column;
62
+ height: 100%;
63
+ min-height: 0;
64
+ overflow: hidden;
65
+ `,
66
+ top: t.css`
67
+ display: flex;
68
+ align-items: center;
69
+ gap: 12px;
70
+ height: ${barHeight};
71
+ flex: 0 0 ${barHeight};
72
+ padding: 0 12px;
73
+ background: ${t.tokens.color.panel};
74
+ border-block-end: 1px solid ${t.tokens.color.line};
75
+ h1 {
76
+ margin: 0;
77
+ font-size: 0.95rem;
78
+ font-weight: 600;
79
+ letter-spacing: -0.02em;
80
+ line-height: 1;
81
+ }
82
+ `,
83
+ brand: t.css`
84
+ color: ${t.tokens.color.accent};
85
+ text-decoration: none;
86
+ font-weight: 600;
87
+ font-size: 0.85rem;
88
+ line-height: 1;
89
+ `,
90
+ layout: t.css`
91
+ flex: 1;
92
+ min-width: 0;
93
+ min-height: 0;
94
+ display: grid;
95
+ gap: 1px;
96
+ background: ${t.tokens.color.line};
97
+ grid-template-columns: minmax(0, 1fr);
98
+ grid-template-rows: minmax(16rem, 42vh) minmax(0, 1fr);
99
+ grid-template-areas:
100
+ 'source'
101
+ 'output';
102
+ @media (min-width: 800px) {
103
+ grid-template-columns: minmax(18rem, 32rem) minmax(0, 1fr);
104
+ grid-template-rows: minmax(0, 1fr);
105
+ grid-template-areas: 'source output';
106
+ }
107
+ @media (min-width: 1100px) {
108
+ grid-template-columns: minmax(24rem, 40rem) minmax(0, 1fr);
109
+ }
110
+ `,
111
+ dockSource: t.css`
112
+ grid-area: source;
113
+ display: grid;
114
+ grid-template-rows: minmax(0, 1fr) minmax(16rem, 38%);
115
+ min-width: 0;
116
+ min-height: 0;
117
+ gap: 1px;
118
+ background: ${t.tokens.color.line};
119
+ > * {
120
+ min-height: 0;
121
+ }
122
+ `,
123
+ dockOutput: t.css`
124
+ grid-area: output;
125
+ display: grid;
126
+ grid-template-rows: minmax(0, 1fr) minmax(8rem, 28%);
127
+ min-width: 0;
128
+ min-height: 0;
129
+ gap: 1px;
130
+ background: ${t.tokens.color.line};
131
+ > * {
132
+ min-height: 0;
133
+ }
134
+ `,
135
+ dockPreview: t.css`
136
+ display: flex;
137
+ flex-direction: column;
138
+ min-width: 0;
139
+ min-height: 0;
140
+ `,
141
+ dockCss: t.css`
142
+ display: flex;
143
+ flex-direction: column;
144
+ min-width: 0;
145
+ min-height: 0;
146
+ `,
147
+ panel: t.css`
148
+ background: ${t.tokens.color.panel};
149
+ overflow: hidden;
150
+ min-width: 0;
151
+ min-height: 0;
152
+ `,
153
+ toolbar: t.css`
154
+ display: flex;
155
+ flex-wrap: nowrap;
156
+ gap: ${t.tokens.space.s};
157
+ align-items: center;
158
+ height: ${barHeight};
159
+ flex: 0 0 ${barHeight};
160
+ padding: 0 12px;
161
+ overflow-x: auto;
162
+ border-block-end: 1px solid ${t.tokens.color.line};
163
+ h2 {
164
+ margin: 0;
165
+ font-size: 0.8rem;
166
+ font-weight: 600;
167
+ line-height: 1;
168
+ flex: 1;
169
+ white-space: nowrap;
170
+ }
171
+ `,
172
+ segmented: t.css`
173
+ display: inline-flex;
174
+ height: ${controlHeight};
175
+ border: 1px solid ${t.tokens.color.line};
176
+ border-radius: ${t.tokens.radius.s};
177
+ overflow: hidden;
178
+ flex: 0 0 auto;
179
+ button {
180
+ font: inherit;
181
+ font-size: 0.8rem;
182
+ line-height: 1;
183
+ background: transparent;
184
+ color: ${t.tokens.color.ink};
185
+ border: 0;
186
+ height: 100%;
187
+ padding: 0 10px;
188
+ cursor: pointer;
189
+ &[aria-pressed='true'] {
190
+ background: ${t.tokens.color.accent};
191
+ color: #fff;
192
+ }
193
+ }
194
+ `,
195
+ ghost: t.css`
196
+ font: inherit;
197
+ font-size: 0.8rem;
198
+ line-height: 1;
199
+ background: transparent;
200
+ color: ${t.tokens.color.ink};
201
+ border: 0;
202
+ height: ${controlHeight};
203
+ padding: 0 10px;
204
+ cursor: pointer;
205
+ margin-left: auto;
206
+ flex: 0 0 auto;
207
+ `,
208
+ snippetSelect: t.css`
209
+ display: inline-flex;
210
+ gap: 6px;
211
+ align-items: center;
212
+ height: ${controlHeight};
213
+ color: ${t.tokens.color.muted};
214
+ font-size: 0.8rem;
215
+ line-height: 1;
216
+ flex: 0 0 auto;
217
+ white-space: nowrap;
218
+ select {
219
+ font: inherit;
220
+ font-size: 0.8rem;
221
+ line-height: 1;
222
+ color: ${t.tokens.color.ink};
223
+ height: ${controlHeight};
224
+ padding: 0 8px;
225
+ cursor: pointer;
226
+ border: 1px solid ${t.tokens.color.line};
227
+ border-radius: ${t.tokens.radius.s};
228
+ background: ${t.tokens.color.panel};
229
+ }
230
+ `,
231
+ tokens: t.css`
232
+ display: flex;
233
+ flex-direction: column;
234
+ min-height: 0;
235
+ `,
236
+ editor: t.css`
237
+ display: flex;
238
+ flex-direction: column;
239
+ [data-pg-monaco] {
240
+ flex: 1 1 auto;
241
+ min-height: 0;
242
+ width: 100%;
243
+ color-scheme: dark;
244
+ background: ${t.tokens.color.code};
245
+ }
246
+ `,
247
+ cssOut: t.css`
248
+ flex: 1 1 auto;
249
+ min-height: 0;
250
+ width: 100%;
251
+ color-scheme: light;
252
+ background: ${t.tokens.color.bg};
253
+ `,
254
+ cssStats: t.css`
255
+ display: flex;
256
+ flex-wrap: wrap;
257
+ gap: 8px;
258
+ align-items: center;
259
+ margin: 0;
260
+ padding: 6px 12px;
261
+ border-block-end: 1px solid ${t.tokens.color.line};
262
+ color: ${t.tokens.color.muted};
263
+ font-size: 0.75rem;
264
+ line-height: 1.3;
265
+ flex: 0 0 auto;
266
+ a {
267
+ color: ${t.tokens.color.accent};
268
+ text-decoration: none;
269
+ margin-left: auto;
270
+ }
271
+ `,
272
+ previewHost: t.css`
273
+ flex: 1 1 auto;
274
+ min-height: 0;
275
+ overflow: auto;
276
+ `,
277
+ tokenPanel: t.css`
278
+ flex: 1 1 auto;
279
+ min-height: 0;
280
+ padding: 8px 12px 12px;
281
+ overflow: auto;
282
+ `,
283
+ tokenTable: t.css`
284
+ width: 100%;
285
+ border-collapse: collapse;
286
+ font-size: 0.75rem;
287
+ th,
288
+ td {
289
+ text-align: left;
290
+ padding: 5px 10px 5px 0;
291
+ vertical-align: middle;
292
+ }
293
+ th {
294
+ color: ${t.tokens.color.muted};
295
+ font-weight: 600;
296
+ }
297
+ code {
298
+ font-family: ${t.tokens.font.mono};
299
+ font-size: 0.75rem;
300
+ }
301
+ `,
302
+ tokenValue: t.css`
303
+ display: inline-flex;
304
+ flex-wrap: wrap;
305
+ gap: 8px;
306
+ align-items: center;
307
+ color: ${t.tokens.color.muted};
308
+ font-family: ${t.tokens.font.mono};
309
+ `,
310
+ swatch: t.css`
311
+ width: 14px;
312
+ height: 14px;
313
+ border-radius: 3px;
314
+ border: 1px solid ${t.tokens.color.line};
315
+ flex: 0 0 auto;
316
+ &[data-active] {
317
+ outline: 2px solid ${t.tokens.color.accent};
318
+ outline-offset: 1px;
319
+ }
320
+ `,
321
+ callout: t.css`
322
+ margin: 10px;
323
+ padding: 10px 12px;
324
+ border: 1px solid ${t.tokens.color.danger};
325
+ border-radius: ${t.tokens.radius.s};
326
+ color: ${t.tokens.color.danger};
327
+ pre {
328
+ margin: ${t.tokens.space.s} 0 0;
329
+ white-space: pre-wrap;
330
+ font-size: 12px;
331
+ }
332
+ `,
333
+ }));
334
+
335
+ const chromeEmotion = createEmotion(distillery);
336
+
337
+ const installChromeGlobals = (): void =>
338
+ chromeEmotion.injectGlobal`
339
+ :root {
340
+ color-scheme: light dark;
341
+ font-family: ${distillery.tokens.font.sans};
342
+ background: ${distillery.tokens.color.bg};
343
+ color: ${distillery.tokens.color.ink};
344
+ }
345
+ * {
346
+ box-sizing: border-box;
347
+ }
348
+ html,
349
+ body,
350
+ #root {
351
+ margin: 0;
352
+ height: 100%;
353
+ }
354
+ `;
355
+
356
+ installChromeGlobals();
357
+
358
+ /** Readable class names for chrome handles. */
359
+ export const cx = (...handles: readonly StyleHandle[]): string =>
360
+ handles.map((handle) => handle.readableName).join(' ');
361
+
362
+ /** Flushes the chrome stylesheet into `document`. Safe to call once at boot. */
363
+ export const mountChromeStyles = (document: Document): void => {
364
+ createEmotion(distillery, { sink: createDomSink({ document }) });
365
+ };
@@ -0,0 +1,64 @@
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 'monaco-editor/features/register.all.js';
9
+
10
+ import { editor } from 'monaco-editor/editor.js';
11
+ import EditorWorker from 'monaco-editor/editor/editor.worker.js?worker';
12
+ import CssWorker from 'monaco-editor/language/css/css.worker.js?worker';
13
+ import TsWorker from 'monaco-editor/language/typescript/ts.worker.js?worker';
14
+
15
+ export const SOURCE_THEME = 'distillate-code';
16
+ export const CSS_THEME = 'distillate-css';
17
+
18
+ const SOURCE_BG = '#0f141c';
19
+ const SOURCE_FG = '#e6e8f0';
20
+ const CSS_BG = '#f4f6f8';
21
+ const CSS_FG = '#1b1e28';
22
+
23
+ const installMonacoWorkers = (): void => {
24
+ self.MonacoEnvironment = {
25
+ getWorker: (_workerId: string, label: string): Worker => {
26
+ if (label === 'typescript' || label === 'javascript') {
27
+ return new TsWorker();
28
+ }
29
+ if (label === 'css') {
30
+ return new CssWorker();
31
+ }
32
+ return new EditorWorker();
33
+ },
34
+ };
35
+ };
36
+
37
+ let monacoReady = false;
38
+
39
+ /** Installs workers and playground themes. Call once before creating an editor. */
40
+ export const ensureMonaco = (): void => {
41
+ if (monacoReady) {
42
+ return;
43
+ }
44
+ monacoReady = true;
45
+ installMonacoWorkers();
46
+ editor.defineTheme(SOURCE_THEME, {
47
+ base: 'vs-dark',
48
+ inherit: true,
49
+ rules: [],
50
+ colors: {
51
+ 'editor.background': SOURCE_BG,
52
+ 'editor.foreground': SOURCE_FG,
53
+ },
54
+ });
55
+ editor.defineTheme(CSS_THEME, {
56
+ base: 'vs',
57
+ inherit: true,
58
+ rules: [],
59
+ colors: {
60
+ 'editor.background': CSS_BG,
61
+ 'editor.foreground': CSS_FG,
62
+ },
63
+ });
64
+ };
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "jsx": "react-jsx",
7
+ "strict": true,
8
+ "noUncheckedIndexedAccess": true,
9
+ "exactOptionalPropertyTypes": true,
10
+ "skipLibCheck": true,
11
+ "noEmit": true,
12
+ "isolatedModules": true,
13
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
14
+ "types": ["vite/client"],
15
+ "paths": {
16
+ "@elastic/distillate": ["../../src/index.ts"],
17
+ "@elastic/distillate/emotion": ["../../src/emotion.ts"],
18
+ "@elastic/distillate/testing": ["../../src/testing.ts"]
19
+ }
20
+ },
21
+ "include": ["src", "vite.config.ts", "vitest.config.ts"]
22
+ }
@@ -0,0 +1,37 @@
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 react from '@vitejs/plugin-react';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { defineConfig } from 'vite';
11
+
12
+ const src = (relative: string): string =>
13
+ fileURLToPath(new URL(relative, import.meta.url));
14
+
15
+ export default defineConfig({
16
+ base: process.env.PLAYGROUND_BASE ?? '/',
17
+ plugins: [react()],
18
+ worker: {
19
+ format: 'es',
20
+ },
21
+ resolve: {
22
+ alias: [
23
+ {
24
+ find: '@elastic/distillate/testing',
25
+ replacement: src('../../src/testing.ts'),
26
+ },
27
+ {
28
+ find: '@elastic/distillate/emotion',
29
+ replacement: src('../../src/emotion.ts'),
30
+ },
31
+ {
32
+ find: '@elastic/distillate',
33
+ replacement: src('../../src/index.ts'),
34
+ },
35
+ ],
36
+ },
37
+ });
@@ -0,0 +1,35 @@
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 { fileURLToPath } from 'node:url';
9
+ import { defineConfig } from 'vitest/config';
10
+
11
+ const src = (relative: string): string =>
12
+ fileURLToPath(new URL(relative, import.meta.url));
13
+
14
+ export default defineConfig({
15
+ resolve: {
16
+ alias: [
17
+ {
18
+ find: '@elastic/distillate/testing',
19
+ replacement: src('../../src/testing.ts'),
20
+ },
21
+ {
22
+ find: '@elastic/distillate/emotion',
23
+ replacement: src('../../src/emotion.ts'),
24
+ },
25
+ {
26
+ find: '@elastic/distillate',
27
+ replacement: src('../../src/index.ts'),
28
+ },
29
+ ],
30
+ },
31
+ test: {
32
+ environment: 'node',
33
+ include: ['src/**/*.test.ts'],
34
+ },
35
+ });