bertui 1.2.9 → 2.0.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 (183) hide show
  1. package/README.md +44 -242
  2. package/TYPES_PATCH.md +17 -0
  3. package/bin/bertui.js +2 -7
  4. package/package.json +32 -98
  5. package/src/config.ts +4 -0
  6. package/src/index.ts +32 -0
  7. package/src/optional.ts +49 -0
  8. package/src/router.ts +3 -0
  9. package/tsconfig.json +29 -0
  10. package/LICENSE +0 -21
  11. package/index.js +0 -103
  12. package/src/analyzer/index.js +0 -370
  13. package/src/build/compiler/file-transpiler.js +0 -216
  14. package/src/build/compiler/index.js +0 -31
  15. package/src/build/compiler/route-discoverer.js +0 -49
  16. package/src/build/compiler/router-generator.js +0 -105
  17. package/src/build/css-builder.js +0 -81
  18. package/src/build/generators/html-generator.js +0 -263
  19. package/src/build/generators/robots-generator.js +0 -58
  20. package/src/build/generators/sitemap-generator.js +0 -63
  21. package/src/build/image-optimizer.js +0 -137
  22. package/src/build/processors/asset-processor.js +0 -19
  23. package/src/build/processors/css-builder.js +0 -142
  24. package/src/build/server-island-validator.js +0 -67
  25. package/src/build/ssr-renderer.js +0 -64
  26. package/src/build.js +0 -273
  27. package/src/cli.js +0 -131
  28. package/src/client/compiler.js +0 -522
  29. package/src/client/fast-refresh.js +0 -72
  30. package/src/client/hmr-runtime.js +0 -59
  31. package/src/compiler/index.js +0 -25
  32. package/src/compiler/router-generator-pure.js +0 -104
  33. package/src/compiler/transform.js +0 -149
  34. package/src/config/defaultConfig.js +0 -37
  35. package/src/config/index.js +0 -2
  36. package/src/config/loadConfig.js +0 -64
  37. package/src/config/og-image.png +0 -0
  38. package/src/css/index.js +0 -46
  39. package/src/css/processor.js +0 -172
  40. package/src/dev.js +0 -68
  41. package/src/hydration/index.js +0 -151
  42. package/src/image-optimizer/index.js +0 -103
  43. package/src/images/index.js +0 -102
  44. package/src/images/processor.js +0 -169
  45. package/src/layouts/index.js +0 -165
  46. package/src/loading/index.js +0 -210
  47. package/src/logger/logger.js +0 -320
  48. package/src/logger/notes.md +0 -20
  49. package/src/middleware/index.js +0 -182
  50. package/src/router/Router.js +0 -150
  51. package/src/router/SSRRouter.js +0 -156
  52. package/src/router/index.js +0 -3
  53. package/src/scaffolder/index.js +0 -310
  54. package/src/serve.js +0 -193
  55. package/src/server/dev-handler.js +0 -195
  56. package/src/server/dev-server-utils.js +0 -406
  57. package/src/server/dev-server.js +0 -15
  58. package/src/server/hmr-handler.js +0 -148
  59. package/src/server/index.js +0 -3
  60. package/src/server/notes.md +0 -1
  61. package/src/server/request-handler.js +0 -36
  62. package/src/server-islands/extractor.js +0 -198
  63. package/src/server-islands/index.js +0 -59
  64. package/src/styles/bertui.css +0 -210
  65. package/src/utils/cache.js +0 -297
  66. package/src/utils/env.js +0 -87
  67. package/src/utils/importhow.js +0 -52
  68. package/src/utils/index.js +0 -11
  69. package/src/utils/meta-extractor.js +0 -127
  70. package/types/bin/bertui.d.ts +0 -3
  71. package/types/bin/bertui.d.ts.map +0 -1
  72. package/types/error-overlay.d.ts +0 -2
  73. package/types/error-overlay.d.ts.map +0 -1
  74. package/types/index.d.ts +0 -26
  75. package/types/index.d.ts.map +0 -1
  76. package/types/scripts/fix-wasm-exports.d.ts +0 -2
  77. package/types/scripts/fix-wasm-exports.d.ts.map +0 -1
  78. package/types/src/analyzer/index.d.ts +0 -8
  79. package/types/src/analyzer/index.d.ts.map +0 -1
  80. package/types/src/build/compiler/file-transpiler.d.ts +0 -5
  81. package/types/src/build/compiler/file-transpiler.d.ts.map +0 -1
  82. package/types/src/build/compiler/index.d.ts +0 -12
  83. package/types/src/build/compiler/index.d.ts.map +0 -1
  84. package/types/src/build/compiler/route-discoverer.d.ts +0 -2
  85. package/types/src/build/compiler/route-discoverer.d.ts.map +0 -1
  86. package/types/src/build/compiler/router-generator.d.ts +0 -2
  87. package/types/src/build/compiler/router-generator.d.ts.map +0 -1
  88. package/types/src/build/css-builder.d.ts +0 -18
  89. package/types/src/build/css-builder.d.ts.map +0 -1
  90. package/types/src/build/generators/html-generator.d.ts +0 -2
  91. package/types/src/build/generators/html-generator.d.ts.map +0 -1
  92. package/types/src/build/generators/robots-generator.d.ts +0 -11
  93. package/types/src/build/generators/robots-generator.d.ts.map +0 -1
  94. package/types/src/build/generators/sitemap-generator.d.ts +0 -5
  95. package/types/src/build/generators/sitemap-generator.d.ts.map +0 -1
  96. package/types/src/build/image-optimizer.d.ts +0 -11
  97. package/types/src/build/image-optimizer.d.ts.map +0 -1
  98. package/types/src/build/processors/asset-processor.d.ts +0 -2
  99. package/types/src/build/processors/asset-processor.d.ts.map +0 -1
  100. package/types/src/build/processors/css-builder.d.ts +0 -2
  101. package/types/src/build/processors/css-builder.d.ts.map +0 -1
  102. package/types/src/build/server-island-validator.d.ts +0 -27
  103. package/types/src/build/server-island-validator.d.ts.map +0 -1
  104. package/types/src/build.d.ts +0 -5
  105. package/types/src/build.d.ts.map +0 -1
  106. package/types/src/cli.d.ts +0 -2
  107. package/types/src/cli.d.ts.map +0 -1
  108. package/types/src/client/compiler.d.ts +0 -16
  109. package/types/src/client/compiler.d.ts.map +0 -1
  110. package/types/src/client/fast-refresh.d.ts +0 -3
  111. package/types/src/client/fast-refresh.d.ts.map +0 -1
  112. package/types/src/client/hmr-runtime.d.ts +0 -4
  113. package/types/src/client/hmr-runtime.d.ts.map +0 -1
  114. package/types/src/compiler/index.d.ts +0 -8
  115. package/types/src/compiler/index.d.ts.map +0 -1
  116. package/types/src/compiler/router-generator-pure.d.ts +0 -2
  117. package/types/src/compiler/router-generator-pure.d.ts.map +0 -1
  118. package/types/src/compiler/transform.d.ts +0 -36
  119. package/types/src/compiler/transform.d.ts.map +0 -1
  120. package/types/src/config/defaultConfig.d.ts +0 -26
  121. package/types/src/config/defaultConfig.d.ts.map +0 -1
  122. package/types/src/config/index.d.ts +0 -3
  123. package/types/src/config/index.d.ts.map +0 -1
  124. package/types/src/config/loadConfig.d.ts +0 -2
  125. package/types/src/config/loadConfig.d.ts.map +0 -1
  126. package/types/src/css/index.d.ts +0 -6
  127. package/types/src/css/index.d.ts.map +0 -1
  128. package/types/src/css/processor.d.ts +0 -23
  129. package/types/src/css/processor.d.ts.map +0 -1
  130. package/types/src/dev.d.ts +0 -2
  131. package/types/src/dev.d.ts.map +0 -1
  132. package/types/src/hydration/index.d.ts +0 -33
  133. package/types/src/hydration/index.d.ts.map +0 -1
  134. package/types/src/image-optimizer/index.d.ts +0 -24
  135. package/types/src/image-optimizer/index.d.ts.map +0 -1
  136. package/types/src/images/index.d.ts +0 -12
  137. package/types/src/images/index.d.ts.map +0 -1
  138. package/types/src/images/processor.d.ts +0 -30
  139. package/types/src/images/processor.d.ts.map +0 -1
  140. package/types/src/layouts/index.d.ts +0 -28
  141. package/types/src/layouts/index.d.ts.map +0 -1
  142. package/types/src/loading/index.d.ts +0 -28
  143. package/types/src/loading/index.d.ts.map +0 -1
  144. package/types/src/logger/logger.d.ts +0 -30
  145. package/types/src/logger/logger.d.ts.map +0 -1
  146. package/types/src/middleware/index.d.ts +0 -61
  147. package/types/src/middleware/index.d.ts.map +0 -1
  148. package/types/src/router/Router.d.ts +0 -16
  149. package/types/src/router/Router.d.ts.map +0 -1
  150. package/types/src/router/SSRRouter.d.ts +0 -20
  151. package/types/src/router/SSRRouter.d.ts.map +0 -1
  152. package/types/src/router/index.d.ts +0 -3
  153. package/types/src/router/index.d.ts.map +0 -1
  154. package/types/src/scaffolder/index.d.ts +0 -14
  155. package/types/src/scaffolder/index.d.ts.map +0 -1
  156. package/types/src/serve.d.ts +0 -3
  157. package/types/src/serve.d.ts.map +0 -1
  158. package/types/src/server/dev-handler.d.ts +0 -13
  159. package/types/src/server/dev-handler.d.ts.map +0 -1
  160. package/types/src/server/dev-server-utils.d.ts +0 -6
  161. package/types/src/server/dev-server-utils.d.ts.map +0 -1
  162. package/types/src/server/dev-server.d.ts +0 -18
  163. package/types/src/server/dev-server.d.ts.map +0 -1
  164. package/types/src/server/hmr-handler.d.ts +0 -19
  165. package/types/src/server/hmr-handler.d.ts.map +0 -1
  166. package/types/src/server/index.d.ts +0 -4
  167. package/types/src/server/index.d.ts.map +0 -1
  168. package/types/src/server/request-handler.d.ts +0 -19
  169. package/types/src/server/request-handler.d.ts.map +0 -1
  170. package/types/src/server-islands/extractor.d.ts +0 -16
  171. package/types/src/server-islands/extractor.d.ts.map +0 -1
  172. package/types/src/server-islands/index.d.ts +0 -3
  173. package/types/src/server-islands/index.d.ts.map +0 -1
  174. package/types/src/utils/cache.d.ts +0 -52
  175. package/types/src/utils/cache.d.ts.map +0 -1
  176. package/types/src/utils/env.d.ts +0 -20
  177. package/types/src/utils/env.d.ts.map +0 -1
  178. package/types/src/utils/importhow.d.ts +0 -15
  179. package/types/src/utils/importhow.d.ts.map +0 -1
  180. package/types/src/utils/index.d.ts +0 -3
  181. package/types/src/utils/index.d.ts.map +0 -1
  182. package/types/src/utils/meta-extractor.d.ts +0 -13
  183. package/types/src/utils/meta-extractor.d.ts.map +0 -1
@@ -1,198 +0,0 @@
1
- // bertui/src/server-islands/extractor.js - PURE SERVER ISLAND EXTRACTOR
2
- // Extract static HTML from Server Island components
3
-
4
- import logger from '../logger/logger.js';
5
-
6
- /**
7
- * Extract static HTML from a Server Island component
8
- * @param {string} sourceCode - The component source code
9
- * @param {string} filePath - Path to file (for error messages)
10
- * @returns {string|null} Extracted HTML or null if extraction fails
11
- */
12
- export function extractStaticHTML(sourceCode, filePath = 'unknown') {
13
- try {
14
- // Find the return statement
15
- const returnMatch = sourceCode.match(/return\s*\(/);
16
- if (!returnMatch) {
17
- logger.warn(`⚠️ Could not find return statement in ${filePath}`);
18
- return null;
19
- }
20
-
21
- // Get code before return for validation
22
- const codeBeforeReturn = sourceCode.substring(0, returnMatch.index);
23
-
24
- // Check for hooks (disallowed in Server Islands)
25
- const hooks = [
26
- 'useState', 'useEffect', 'useContext', 'useReducer',
27
- 'useCallback', 'useMemo', 'useRef', 'useImperativeHandle',
28
- 'useLayoutEffect', 'useDebugValue', 'useId',
29
- 'useDeferredValue', 'useTransition', 'useSyncExternalStore'
30
- ];
31
-
32
- for (const hook of hooks) {
33
- const hookRegex = new RegExp(`\\b${hook}\\s*\\(`, 'g');
34
- if (hookRegex.test(codeBeforeReturn)) {
35
- logger.error(`❌ Server Island at ${filePath} contains React hook: ${hook}`);
36
- return null;
37
- }
38
- }
39
-
40
- // Check for router imports (disallowed)
41
- if (sourceCode.includes('from \'bertui/router\'') ||
42
- sourceCode.includes('from "bertui/router"')) {
43
- logger.error(`❌ Server Island at ${filePath} imports from 'bertui/router'`);
44
- return null;
45
- }
46
-
47
- // Check for event handlers (disallowed in static HTML)
48
- const eventHandlers = [
49
- 'onClick=', 'onChange=', 'onSubmit=', 'onInput=',
50
- 'onFocus=', 'onBlur=', 'onMouseEnter=', 'onMouseLeave=',
51
- 'onKeyDown=', 'onKeyUp=', 'onScroll='
52
- ];
53
-
54
- for (const handler of eventHandlers) {
55
- if (sourceCode.includes(handler)) {
56
- logger.error(`❌ Server Island at ${filePath} uses event handler: ${handler.replace('=', '')}`);
57
- return null;
58
- }
59
- }
60
-
61
- // Extract the JSX content
62
- const fullReturnMatch = sourceCode.match(/return\s*\(([\s\S]*?)\);?\s*}/);
63
- if (!fullReturnMatch) {
64
- logger.warn(`⚠️ Could not extract JSX from ${filePath}`);
65
- return null;
66
- }
67
-
68
- let html = fullReturnMatch[1].trim();
69
-
70
- // Remove comments
71
- html = html.replace(/\{\/\*[\s\S]*?\*\/\}/g, '');
72
-
73
- // Convert className to class
74
- html = html.replace(/className=/g, 'class=');
75
-
76
- // Convert style objects to inline CSS strings
77
- html = convertStyleObjects(html);
78
-
79
- // Fix self-closing tags
80
- html = fixVoidElements(html);
81
-
82
- // Remove JavaScript expressions
83
- html = removeJSExpressions(html);
84
-
85
- // Clean up whitespace
86
- html = html.replace(/\s+/g, ' ').trim();
87
-
88
- logger.debug(` Extracted ${html.length} chars of static HTML from ${filePath}`);
89
- return html;
90
-
91
- } catch (error) {
92
- logger.error(`Failed to extract HTML from ${filePath}: ${error.message}`);
93
- return null;
94
- }
95
- }
96
-
97
- /**
98
- * Convert React style objects to inline CSS strings
99
- */
100
- function convertStyleObjects(html) {
101
- return html.replace(/style=\{\{([^}]+)\}\}/g, (match, styleObj) => {
102
- try {
103
- // Parse the style object properties
104
- const props = [];
105
- let current = '';
106
- let depth = 0;
107
-
108
- for (let i = 0; i < styleObj.length; i++) {
109
- const char = styleObj[i];
110
- if (char === '(') depth++;
111
- if (char === ')') depth--;
112
-
113
- if (char === ',' && depth === 0) {
114
- props.push(current.trim());
115
- current = '';
116
- } else {
117
- current += char;
118
- }
119
- }
120
- if (current.trim()) props.push(current.trim());
121
-
122
- // Convert to CSS string
123
- const cssString = props
124
- .map(prop => {
125
- const colonIndex = prop.indexOf(':');
126
- if (colonIndex === -1) return '';
127
-
128
- const key = prop.substring(0, colonIndex).trim();
129
- const value = prop.substring(colonIndex + 1).trim();
130
-
131
- if (!key || !value) return '';
132
-
133
- // Convert camelCase to kebab-case
134
- const cssKey = key.replace(/([A-Z])/g, '-$1').toLowerCase();
135
- // Remove quotes from value
136
- const cssValue = value.replace(/['"]/g, '');
137
-
138
- return `${cssKey}: ${cssValue}`;
139
- })
140
- .filter(Boolean)
141
- .join('; ');
142
-
143
- return `style="${cssString}"`;
144
- } catch (e) {
145
- return 'style=""';
146
- }
147
- });
148
- }
149
-
150
- /**
151
- * Fix void elements (self-closing tags)
152
- */
153
- function fixVoidElements(html) {
154
- const voidElements = [
155
- 'area', 'base', 'br', 'col', 'embed', 'hr', 'img',
156
- 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'
157
- ];
158
-
159
- return html.replace(/<(\w+)([^>]*)\s*\/>/g, (match, tag, attrs) => {
160
- if (voidElements.includes(tag.toLowerCase())) {
161
- // Keep self-closing for void elements
162
- return match;
163
- } else {
164
- // Expand to open/close tags for non-void elements
165
- return `<${tag}${attrs}></${tag}>`;
166
- }
167
- });
168
- }
169
-
170
- /**
171
- * Remove JavaScript expressions from JSX
172
- */
173
- function removeJSExpressions(html) {
174
- return html
175
- // Template literals: {`value`} → value
176
- .replace(/\{`([^`]*)`\}/g, '$1')
177
- // String literals: {'value'} or {"value"} → value
178
- .replace(/\{(['"])(.*?)\1\}/g, '$2')
179
- // Number literals: {123} → 123
180
- .replace(/\{(\d+)\}/g, '$1')
181
- // Remove other expressions
182
- .replace(/\{[^}]+\}/g, '');
183
- }
184
-
185
- /**
186
- * Quick check if a file is a Server Island
187
- */
188
- export function isServerIsland(sourceCode) {
189
- return sourceCode.includes('export const render = "server"');
190
- }
191
-
192
- /**
193
- * Extract component name from file
194
- */
195
- export function extractComponentName(filePath) {
196
- const fileName = filePath.split(/[\/\\]/).pop() || '';
197
- return fileName.replace(/\.[^/.]+$/, '');
198
- }
@@ -1,59 +0,0 @@
1
- // bertui/src/server-islands/index.js - NEW FILE
2
- // PURE Server Island extraction - AST-based, not regex
3
-
4
- import { validateServerIsland } from '../build/server-island-validator.js';
5
-
6
- function extractStaticHTML(componentCode) {
7
- // For now, use existing regex-based extractor
8
- // TODO: Replace with proper AST parser
9
- return extractJSXFromReturn(componentCode);
10
- }
11
-
12
- function extractJSXFromReturn(code) {
13
- const returnMatch = code.match(/return\s*\(([\s\S]*?)\);?\s*}/);
14
- if (!returnMatch) return null;
15
-
16
- let html = returnMatch[1].trim();
17
-
18
- // Basic transformations
19
- html = html.replace(/\{\/\*[\s\S]*?\*\/\}/g, '');
20
- html = html.replace(/className=/g, 'class=');
21
-
22
- // Convert style objects to strings
23
- html = html.replace(/style=\{\{([^}]+)\}\}/g, (match, styleObj) => {
24
- const props = styleObj.split(',').map(p => p.trim()).filter(Boolean);
25
- const cssString = props
26
- .map(prop => {
27
- const [key, value] = prop.split(':').map(s => s.trim());
28
- if (!key || !value) return '';
29
- const cssKey = key.replace(/([A-Z])/g, '-$1').toLowerCase();
30
- const cssValue = value.replace(/['"]/g, '');
31
- return `${cssKey}: ${cssValue}`;
32
- })
33
- .filter(Boolean)
34
- .join('; ');
35
- return `style="${cssString}"`;
36
- });
37
-
38
- // Fix void elements
39
- const voidElements = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img',
40
- 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
41
-
42
- html = html.replace(/<(\w+)([^>]*)\s*\/>/g, (match, tag, attrs) => {
43
- if (voidElements.includes(tag.toLowerCase())) {
44
- return match;
45
- }
46
- return `<${tag}${attrs}></${tag}>`;
47
- });
48
-
49
- // Remove JS expressions
50
- html = html.replace(/\{`([^`]*)`\}/g, '$1');
51
- html = html.replace(/\{(['"])(.*?)\1\}/g, '$2');
52
- html = html.replace(/\{(\d+)\}/g, '$1');
53
-
54
- return html;
55
- }
56
-
57
-
58
- export { extractStaticHTML, isServerIsland, extractComponentName } from './extractor.js';
59
- export { validateServerIsland, displayValidationErrors, validateAllServerIslands } from '../build/server-island-validator.js';
@@ -1,210 +0,0 @@
1
- /* BertUI Built-in Utilities v0.1.0 */
2
-
3
- /* Split Text Animation */
4
- .split {
5
- display: inline-block;
6
- position: relative;
7
- overflow: hidden;
8
- }
9
-
10
- .split::before {
11
- content: attr(data-text);
12
- position: absolute;
13
- top: 0;
14
- left: 0;
15
- width: 50%;
16
- overflow: hidden;
17
- animation: split-left 0.6s ease-out;
18
- }
19
-
20
- .split::after {
21
- content: attr(data-text);
22
- position: absolute;
23
- top: 0;
24
- right: 0;
25
- width: 50%;
26
- overflow: hidden;
27
- animation: split-right 0.6s ease-out;
28
- }
29
-
30
- @keyframes split-left {
31
- from {
32
- transform: translateX(-100%);
33
- opacity: 0;
34
- }
35
- to {
36
- transform: translateX(0);
37
- opacity: 1;
38
- }
39
- }
40
-
41
- @keyframes split-right {
42
- from {
43
- transform: translateX(100%);
44
- opacity: 0;
45
- }
46
- to {
47
- transform: translateX(0);
48
- opacity: 1;
49
- }
50
- }
51
-
52
- /* Move Right Animation */
53
- .moveright {
54
- animation: moveright 0.5s ease-out;
55
- }
56
-
57
- @keyframes moveright {
58
- from {
59
- transform: translateX(-20px);
60
- opacity: 0;
61
- }
62
- to {
63
- transform: translateX(0);
64
- opacity: 1;
65
- }
66
- }
67
-
68
- /* Move Left Animation */
69
- .moveleft {
70
- animation: moveleft 0.5s ease-out;
71
- }
72
-
73
- @keyframes moveleft {
74
- from {
75
- transform: translateX(20px);
76
- opacity: 0;
77
- }
78
- to {
79
- transform: translateX(0);
80
- opacity: 1;
81
- }
82
- }
83
-
84
- /* Fade In */
85
- .fadein {
86
- animation: fadein 0.5s ease-out;
87
- }
88
-
89
- @keyframes fadein {
90
- from {
91
- opacity: 0;
92
- }
93
- to {
94
- opacity: 1;
95
- }
96
- }
97
-
98
- /* Scale In */
99
- .scalein {
100
- animation: scalein 0.4s ease-out;
101
- }
102
-
103
- @keyframes scalein {
104
- from {
105
- transform: scale(0.8);
106
- opacity: 0;
107
- }
108
- to {
109
- transform: scale(1);
110
- opacity: 1;
111
- }
112
- }
113
-
114
- /* Bounce In */
115
- .bouncein {
116
- animation: bouncein 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
117
- }
118
-
119
- @keyframes bouncein {
120
- 0% {
121
- transform: scale(0);
122
- opacity: 0;
123
- }
124
- 50% {
125
- transform: scale(1.1);
126
- }
127
- 100% {
128
- transform: scale(1);
129
- opacity: 1;
130
- }
131
- }
132
-
133
- /* Slide Up */
134
- .slideup {
135
- animation: slideup 0.5s ease-out;
136
- }
137
-
138
- @keyframes slideup {
139
- from {
140
- transform: translateY(20px);
141
- opacity: 0;
142
- }
143
- to {
144
- transform: translateY(0);
145
- opacity: 1;
146
- }
147
- }
148
-
149
- /* Slide Down */
150
- .slidedown {
151
- animation: slidedown 0.5s ease-out;
152
- }
153
-
154
- @keyframes slidedown {
155
- from {
156
- transform: translateY(-20px);
157
- opacity: 0;
158
- }
159
- to {
160
- transform: translateY(0);
161
- opacity: 1;
162
- }
163
- }
164
-
165
- /* Rotate In */
166
- .rotatein {
167
- animation: rotatein 0.6s ease-out;
168
- }
169
-
170
- @keyframes rotatein {
171
- from {
172
- transform: rotate(-180deg) scale(0);
173
- opacity: 0;
174
- }
175
- to {
176
- transform: rotate(0) scale(1);
177
- opacity: 1;
178
- }
179
- }
180
-
181
- /* Pulse */
182
- .pulse {
183
- animation: pulse 1.5s ease-in-out infinite;
184
- }
185
-
186
- @keyframes pulse {
187
- 0%, 100% {
188
- transform: scale(1);
189
- }
190
- 50% {
191
- transform: scale(1.05);
192
- }
193
- }
194
-
195
- /* Shake */
196
- .shake {
197
- animation: shake 0.5s ease-in-out;
198
- }
199
-
200
- @keyframes shake {
201
- 0%, 100% {
202
- transform: translateX(0);
203
- }
204
- 10%, 30%, 50%, 70%, 90% {
205
- transform: translateX(-5px);
206
- }
207
- 20%, 40%, 60%, 80% {
208
- transform: translateX(5px);
209
- }
210
- }