@greese/ui 0.0.0-stage → 1.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 (288) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -2
  3. package/bin/greese-utilities.mjs +56 -0
  4. package/dist/_layers.scss +2 -0
  5. package/dist/_maps.scss +1884 -0
  6. package/dist/_tokens-base.scss +174 -0
  7. package/dist/_tokens.scss +2140 -0
  8. package/dist/base.css +67 -0
  9. package/dist/colorScheme.d.ts +16 -0
  10. package/dist/colorScheme.js +13 -0
  11. package/dist/contrast.d.ts +15 -0
  12. package/dist/contrast.js +43 -0
  13. package/dist/css/Accordion.css +9 -0
  14. package/dist/css/ActionSelect.css +6 -0
  15. package/dist/css/Alert.css +84 -0
  16. package/dist/css/AppBar.css +35 -0
  17. package/dist/css/AspectRatio.css +40 -0
  18. package/dist/css/AutoLayout.css +508 -0
  19. package/dist/css/Avatar.css +88 -0
  20. package/dist/css/Badge.css +66 -0
  21. package/dist/css/Box.css +640 -0
  22. package/dist/css/Breadcrumbs.css +57 -0
  23. package/dist/css/Button.css +275 -0
  24. package/dist/css/ButtonGroup.css +40 -0
  25. package/dist/css/Card.css +101 -0
  26. package/dist/css/Carousel.css +170 -0
  27. package/dist/css/Center.css +11 -0
  28. package/dist/css/ChatBubble.css +128 -0
  29. package/dist/css/Checkbox.css +65 -0
  30. package/dist/css/Chip.css +124 -0
  31. package/dist/css/ChoiceGroup.css +57 -0
  32. package/dist/css/Code.css +29 -0
  33. package/dist/css/Collapsible.css +126 -0
  34. package/dist/css/ColorPicker.css +191 -0
  35. package/dist/css/Combobox.css +90 -0
  36. package/dist/css/Container.css +30 -0
  37. package/dist/css/Countdown.css +25 -0
  38. package/dist/css/DateField.css +15 -0
  39. package/dist/css/Dialog.css +640 -0
  40. package/dist/css/Diff.css +103 -0
  41. package/dist/css/Divider.css +19 -0
  42. package/dist/css/Dock.css +91 -0
  43. package/dist/css/Field.css +33 -0
  44. package/dist/css/Fieldset.css +54 -0
  45. package/dist/css/FileInput.css +65 -0
  46. package/dist/css/Footer.css +72 -0
  47. package/dist/css/Grid.css +998 -0
  48. package/dist/css/Header.css +89 -0
  49. package/dist/css/Heading.css +6 -0
  50. package/dist/css/Icon.css +12 -0
  51. package/dist/css/IconButton.css +7 -0
  52. package/dist/css/Image.css +69 -0
  53. package/dist/css/Indicator.css +41 -0
  54. package/dist/css/Input.css +115 -0
  55. package/dist/css/Key.css +42 -0
  56. package/dist/css/Link.css +72 -0
  57. package/dist/css/List.css +52 -0
  58. package/dist/css/Media.css +8 -0
  59. package/dist/css/Menu.css +161 -0
  60. package/dist/css/Motion.css +1356 -0
  61. package/dist/css/NumberField.css +49 -0
  62. package/dist/css/OtpField.css +90 -0
  63. package/dist/css/PageTransition.css +991 -0
  64. package/dist/css/Pagination.css +43 -0
  65. package/dist/css/Popover.css +93 -0
  66. package/dist/css/Progress.css +101 -0
  67. package/dist/css/RadialProgress.css +44 -0
  68. package/dist/css/Radio.css +41 -0
  69. package/dist/css/Rating.css +100 -0
  70. package/dist/css/ScrollSpy.css +6 -0
  71. package/dist/css/SegmentedControl.css +101 -0
  72. package/dist/css/Select.css +115 -0
  73. package/dist/css/Sidebar.css +207 -0
  74. package/dist/css/Skeleton.css +48 -0
  75. package/dist/css/Slider.css +75 -0
  76. package/dist/css/Spacer.css +34 -0
  77. package/dist/css/SpeedDial.css +165 -0
  78. package/dist/css/Spinner.css +44 -0
  79. package/dist/css/Stack.css +528 -0
  80. package/dist/css/Stat.css +107 -0
  81. package/dist/css/Status.css +86 -0
  82. package/dist/css/Steps.css +201 -0
  83. package/dist/css/Swap.css +49 -0
  84. package/dist/css/Switch.css +66 -0
  85. package/dist/css/Table.css +269 -0
  86. package/dist/css/Tabs.css +119 -0
  87. package/dist/css/Text.css +60 -0
  88. package/dist/css/TextRotate.css +147 -0
  89. package/dist/css/Textarea.css +107 -0
  90. package/dist/css/ThemeProvider.css +6 -0
  91. package/dist/css/Tile.css +18 -0
  92. package/dist/css/Toast.css +110 -0
  93. package/dist/css/ToggleButton.css +20 -0
  94. package/dist/css/Tooltip.css +94 -0
  95. package/dist/css/Type.css +211 -0
  96. package/dist/css/Visibility.css +78 -0
  97. package/dist/css/VisuallyHidden.css +15 -0
  98. package/dist/css/core.css +251 -0
  99. package/dist/css.d.ts +29 -0
  100. package/dist/css.js +28 -0
  101. package/dist/effect-classes.d.ts +8 -0
  102. package/dist/effect-classes.js +5 -0
  103. package/dist/effects/css.d.ts +71 -0
  104. package/dist/effects/css.js +184 -0
  105. package/dist/effects/definitions.d.ts +555 -0
  106. package/dist/effects/definitions.js +379 -0
  107. package/dist/effects/frames.d.ts +18 -0
  108. package/dist/effects/frames.js +68 -0
  109. package/dist/effects/sequence.d.ts +33 -0
  110. package/dist/effects/sequence.js +106 -0
  111. package/dist/effects.d.ts +30 -0
  112. package/dist/effects.js +30 -0
  113. package/dist/greese.css +11919 -0
  114. package/dist/index.d.ts +10 -0
  115. package/dist/index.js +10 -0
  116. package/dist/kebab.d.ts +2 -0
  117. package/dist/kebab.js +2 -0
  118. package/dist/palette.css +249 -0
  119. package/dist/palette.d.ts +599 -0
  120. package/dist/palette.js +334 -0
  121. package/dist/shapes.d.ts +193 -0
  122. package/dist/shapes.js +852 -0
  123. package/dist/storage.d.ts +47 -0
  124. package/dist/storage.js +118 -0
  125. package/dist/style-manifest.json +3017 -0
  126. package/dist/theme.d.ts +71 -0
  127. package/dist/theme.js +180 -0
  128. package/dist/tokens.css +253 -0
  129. package/dist/tokens.d.ts +343 -0
  130. package/dist/tokens.js +179 -0
  131. package/dist/typography.d.ts +55 -0
  132. package/dist/typography.js +144 -0
  133. package/dist/utilities.css +6975 -0
  134. package/dist/utilities.d.ts +82 -0
  135. package/dist/utilities.js +636 -0
  136. package/dist/utilitiesFiles.d.ts +18 -0
  137. package/dist/utilitiesFiles.js +26 -0
  138. package/dist/vite.d.ts +40 -0
  139. package/dist/vite.js +43 -0
  140. package/package.json +131 -4
  141. package/src/components/Accordion/Accordion.scss +9 -0
  142. package/src/components/ActionSelect/ActionSelect.scss +6 -0
  143. package/src/components/Alert/Alert.scss +71 -0
  144. package/src/components/AppBar/AppBar.scss +43 -0
  145. package/src/components/AspectRatio/AspectRatio.scss +22 -0
  146. package/src/components/AutoLayout/AutoLayout.scss +90 -0
  147. package/src/components/Avatar/Avatar.scss +91 -0
  148. package/src/components/Badge/Badge.scss +52 -0
  149. package/src/components/Box/Box.scss +63 -0
  150. package/src/components/Breadcrumbs/Breadcrumbs.scss +59 -0
  151. package/src/components/Button/Button.scss +231 -0
  152. package/src/components/ButtonGroup/ButtonGroup.scss +56 -0
  153. package/src/components/Card/Card.scss +99 -0
  154. package/src/components/Carousel/Carousel.scss +161 -0
  155. package/src/components/Center/Center.scss +11 -0
  156. package/src/components/ChatBubble/ChatBubble.scss +119 -0
  157. package/src/components/Checkbox/Checkbox.scss +66 -0
  158. package/src/components/Chip/Chip.scss +119 -0
  159. package/src/components/ChoiceGroup/ChoiceGroup.scss +69 -0
  160. package/src/components/Code/Code.scss +28 -0
  161. package/src/components/Collapsible/Collapsible.scss +136 -0
  162. package/src/components/ColorPicker/ColorPicker.scss +235 -0
  163. package/src/components/Combobox/Combobox.scss +83 -0
  164. package/src/components/Container/Container.scss +28 -0
  165. package/src/components/Countdown/Countdown.scss +28 -0
  166. package/src/components/DateField/DateField.scss +19 -0
  167. package/src/components/Dialog/Dialog.scss +268 -0
  168. package/src/components/Diff/Diff.scss +125 -0
  169. package/src/components/Divider/Divider.scss +22 -0
  170. package/src/components/Dock/Dock.scss +86 -0
  171. package/src/components/Field/Field.scss +38 -0
  172. package/src/components/Fieldset/Fieldset.scss +63 -0
  173. package/src/components/FileInput/FileInput.scss +66 -0
  174. package/src/components/Footer/Footer.scss +79 -0
  175. package/src/components/Grid/Grid.scss +86 -0
  176. package/src/components/Header/Header.scss +111 -0
  177. package/src/components/Heading/Heading.scss +7 -0
  178. package/src/components/Icon/Icon.scss +12 -0
  179. package/src/components/IconButton/IconButton.scss +6 -0
  180. package/src/components/Image/Image.scss +46 -0
  181. package/src/components/Indicator/Indicator.scss +48 -0
  182. package/src/components/Input/Input.scss +58 -0
  183. package/src/components/Key/Key.scss +48 -0
  184. package/src/components/Link/Link.scss +50 -0
  185. package/src/components/List/List.scss +62 -0
  186. package/src/components/Media/Media.scss +7 -0
  187. package/src/components/Menu/Menu.scss +91 -0
  188. package/src/components/Motion/Motion.scss +106 -0
  189. package/src/components/NumberField/NumberField.scss +44 -0
  190. package/src/components/OtpField/OtpField.scss +91 -0
  191. package/src/components/PageTransition/PageTransition.scss +197 -0
  192. package/src/components/Pagination/Pagination.scss +55 -0
  193. package/src/components/Popover/Popover.scss +13 -0
  194. package/src/components/Progress/Progress.scss +126 -0
  195. package/src/components/RadialProgress/RadialProgress.scss +65 -0
  196. package/src/components/Radio/Radio.scss +36 -0
  197. package/src/components/Rating/Rating.scss +121 -0
  198. package/src/components/ScrollSpy/ScrollSpy.scss +6 -0
  199. package/src/components/SegmentedControl/SegmentedControl.scss +107 -0
  200. package/src/components/Select/Select.scss +59 -0
  201. package/src/components/Sidebar/Sidebar.scss +88 -0
  202. package/src/components/Skeleton/Skeleton.scss +60 -0
  203. package/src/components/Slider/Slider.scss +96 -0
  204. package/src/components/Spacer/Spacer.scss +15 -0
  205. package/src/components/SpeedDial/SpeedDial.scss +109 -0
  206. package/src/components/Spinner/Spinner.scss +43 -0
  207. package/src/components/Stack/Stack.scss +57 -0
  208. package/src/components/Stat/Stat.scss +96 -0
  209. package/src/components/Status/Status.scss +60 -0
  210. package/src/components/Steps/Steps.scss +216 -0
  211. package/src/components/Swap/Swap.scss +62 -0
  212. package/src/components/Switch/Switch.scss +63 -0
  213. package/src/components/Table/Table.scss +183 -0
  214. package/src/components/Tabs/Tabs.scss +108 -0
  215. package/src/components/Text/Text.scss +34 -0
  216. package/src/components/TextRotate/TextRotate.scss +51 -0
  217. package/src/components/Textarea/Textarea.scss +56 -0
  218. package/src/components/ThemeProvider/ThemeProvider.scss +7 -0
  219. package/src/components/Tile/Tile.scss +23 -0
  220. package/src/components/Toast/Toast.scss +93 -0
  221. package/src/components/ToggleButton/ToggleButton.scss +23 -0
  222. package/src/components/Tooltip/Tooltip.scss +21 -0
  223. package/src/components/Type/Type.scss +35 -0
  224. package/src/components/Visibility/Visibility.scss +39 -0
  225. package/src/components/VisuallyHidden/VisuallyHidden.scss +17 -0
  226. package/src/styles/_breakpoint-vars.scss +16 -0
  227. package/src/styles/_config.scss +48 -0
  228. package/src/styles/_controls.scss +88 -0
  229. package/src/styles/_core.scss +4 -0
  230. package/src/styles/_effect.scss +51 -0
  231. package/src/styles/_floating.scss +141 -0
  232. package/src/styles/_kit.scss +1548 -0
  233. package/src/styles/_manifest.scss +670 -0
  234. package/src/styles/_mixins.scss +261 -0
  235. package/src/styles/_tones.scss +63 -0
  236. package/src/styles/_type-emit.scss +76 -0
  237. package/src/styles/_typography-vars.scss +8 -0
  238. package/src/styles/base.scss +80 -0
  239. package/src/styles/breakpoints.test.ts +73 -0
  240. package/src/styles/entryPoints.test.ts +68 -0
  241. package/src/styles/index.scss +93 -0
  242. package/src/styles/kit.test.ts +754 -0
  243. package/src/styles/public/_controls.scss +3 -0
  244. package/src/styles/public/_floating.scss +3 -0
  245. package/src/styles/public/_mixins.scss +5 -0
  246. package/src/styles/public/_tones.scss +4 -0
  247. package/themes/bevel.css +1077 -0
  248. package/themes/bevel.scss +1166 -0
  249. package/themes/candy.css +87 -0
  250. package/themes/candy.scss +32 -0
  251. package/themes/depth.css +123 -0
  252. package/themes/depth.scss +46 -0
  253. package/themes/extrude.css +219 -0
  254. package/themes/extrude.scss +255 -0
  255. package/themes/folio.css +986 -0
  256. package/themes/folio.scss +1047 -0
  257. package/themes/forest.css +87 -0
  258. package/themes/forest.scss +32 -0
  259. package/themes/gentle.css +66 -0
  260. package/themes/gentle.scss +39 -0
  261. package/themes/grape.css +87 -0
  262. package/themes/grape.scss +32 -0
  263. package/themes/greese.css +36 -0
  264. package/themes/greese.scss +21 -0
  265. package/themes/mono.css +87 -0
  266. package/themes/mono.scss +32 -0
  267. package/themes/ocean.css +87 -0
  268. package/themes/ocean.scss +32 -0
  269. package/themes/outline.css +127 -0
  270. package/themes/outline.scss +126 -0
  271. package/themes/pebble.css +65 -0
  272. package/themes/pebble.scss +69 -0
  273. package/themes/pocket.css +137 -0
  274. package/themes/pocket.scss +45 -0
  275. package/themes/ridge.css +927 -0
  276. package/themes/ridge.scss +998 -0
  277. package/themes/snappy.css +82 -0
  278. package/themes/snappy.scss +40 -0
  279. package/themes/soft.css +79 -0
  280. package/themes/soft.scss +84 -0
  281. package/themes/sunset.css +87 -0
  282. package/themes/sunset.scss +32 -0
  283. package/themes/ticket.css +960 -0
  284. package/themes/ticket.scss +1031 -0
  285. package/themes/tilt.css +148 -0
  286. package/themes/tilt.scss +169 -0
  287. package/themes/wipe.css +186 -0
  288. package/themes/wipe.scss +46 -0
@@ -0,0 +1,379 @@
1
+ /** The built-in effects' definitions: base effects, combos, and how far they reach. */
2
+ /** Keys every call accepts, in the order positional arguments fill them. */
3
+ export const timingKeys = ['duration', 'offset', 'ease'];
4
+ export const base = (definition) => definition;
5
+ export const px = (fn) => (value) => `${fn}(${typeof value === 'number' ? `${value}px` : value})`;
6
+ export const plain = (fn) => (value) => `${fn}(${value})`;
7
+ export const ZERO = '0px';
8
+ /**
9
+ * Wipes and pockets: a mask that shows everything, anchored at one side (or
10
+ * the middle), sized from `start` to `end`. A mask, not `clip-path`, because
11
+ * the clip belongs to the element's shape and a mask composes with it (ADR
12
+ * 0024); it exists only while the effect plays.
13
+ */
14
+ // Colors by name, not `#000`: greese.js interpolates the numbers in a value,
15
+ // and would write `#000` back as `#0`, dropping the mask.
16
+ export const SOLID = 'linear-gradient(black, black)';
17
+ export const WHOLE = '100% 100%';
18
+ export const masked = (position, start, end) => base({
19
+ property: 'maskSize',
20
+ params: { start, end },
21
+ fixed: { maskImage: SOLID, maskRepeat: 'no-repeat', maskPosition: position },
22
+ });
23
+ /** The directions wipes and pockets go in (physical, like the slides): x, y. */
24
+ export const DIRECTIONS = {
25
+ Right: [1, 0],
26
+ Left: [-1, 0],
27
+ Up: [0, -1],
28
+ Down: [0, 1],
29
+ DownRight: [1, 1],
30
+ DownLeft: [-1, 1],
31
+ UpRight: [1, -1],
32
+ UpLeft: [-1, -1],
33
+ };
34
+ /** The directions wipes and pockets go in, by name: `Right`, `DownLeft`… */
35
+ export const effectDirections = Object.keys(DIRECTIONS);
36
+ /** `50% 0%` for a side: where a direction comes from (`-1`) or goes to (`1`). */
37
+ export const side = (dx, dy, toward) => `${50 + 50 * dx * toward}% ${50 + 50 * dy * toward}%`;
38
+ /** The mask's size with the moving axes at `amount`. */
39
+ export const sized = (dx, dy, amount) => `${dx ? amount : '100%'} ${dy ? amount : '100%'}`;
40
+ /**
41
+ * A wipe in `direction`: arriving, the edge sweeps that way and reveals the
42
+ * element from the side it leaves; leaving, it sweeps that way and covers it.
43
+ */
44
+ export const wipes = Object.fromEntries(Object.entries(DIRECTIONS).flatMap(([name, [dx, dy]]) => [
45
+ [`wipe${name}`, masked(side(dx, dy, -1), sized(dx, dy, '0%'), WHOLE)],
46
+ [`wipeOut${name}`, masked(side(dx, dy, 1), WHOLE, sized(dx, dy, '0%'))],
47
+ ]));
48
+ /**
49
+ * An iris: an opening the element's shape (an ellipse in its proportions)
50
+ * that grows from, or shrinks to, a point: the middle, a side or a corner. The
51
+ * mask is anchored at that point, so it stays put while the opening changes
52
+ * size. `IRIS_OPEN` is where it just covers the farthest corner from any of
53
+ * those points, so the whole run is visible change, in and out alike.
54
+ */
55
+ export const iris = (at, start, end) => base({
56
+ property: 'maskSize',
57
+ params: { start, end },
58
+ fixed: {
59
+ maskImage: `radial-gradient(${at === '50% 50%' ? 'closest-side' : `farthest-side at ${at}`}, black 98%, transparent)`,
60
+ maskRepeat: 'no-repeat',
61
+ maskPosition: at,
62
+ },
63
+ });
64
+ // √2: an ellipse in the element's proportions reaches its far corner at 141.4%.
65
+ export const OPEN = '142% 142%';
66
+ export const SHUT = '0% 0%';
67
+ /**
68
+ * Leaving, the opening closes toward the side it goes to; arriving, it plays
69
+ * that backwards, opening from the same side, so an entrance is its exit
70
+ * reversed.
71
+ */
72
+ export const irises = Object.fromEntries(Object.entries(DIRECTIONS).flatMap(([name, [dx, dy]]) => [
73
+ [`iris${name}`, iris(side(dx, dy, 1), SHUT, OPEN)],
74
+ [`irisOut${name}`, iris(side(dx, dy, 1), OPEN, SHUT)],
75
+ ]));
76
+ /**
77
+ * Three-dimensional turns and depth: `transform`, with its own perspective, so
78
+ * they foreshorten wherever they play, with no `perspective` on a parent. Not
79
+ * the individual `translate`/`rotate`/`scale` the other effects animate, so
80
+ * they compose with those, and never with a shape's clip-path (applied before
81
+ * the transform, it turns with the element).
82
+ */
83
+ export const PERSPECTIVE = 'perspective(800px)';
84
+ export const turn = (axis, start, end, origin) => base({
85
+ property: 'transform',
86
+ params: { start, end },
87
+ format: (v) => `${PERSPECTIVE} rotate${axis}(${v}deg)`,
88
+ ...(origin && { fixed: { transformOrigin: origin } }),
89
+ });
90
+ /** The flips' directions: the axis each turns about, and which way. */
91
+ export const FLIPS = {
92
+ Up: ['X', 1],
93
+ Down: ['X', -1],
94
+ Left: ['Y', 1],
95
+ Right: ['Y', -1],
96
+ };
97
+ /**
98
+ * A flip over: a panel turned half a turn about its middle, its two faces
99
+ * the old and the new: arriving, it turns from its back (180 degrees) to its
100
+ * front; leaving, from its front to its back, the same way, so a pair played
101
+ * together turns as one panel. The back face is hidden, so each shows only
102
+ * while it faces the viewer, and the switch is at the quarter turn. A longer
103
+ * perspective than a flip's, so a panel as wide as the screen doesn't swing
104
+ * through the viewer at the quarter turn.
105
+ */
106
+ export const FLIP_OVER_PERSPECTIVE = 'perspective(2000px)';
107
+ const flipOver = (axis, start, end) => base({
108
+ property: 'transform',
109
+ params: { start, end },
110
+ format: (v) => `${FLIP_OVER_PERSPECTIVE} rotate${axis}(${v}deg)`,
111
+ fixed: { backfaceVisibility: 'hidden' },
112
+ });
113
+ export const flipOvers = Object.fromEntries(Object.entries(FLIPS).flatMap(([name, [axis, sign]]) => [
114
+ [`flipOver${name}`, flipOver(axis, sign * 180, 0)],
115
+ [`flipOverOut${name}`, flipOver(axis, 0, sign * 180)],
116
+ ]));
117
+ export const baseEffects = {
118
+ fadeIn: base({ property: 'opacity', params: { start: 0, end: 1 } }),
119
+ fadeOut: base({ property: 'opacity', params: { start: 1, end: 0 } }),
120
+ scaleIn: base({ property: 'scale', params: { start: 0, end: 1 } }),
121
+ scaleOut: base({ property: 'scale', params: { start: 1, end: 0 } }),
122
+ blurIn: base({ property: 'filter', params: { start: 8, end: 0 }, format: px('blur') }),
123
+ blurOut: base({ property: 'filter', params: { start: 0, end: 8 }, format: px('blur') }),
124
+ slideUp: base({ property: 'y', params: { start: '100%', end: '0%' } }),
125
+ slideDown: base({ property: 'y', params: { start: '-100%', end: '0%' } }),
126
+ // Right and left are physical: the direction the element moves.
127
+ slideRight: base({ property: 'x', params: { start: '-100%', end: '0%' } }),
128
+ slideLeft: base({ property: 'x', params: { start: '100%', end: '0%' } }),
129
+ // A springy scale: past `end` by `peak` at `peakAt` (a share of the effect).
130
+ pop: base({
131
+ property: 'scale',
132
+ params: { start: 1, end: 1, peak: 1.075, peakAt: 0.6 },
133
+ stops: (p) => [
134
+ [0, p.start],
135
+ [Number(p.peakAt), p.peak],
136
+ [1, p.end],
137
+ ],
138
+ }),
139
+ squish: base({ property: 'scale', params: { start: 1, end: 0.96 } }),
140
+ tilt: base({ property: 'rotate', params: { start: 0, end: -2 } }),
141
+ glow: base({
142
+ property: 'filter',
143
+ params: { start: 1, end: 1.12 },
144
+ format: plain('brightness'),
145
+ }),
146
+ // Wipes, every direction (`wipeRight`, `wipeOutUp`, `wipeDownLeft`…),
147
+ // then from and to the middle.
148
+ ...wipes,
149
+ wipeOpenX: masked('50% 50%', '0% 100%', WHOLE),
150
+ wipeOpenY: masked('50% 50%', '100% 0%', WHOLE),
151
+ wipeCloseX: masked('50% 50%', WHOLE, '0% 100%'),
152
+ wipeCloseY: masked('50% 50%', WHOLE, '100% 0%'),
153
+ // Irises, from and to the middle, then every direction (`irisRight`, `irisOutUpLeft`…).
154
+ irisIn: iris('50% 50%', SHUT, OPEN),
155
+ irisOut: iris('50% 50%', OPEN, SHUT),
156
+ ...irises,
157
+ // In three dimensions: a turn about the horizontal (`turnX`) or vertical
158
+ // (`turnY`) axis through the middle, and a move along the line of sight
159
+ // (`depth`, in px: negative is away).
160
+ turnX: turn('X', 0, 0),
161
+ turnY: turn('Y', 0, 0),
162
+ depth: base({
163
+ property: 'transform',
164
+ params: { start: 0, end: 0 },
165
+ format: (v) => `${PERSPECTIVE} translateZ(${v}px)`,
166
+ }),
167
+ // A hinge along the top edge, like a sign swinging down into place.
168
+ hinge: turn('X', 0, 0, '50% 0%'),
169
+ // Half turns, a panel's two faces (`flipOverRight`, `flipOverOutLeft`…).
170
+ ...flipOvers,
171
+ };
172
+ /** `effect` must be a base effect's name: a typo, or a combo, fails to compile. */
173
+ export const part = (effect, args = {}, at = [0, 1]) => ({ effect, args, at });
174
+ export const combo = (definition) => definition;
175
+ export const away = ({ distance }) => ({ distance });
176
+ /**
177
+ * A pocket: the element moves out of (or into) an invisible slot at one of
178
+ * its own edges. It slides `distance` (its whole size, by default, so it
179
+ * starts or ends out of sight) while a mask anchored where it's going grows or
180
+ * shrinks by the same amount, so the window it shows through stays where the
181
+ * element rests. Arriving, it moves `direction`; leaving, it moves on that
182
+ * way, into the slot on that side.
183
+ */
184
+ export const pocket = (direction, leaving) => {
185
+ const [dx, dy] = DIRECTIONS[direction];
186
+ return {
187
+ params: () => ({ distance: '100%' }),
188
+ parts: ({ distance }) => {
189
+ const far = (sign) => sign > 0 ? String(distance) : negate(String(distance));
190
+ const slide = (axis, sign) => {
191
+ const travel = {
192
+ start: leaving ? ZERO : far(-sign),
193
+ end: leaving ? far(sign) : ZERO,
194
+ };
195
+ return axis === 'x' ? part('slideRight', travel) : part('slideDown', travel);
196
+ };
197
+ // A share of its size (the default, 100%) is plain percentages, which
198
+ // every engine transitions; any other length is calc() at both ends,
199
+ // the same shape, so greese.js interpolates them.
200
+ const share = /^(-?[\d.]+)%$/.exec(String(distance).trim());
201
+ const short = sized(dx, dy, share ? `${100 - Number(share[1])}%` : `calc(100% - ${distance})`);
202
+ const full = sized(dx, dy, share ? '100%' : 'calc(100% - 0px)');
203
+ return [
204
+ ...(dx ? [slide('x', dx)] : []),
205
+ ...(dy ? [slide('y', dy)] : []),
206
+ // Arriving, the window is anchored at the side it moves toward; leaving, the side it leaves.
207
+ leaving
208
+ ? part(`wipe${direction}`, { start: full, end: short })
209
+ : part(`wipeOut${direction}`, { start: short, end: full }),
210
+ ];
211
+ },
212
+ };
213
+ };
214
+ export const pockets = Object.fromEntries(Object.keys(DIRECTIONS).flatMap((name) => [
215
+ [`pocket${name}`, pocket(name, false)],
216
+ [`pocketOut${name}`, pocket(name, true)],
217
+ ]));
218
+ /**
219
+ * A flip: the element turns into place about its middle, from `angle` degrees
220
+ * (75 by default) toward the direction it arrives in: `flipUp` rises, its
221
+ * bottom edge leading; `flipRight` swings in from the left. Leaving, it turns
222
+ * back out the same way.
223
+ */
224
+ export const flips = Object.fromEntries(Object.entries(FLIPS).flatMap(([name, [axis, sign]]) => {
225
+ const effect = `turn${axis}`;
226
+ return [
227
+ [
228
+ `flip${name}`,
229
+ combo({
230
+ params: () => ({ angle: 75 }),
231
+ parts: (p) => [
232
+ part('fadeIn', {}, [0, 0.5]),
233
+ part(effect, { start: sign * Number(p.angle), end: 0 }),
234
+ ],
235
+ }),
236
+ ],
237
+ [
238
+ `flipOut${name}`,
239
+ combo({
240
+ params: () => ({ angle: 75 }),
241
+ parts: (p) => [
242
+ part('fadeOut', {}, [0.5, 1]),
243
+ part(effect, { start: 0, end: sign * Number(p.angle) }),
244
+ ],
245
+ }),
246
+ ],
247
+ ];
248
+ }));
249
+ export const comboEffects = {
250
+ fadeUp: combo({
251
+ params: away,
252
+ parts: (p) => [part('fadeIn'), part('slideUp', { start: p.distance, end: ZERO })],
253
+ }),
254
+ fadeDown: combo({
255
+ params: away,
256
+ parts: (p, r) => [
257
+ part('fadeIn'),
258
+ part('slideDown', { start: r.negate(String(p.distance)), end: ZERO }),
259
+ ],
260
+ }),
261
+ fadeStart: combo({
262
+ params: away,
263
+ parts: (p, r) => [
264
+ part('fadeIn'),
265
+ part('slideRight', { start: r.start(String(p.distance)), end: ZERO }),
266
+ ],
267
+ }),
268
+ fadeEnd: combo({
269
+ params: away,
270
+ parts: (p, r) => [
271
+ part('fadeIn'),
272
+ part('slideLeft', { start: r.end(String(p.distance)), end: ZERO }),
273
+ ],
274
+ }),
275
+ fadeOutUp: combo({
276
+ params: away,
277
+ parts: (p, r) => [
278
+ part('fadeOut'),
279
+ part('slideUp', { start: ZERO, end: r.negate(String(p.distance)) }),
280
+ ],
281
+ }),
282
+ fadeOutDown: combo({
283
+ params: away,
284
+ parts: (p) => [part('fadeOut'), part('slideDown', { start: ZERO, end: p.distance })],
285
+ }),
286
+ popIn: combo({
287
+ params: () => ({ start: 0.8, peak: 1.04, peakAt: 0.6 }),
288
+ parts: (p) => [
289
+ part('pop', { start: p.start, peak: p.peak, peakAt: p.peakAt }),
290
+ part('fadeIn', {}, [0, Number(p.peakAt)]),
291
+ ],
292
+ }),
293
+ popOut: combo({
294
+ params: () => ({ end: 0.8, peak: 1.04, peakAt: 0.4 }),
295
+ parts: (p) => [
296
+ part('pop', { start: 1, end: p.end, peak: p.peak, peakAt: p.peakAt }),
297
+ part('fadeOut', {}, [Number(p.peakAt), 1]),
298
+ ],
299
+ }),
300
+ rise: combo({
301
+ params: () => ({ lift: -4, scale: 1.02 }),
302
+ parts: (p) => [
303
+ part('slideUp', { start: 0, end: p.lift }),
304
+ part('scaleIn', { start: 1, end: p.scale }),
305
+ ],
306
+ }),
307
+ fall: combo({
308
+ params: () => ({ drop: 4, scale: 0.98 }),
309
+ parts: (p) => [
310
+ part('slideDown', { start: 0, end: p.drop }),
311
+ part('scaleOut', { start: 1, end: p.scale }),
312
+ ],
313
+ }),
314
+ // Pockets, every direction, arriving and leaving.
315
+ ...pockets,
316
+ // Flips, depth and swings: three-dimensional, each leaving as its arrival
317
+ // reversed (`flipOutUp` turns back down the way `flipUp` came).
318
+ ...flips,
319
+ depthIn: combo({
320
+ params: () => ({ depth: -240 }),
321
+ parts: (p) => [
322
+ part('fadeIn', {}, [0, 0.6]),
323
+ part('depth', { start: p.depth, end: 0 }),
324
+ ],
325
+ }),
326
+ depthOut: combo({
327
+ params: () => ({ depth: -240 }),
328
+ parts: (p) => [
329
+ part('fadeOut', {}, [0.4, 1]),
330
+ part('depth', { start: 0, end: p.depth }),
331
+ ],
332
+ }),
333
+ swingIn: combo({
334
+ params: () => ({ angle: -80 }),
335
+ parts: (p) => [
336
+ part('fadeIn', {}, [0, 0.5]),
337
+ part('hinge', { start: p.angle, end: 0 }),
338
+ ],
339
+ }),
340
+ swingOut: combo({
341
+ params: () => ({ angle: -80 }),
342
+ parts: (p) => [
343
+ part('fadeOut', {}, [0.5, 1]),
344
+ part('hinge', { start: 0, end: p.angle }),
345
+ ],
346
+ }),
347
+ };
348
+ /** Base effects and combos together: every effect the library ships. */
349
+ export const builtInEffects = { ...baseEffects, ...comboEffects };
350
+ /** Every built-in effect name, base effects first. */
351
+ export const effectNames = Object.keys(builtInEffects);
352
+ /** Own keys only, so `constructor` is no effect. */
353
+ export const isBuiltInEffect = (name) => Object.hasOwn(builtInEffects, name);
354
+ export const isBase = (name) => Object.hasOwn(baseEffects, name);
355
+ export const PLAIN = /^-?[\d.]+[a-z%]*$/i;
356
+ /**
357
+ * A length the other way. Plain ones (`1rem`, `-12px`) flip textually,
358
+ * anything else (`calc(…)`, `var(…)`) through `calc()`.
359
+ */
360
+ export const negate = (length) => PLAIN.test(length)
361
+ ? length.startsWith('-')
362
+ ? length.slice(1)
363
+ : `-${length}`
364
+ : `calc(-1 * ${length})`;
365
+ /** The reach for JavaScript: lengths, flipped when the element is right to left. */
366
+ export const jsReach = (distance, rtl) => ({
367
+ distance,
368
+ negate,
369
+ start: (length) => (rtl ? length : negate(length)),
370
+ end: (length) => (rtl ? negate(length) : length),
371
+ });
372
+ export const CSS_DIR = 'var(--greese-motion-dir, 1)';
373
+ /** The reach for CSS: `--greese-motion-dir` is 1, or -1 in right-to-left (Motion.scss). */
374
+ export const cssReach = {
375
+ distance: 'var(--greese-motion-distance, 1rem)',
376
+ negate,
377
+ start: (length) => `calc(-1 * ${CSS_DIR} * ${length})`,
378
+ end: (length) => `calc(${CSS_DIR} * ${length})`,
379
+ };
@@ -0,0 +1,18 @@
1
+ /** An effect call as greese.js keyframes: its parts' tracks, resolved for a reach. */
2
+ import { type BuiltInEffect, type EffectFrames, type Reach, type Stop, type Value } from './definitions.ts';
3
+ export type Track = {
4
+ property: string;
5
+ stops: Stop[];
6
+ };
7
+ export declare const round: (offset: number) => number;
8
+ export declare const tracksOf: (name: BuiltInEffect, args: Record<string, Value | undefined>, reach: Reach) => Track[];
9
+ /** Properties with evenly spaced stops are written as `{ property: [values] }`, else as a list of frames. */
10
+ export declare const framesOf: (tracks: Track[]) => EffectFrames;
11
+ /**
12
+ * An effect's keyframes for a reach and arguments (parameter names to values).
13
+ * Defaults to a left-to-right `1rem` and every parameter's default, which is
14
+ * what tools that show or edit the effects want.
15
+ */
16
+ export declare const effectFrames: (name: BuiltInEffect, reach?: Reach, args?: Record<string, Value | undefined>) => EffectFrames;
17
+ /** The parameters an effect has, then the timing keys: the order positional arguments fill. */
18
+ export declare const effectParamNames: (name: string) => string[];
@@ -0,0 +1,68 @@
1
+ /** An effect call as greese.js keyframes: its parts' tracks, resolved for a reach. */
2
+ import { baseEffects, builtInEffects, comboEffects, cssReach, isBase, isBuiltInEffect, jsReach, timingKeys, } from "./definitions.js";
3
+ export const round = (offset) => Math.round(offset * 10_000) / 10_000;
4
+ export const tracksOf = (name, args, reach) => {
5
+ const definition = builtInEffects[name];
6
+ const defaults = isBase(name)
7
+ ? baseEffects[name].params
8
+ : definition.params(reach);
9
+ const params = { ...defaults };
10
+ for (const key of Object.keys(defaults))
11
+ if (args[key] !== undefined)
12
+ params[key] = args[key];
13
+ if (isBase(name)) {
14
+ const { stops, format, property, fixed } = baseEffects[name];
15
+ const at = stops
16
+ ? stops(params)
17
+ : [
18
+ [0, params.start],
19
+ [1, params.end],
20
+ ];
21
+ return [
22
+ {
23
+ property,
24
+ stops: at.map(([offset, value]) => [offset, format ? format(value) : value]),
25
+ },
26
+ ...Object.entries(fixed ?? {}).map(([prop, value]) => ({
27
+ property: prop,
28
+ stops: [
29
+ [0, value],
30
+ [1, value],
31
+ ],
32
+ })),
33
+ ];
34
+ }
35
+ return definition.parts(params, reach).flatMap((p) => tracksOf(p.effect, p.args, reach).map(({ property, stops }) => ({
36
+ property,
37
+ stops: stops.map(([offset, value]) => [round(p.at[0] + offset * (p.at[1] - p.at[0])), value]),
38
+ })));
39
+ };
40
+ /** Properties with evenly spaced stops are written as `{ property: [values] }`, else as a list of frames. */
41
+ export const framesOf = (tracks) => {
42
+ const even = tracks.every(({ stops }) => stops.length > 1 &&
43
+ stops.every(([offset], i) => round(offset) === round(i / (stops.length - 1))));
44
+ if (even)
45
+ return Object.fromEntries(tracks.map(({ property, stops }) => [property, stops.map(([, value]) => value)]));
46
+ const at = new Map();
47
+ for (const { property, stops } of tracks)
48
+ for (const [offset, value] of stops) {
49
+ const key = round(offset);
50
+ at.set(key, { ...at.get(key), [property]: value });
51
+ }
52
+ return [...at]
53
+ .sort(([a], [b]) => a - b)
54
+ .map(([offset, values]) => ({ ...values, offset }));
55
+ };
56
+ /**
57
+ * An effect's keyframes for a reach and arguments (parameter names to values).
58
+ * Defaults to a left-to-right `1rem` and every parameter's default, which is
59
+ * what tools that show or edit the effects want.
60
+ */
61
+ export const effectFrames = (name, reach = jsReach('1rem', false), args = {}) => framesOf(tracksOf(name, args, reach));
62
+ /** The parameters an effect has, then the timing keys: the order positional arguments fill. */
63
+ export const effectParamNames = (name) => isBuiltInEffect(name)
64
+ ? [
65
+ ...Object.keys(isBase(name) ? baseEffects[name].params : comboEffects[name].params(cssReach)),
66
+ ...timingKeys,
67
+ ]
68
+ : [...timingKeys];
@@ -0,0 +1,33 @@
1
+ /** Sequence strings (`'fadeIn+scaleIn,+1,pop'`): steps, calls and their arguments. */
2
+ import { type Timing, type Value } from './definitions.ts';
3
+ /** One effect in a sequence, with the arguments written for it. */
4
+ export interface EffectCall {
5
+ name: string;
6
+ args: Record<string, Value>;
7
+ }
8
+ /** A step of a sequence: effects that play together, or a pause in seconds. */
9
+ export type EffectStep = EffectCall[] | number;
10
+ /** Splits at `separator` outside brackets, braces, parentheses and quotes. */
11
+ export declare const splitTop: (text: string, separator: string) => string[];
12
+ export declare const NUMBER: RegExp;
13
+ export declare const valueOf: (text: string) => Value;
14
+ export declare const NAMED: RegExp;
15
+ /**
16
+ * `0.25, 0.8, { duration: 1 }`: positional values fill the effect's parameters
17
+ * in order, `key: value` (or `key=value`) sets one by name, and an object sets
18
+ * several. Only what is written is set.
19
+ */
20
+ export declare const parseArgs: (name: string, text: string) => Record<string, Value>;
21
+ export declare const CALL: RegExp;
22
+ /**
23
+ * Parses `'fadeIn(0.25)+scaleIn,+2,fadeOut({ duration: 1 })'`: commas separate
24
+ * steps that play in turn, `+` joins effects that play together, a number is a
25
+ * pause, and a negative one (`-0.2`) backs the next step up, so it overlaps
26
+ * the last. An effect may be followed by arguments in parentheses.
27
+ */
28
+ export declare const parseSequence: (sequence: string) => EffectStep[];
29
+ /** A call's timing keys, apart from the effect's own parameters. */
30
+ export declare const splitTiming: (args: Record<string, Value>) => {
31
+ timing: Timing;
32
+ params: Record<string, Value>;
33
+ };
@@ -0,0 +1,106 @@
1
+ /** Sequence strings (`'fadeIn+scaleIn,+1,pop'`): steps, calls and their arguments. */
2
+ import {} from "./definitions.js";
3
+ import { effectParamNames } from "./frames.js";
4
+ /** Splits at `separator` outside brackets, braces, parentheses and quotes. */
5
+ export const splitTop = (text, separator) => {
6
+ const parts = [];
7
+ let depth = 0;
8
+ let quote = '';
9
+ let start = 0;
10
+ for (let i = 0; i < text.length; i++) {
11
+ const c = text[i];
12
+ if (quote) {
13
+ if (c === quote)
14
+ quote = '';
15
+ }
16
+ else if (c === '"' || c === "'")
17
+ quote = c;
18
+ else if ('([{'.includes(c))
19
+ depth++;
20
+ else if (')]}'.includes(c))
21
+ depth--;
22
+ else if (c === separator && depth === 0) {
23
+ parts.push(text.slice(start, i));
24
+ start = i + 1;
25
+ }
26
+ }
27
+ parts.push(text.slice(start));
28
+ return parts;
29
+ };
30
+ export const NUMBER = /^[+-]?(\d+\.?\d*|\.\d+)$/;
31
+ export const valueOf = (text) => {
32
+ const value = text.trim().replace(/^(['"])(.*)\1$/, '$2');
33
+ return NUMBER.test(value) ? Number(value) : value;
34
+ };
35
+ export const NAMED = /^([A-Za-z_$][\w$]*)\s*[:=]\s*([\s\S]+)$/;
36
+ /**
37
+ * `0.25, 0.8, { duration: 1 }`: positional values fill the effect's parameters
38
+ * in order, `key: value` (or `key=value`) sets one by name, and an object sets
39
+ * several. Only what is written is set.
40
+ */
41
+ export const parseArgs = (name, text) => {
42
+ const names = effectParamNames(name);
43
+ const args = {};
44
+ let next = 0;
45
+ const set = (key, value) => {
46
+ args[key] = valueOf(value);
47
+ };
48
+ for (const raw of splitTop(text, ',')) {
49
+ const arg = raw.trim();
50
+ if (!arg)
51
+ continue;
52
+ if (arg.startsWith('{') && arg.endsWith('}')) {
53
+ for (const entry of splitTop(arg.slice(1, -1), ',')) {
54
+ const named = NAMED.exec(entry.trim());
55
+ if (named)
56
+ set(named[1], named[2]);
57
+ }
58
+ }
59
+ else {
60
+ const named = NAMED.exec(arg);
61
+ if (named)
62
+ set(named[1], named[2]);
63
+ else if (names[next])
64
+ set(names[next++], arg);
65
+ }
66
+ }
67
+ return args;
68
+ };
69
+ export const CALL = /^([A-Za-z_$][\w$]*)\s*(?:\(([\s\S]*)\))?$/;
70
+ /**
71
+ * Parses `'fadeIn(0.25)+scaleIn,+2,fadeOut({ duration: 1 })'`: commas separate
72
+ * steps that play in turn, `+` joins effects that play together, a number is a
73
+ * pause, and a negative one (`-0.2`) backs the next step up, so it overlaps
74
+ * the last. An effect may be followed by arguments in parentheses.
75
+ */
76
+ export const parseSequence = (sequence) => {
77
+ const steps = [];
78
+ for (const raw of splitTop(sequence, ',')) {
79
+ const step = raw.trim();
80
+ if (NUMBER.test(step))
81
+ steps.push(Number(step));
82
+ else if (step)
83
+ steps.push(splitTop(step, '+')
84
+ .map((call) => call.trim())
85
+ .filter(Boolean)
86
+ .map((call) => {
87
+ const match = CALL.exec(call);
88
+ return match
89
+ ? { name: match[1], args: parseArgs(match[1], match[2] ?? '') }
90
+ : { name: call, args: {} };
91
+ }));
92
+ }
93
+ return steps;
94
+ };
95
+ /** A call's timing keys, apart from the effect's own parameters. */
96
+ export const splitTiming = (args) => {
97
+ const { duration, offset, ease, ...params } = args;
98
+ const timing = {};
99
+ if (duration !== undefined && Number.isFinite(Number(duration)))
100
+ timing.duration = Number(duration);
101
+ if (offset !== undefined && Number.isFinite(Number(offset)))
102
+ timing.offset = Number(offset);
103
+ if (ease !== undefined)
104
+ timing.ease = String(ease);
105
+ return { timing, params };
106
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The built-in effects of the `greese` prop: the one place they are defined.
3
+ *
4
+ * - **Base effects** animate one property each (opacity, scale, a translation,
5
+ * a filter…) and take optional parameters: `start`, `end` and whatever else
6
+ * they need, each with a default. `fadeIn` fades from 0 to 1; `fadeIn(0.25,
7
+ * 0.8)` or `fadeIn({ end: 0.8 })` changes that.
8
+ * - **Combo effects** are made of base effects, by name (typed against
9
+ * `baseEffects`), each placed in time as a share of the combo: `popIn` is
10
+ * `pop` plus a `fadeIn` over its first 60%.
11
+ *
12
+ * Every call also takes the timing keys `duration` and `offset` (seconds) and
13
+ * `ease`, after the effect's own parameters when given by position:
14
+ * `someEffect(start, end, duration, offset, ease)`.
15
+ *
16
+ * Nothing else lists the effects. The runtime plays what this file says; the
17
+ * build writes every effect that ends at the element's resting state as CSS
18
+ * (`@keyframes greese-<name>`) and every one that ends away from it as an
19
+ * overlay exit (`dist/_maps.scss`); the name types and Theme Studio's lists are
20
+ * derived; an effect Studio defines is turned into the same CSS by the same
21
+ * `cssPlan()`. To add an effect, add it here.
22
+ *
23
+ * Its modules (effects/) import nothing but each other and `kebab.ts` (which
24
+ * imports nothing, so the runtime chunk carries no tokens): the build script
25
+ * runs them directly under Node's type stripping.
26
+ */
27
+ export { baseEffects, builtInEffects, comboEffects, cssReach, effectDirections, effectNames, isBuiltInEffect, jsReach, negate, timingKeys, type BaseArgs, type BaseEffect, type BuiltInEffect, type ComboEffect, type EffectFrames, type Reach, type Timing, } from './effects/definitions.ts';
28
+ export { effectFrames, effectParamNames } from './effects/frames.ts';
29
+ export { parseSequence, splitTiming, type EffectCall, type EffectStep, } from './effects/sequence.ts';
30
+ export { cssPlan, effectClass, effectCss, effectPlan, endsHidden, entranceNames, exitNames, toCssSteps, type CssPlan, type CssStep, } from './effects/css.ts';
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The built-in effects of the `greese` prop: the one place they are defined.
3
+ *
4
+ * - **Base effects** animate one property each (opacity, scale, a translation,
5
+ * a filter…) and take optional parameters: `start`, `end` and whatever else
6
+ * they need, each with a default. `fadeIn` fades from 0 to 1; `fadeIn(0.25,
7
+ * 0.8)` or `fadeIn({ end: 0.8 })` changes that.
8
+ * - **Combo effects** are made of base effects, by name (typed against
9
+ * `baseEffects`), each placed in time as a share of the combo: `popIn` is
10
+ * `pop` plus a `fadeIn` over its first 60%.
11
+ *
12
+ * Every call also takes the timing keys `duration` and `offset` (seconds) and
13
+ * `ease`, after the effect's own parameters when given by position:
14
+ * `someEffect(start, end, duration, offset, ease)`.
15
+ *
16
+ * Nothing else lists the effects. The runtime plays what this file says; the
17
+ * build writes every effect that ends at the element's resting state as CSS
18
+ * (`@keyframes greese-<name>`) and every one that ends away from it as an
19
+ * overlay exit (`dist/_maps.scss`); the name types and Theme Studio's lists are
20
+ * derived; an effect Studio defines is turned into the same CSS by the same
21
+ * `cssPlan()`. To add an effect, add it here.
22
+ *
23
+ * Its modules (effects/) import nothing but each other and `kebab.ts` (which
24
+ * imports nothing, so the runtime chunk carries no tokens): the build script
25
+ * runs them directly under Node's type stripping.
26
+ */
27
+ export { baseEffects, builtInEffects, comboEffects, cssReach, effectDirections, effectNames, isBuiltInEffect, jsReach, negate, timingKeys, } from "./effects/definitions.js";
28
+ export { effectFrames, effectParamNames } from "./effects/frames.js";
29
+ export { parseSequence, splitTiming, } from "./effects/sequence.js";
30
+ export { cssPlan, effectClass, effectCss, effectPlan, endsHidden, entranceNames, exitNames, toCssSteps, } from "./effects/css.js";