@luna_ui/luna 0.11.0 → 0.17.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 (86) hide show
  1. package/dist/api-DAWeanTX.js +1 -0
  2. package/dist/api-qXll116-.d.ts +80 -0
  3. package/dist/cli.mjs +27 -22
  4. package/dist/css/index.js +1 -0
  5. package/dist/event-utils.d.ts +1 -1
  6. package/dist/event-utils.js +1 -1
  7. package/dist/{index-BZoM-af5.d.ts → index-VY8G32hr.d.ts} +16 -76
  8. package/dist/index.d.ts +4 -3
  9. package/dist/index.js +1 -1
  10. package/dist/jsx-dev-runtime.js +1 -1
  11. package/dist/jsx-runtime.d.ts +1 -1
  12. package/dist/jsx-runtime.js +1 -1
  13. package/dist/raw.d.ts +2 -0
  14. package/dist/raw.js +1 -0
  15. package/dist/resource.d.ts +41 -0
  16. package/dist/resource.js +1 -0
  17. package/dist/router-lite.d.ts +44 -0
  18. package/dist/router-lite.js +1 -0
  19. package/dist/signals-shared.d.ts +12 -0
  20. package/dist/signals-shared.js +1 -0
  21. package/dist/signals.d.ts +2 -3
  22. package/dist/signals.js +1 -1
  23. package/dist/vite-plugin.d.ts +7708 -2
  24. package/dist/vite-plugin.js +7 -6
  25. package/package.json +30 -11
  26. package/dist/event-utils-9cHYnvun.js +0 -1
  27. package/dist/src-BFWjzzPo.js +0 -1
  28. package/src/css/extract.ts +0 -798
  29. package/src/css/index.ts +0 -10
  30. package/src/css/inject.ts +0 -205
  31. package/src/css/inline.ts +0 -182
  32. package/src/css/minify.ts +0 -70
  33. package/src/css/optimizer.ts +0 -6
  34. package/src/css/runtime.ts +0 -344
  35. package/src/css-optimizer/README.md +0 -353
  36. package/src/css-optimizer/cooccurrence.ts +0 -100
  37. package/src/css-optimizer/core.ts +0 -263
  38. package/src/css-optimizer/extractors.ts +0 -243
  39. package/src/css-optimizer/hash.ts +0 -54
  40. package/src/css-optimizer/index.ts +0 -129
  41. package/src/css-optimizer/merge.ts +0 -109
  42. package/src/css-optimizer/moonbit-analyzer.ts +0 -210
  43. package/src/css-optimizer/parser.ts +0 -120
  44. package/src/css-optimizer/pattern.ts +0 -171
  45. package/src/css-optimizer/transformers.ts +0 -301
  46. package/src/css-optimizer/types.ts +0 -128
  47. package/src/event-utils.ts +0 -227
  48. package/src/hydration/createHydrator.ts +0 -62
  49. package/src/hydration/delegate.ts +0 -62
  50. package/src/hydration/drag.ts +0 -214
  51. package/src/hydration/index.ts +0 -12
  52. package/src/hydration/keyboard.ts +0 -64
  53. package/src/hydration/toggle.ts +0 -101
  54. package/src/index.ts +0 -908
  55. package/src/jsx-dev-runtime.ts +0 -2
  56. package/src/jsx-runtime.ts +0 -398
  57. package/src/signals.ts +0 -113
  58. package/src/vite-plugin.ts +0 -718
  59. package/tests/__screenshots__/apg.test.ts/APG-Components---Accessibility-Tests-Button-Pattern-disabled-button-has-aria-disabled-1.png +0 -0
  60. package/tests/__screenshots__/resource.test.ts/Resource-API--SolidJS-style--createResource-error-is-undefined-when-pending-1.png +0 -0
  61. package/tests/__screenshots__/resource.test.ts/Resource-API--SolidJS-style--createResource-transitions-to-success-on-resolve-1.png +0 -0
  62. package/tests/apg.test.ts +0 -466
  63. package/tests/context.test.ts +0 -118
  64. package/tests/css-optimizer-extractors.test.ts +0 -264
  65. package/tests/css-optimizer-integration.test.ts +0 -566
  66. package/tests/css-optimizer-transformers.test.ts +0 -301
  67. package/tests/css-optimizer.test.ts +0 -646
  68. package/tests/css-runtime.bench.ts +0 -442
  69. package/tests/css-runtime.test.ts +0 -342
  70. package/tests/debounced.test.ts +0 -165
  71. package/tests/dom.test.ts +0 -873
  72. package/tests/integration.test.ts +0 -405
  73. package/tests/issue-11-show-null-to-truthy.test.ts +0 -176
  74. package/tests/issue-5-for-infinite-loop.test.ts +0 -516
  75. package/tests/jsx-runtime.test.tsx +0 -393
  76. package/tests/lifecycle.test.ts +0 -833
  77. package/tests/move-before.bench.ts +0 -304
  78. package/tests/preact-signals-comparison.test.ts +0 -1608
  79. package/tests/resource.test.ts +0 -170
  80. package/tests/router.test.ts +0 -117
  81. package/tests/show-initial-mount-leak.test.tsx +0 -182
  82. package/tests/solidjs-api.test.ts +0 -660
  83. package/tests/static-perf.bench.ts +0 -64
  84. package/tests/store.test.ts +0 -263
  85. package/tests/tsx-syntax.test.tsx +0 -404
  86. /package/dist/{event-utils-BkTM7rk5.d.ts → event-utils-BvAf0NwN.d.ts} +0 -0
@@ -1,171 +0,0 @@
1
- /**
2
- * Frequent pattern mining for CSS classes
3
- */
4
-
5
- import type { ClassUsage, MergePattern } from "./types.js";
6
-
7
- /**
8
- * Find frequent patterns (sets of classes that often appear together)
9
- * Uses a greedy enumeration approach for small pattern sizes
10
- */
11
- export function findFrequentPatterns(
12
- usages: ClassUsage[],
13
- minFrequency: number,
14
- maxSize: number
15
- ): MergePattern[] {
16
- // Count all class set patterns
17
- const patternCounts = new Map<string, number>();
18
-
19
- for (const usage of usages) {
20
- const classes = [...usage.classes].sort();
21
- const n = classes.length;
22
-
23
- // Count pairs (size 2)
24
- for (let i = 0; i < n; i++) {
25
- for (let j = i + 1; j < n; j++) {
26
- const key = `${classes[i]}|${classes[j]}`;
27
- patternCounts.set(key, (patternCounts.get(key) || 0) + 1);
28
- }
29
- }
30
-
31
- // Count triples (size 3)
32
- if (maxSize >= 3) {
33
- for (let i = 0; i < n; i++) {
34
- for (let j = i + 1; j < n; j++) {
35
- for (let k = j + 1; k < n; k++) {
36
- const key = `${classes[i]}|${classes[j]}|${classes[k]}`;
37
- patternCounts.set(key, (patternCounts.get(key) || 0) + 1);
38
- }
39
- }
40
- }
41
- }
42
-
43
- // Count quadruples (size 4)
44
- if (maxSize >= 4) {
45
- for (let i = 0; i < n; i++) {
46
- for (let j = i + 1; j < n; j++) {
47
- for (let k = j + 1; k < n; k++) {
48
- for (let l = k + 1; l < n; l++) {
49
- const key = `${classes[i]}|${classes[j]}|${classes[k]}|${classes[l]}`;
50
- patternCounts.set(key, (patternCounts.get(key) || 0) + 1);
51
- }
52
- }
53
- }
54
- }
55
- }
56
-
57
- // Count quintuples (size 5)
58
- if (maxSize >= 5) {
59
- for (let i = 0; i < n; i++) {
60
- for (let j = i + 1; j < n; j++) {
61
- for (let k = j + 1; k < n; k++) {
62
- for (let l = k + 1; l < n; l++) {
63
- for (let m = l + 1; m < n; m++) {
64
- const key = `${classes[i]}|${classes[j]}|${classes[k]}|${classes[l]}|${classes[m]}`;
65
- patternCounts.set(key, (patternCounts.get(key) || 0) + 1);
66
- }
67
- }
68
- }
69
- }
70
- }
71
- }
72
- }
73
-
74
- // Filter by min frequency and create patterns
75
- const patterns: MergePattern[] = [];
76
-
77
- for (const [key, frequency] of patternCounts) {
78
- if (frequency >= minFrequency) {
79
- const originalClasses = key.split("|");
80
- const classCount = originalClasses.length;
81
-
82
- // Estimate savings:
83
- // HTML: each class is ~6 chars + space, merged saves (n-1) * 7 * frequency
84
- // CSS: each rule is ~25 bytes, merged saves (n-1) * 25
85
- const htmlSavings = (classCount - 1) * 7 * frequency;
86
- const cssSavings = (classCount - 1) * 25;
87
- const bytesSaved = htmlSavings + cssSavings;
88
-
89
- patterns.push({
90
- originalClasses,
91
- mergedClass: "", // Will be set during merge
92
- declarations: [], // Will be set during merge
93
- frequency,
94
- bytesSaved,
95
- });
96
- }
97
- }
98
-
99
- // Sort by bytes saved descending
100
- patterns.sort((a, b) => b.bytesSaved - a.bytesSaved);
101
-
102
- // Remove subsumed patterns
103
- return removeSubsumedPatterns(patterns);
104
- }
105
-
106
- /**
107
- * Remove patterns that are subsets of larger patterns with similar frequency
108
- * This prevents double-counting savings
109
- */
110
- export function removeSubsumedPatterns(patterns: MergePattern[]): MergePattern[] {
111
- const result: MergePattern[] = [];
112
-
113
- for (let i = 0; i < patterns.length; i++) {
114
- const pattern = patterns[i];
115
- let isDominated = false;
116
-
117
- for (let j = 0; j < patterns.length; j++) {
118
- if (i === j) continue;
119
-
120
- const other = patterns[j];
121
- // Check if other is a superset with similar or higher frequency (80% threshold)
122
- if (
123
- other.originalClasses.length > pattern.originalClasses.length &&
124
- other.frequency >= pattern.frequency * 0.8
125
- ) {
126
- const patternSet = new Set(pattern.originalClasses);
127
- const otherSet = new Set(other.originalClasses);
128
-
129
- // Check if pattern is subset of other
130
- let isSubset = true;
131
- for (const cls of patternSet) {
132
- if (!otherSet.has(cls)) {
133
- isSubset = false;
134
- break;
135
- }
136
- }
137
-
138
- if (isSubset) {
139
- isDominated = true;
140
- break;
141
- }
142
- }
143
- }
144
-
145
- if (!isDominated) {
146
- result.push(pattern);
147
- }
148
- }
149
-
150
- return result;
151
- }
152
-
153
- /**
154
- * Group usages by their exact class set
155
- * Returns a map from sorted class key to array of usages
156
- */
157
- export function groupByClassSet(
158
- usages: ClassUsage[]
159
- ): Map<string, ClassUsage[]> {
160
- const groups = new Map<string, ClassUsage[]>();
161
-
162
- for (const usage of usages) {
163
- const key = [...usage.classes].sort().join("|");
164
- if (!groups.has(key)) {
165
- groups.set(key, []);
166
- }
167
- groups.get(key)!.push(usage);
168
- }
169
-
170
- return groups;
171
- }
@@ -1,301 +0,0 @@
1
- /**
2
- * CSS Co-occurrence Optimizer - Transformers
3
- *
4
- * Pluggable output transformation strategies for different formats.
5
- * Each transformer applies merge maps to source content.
6
- */
7
-
8
- /**
9
- * Transformer interface - implement this for custom output formats
10
- */
11
- export interface ClassTransformer {
12
- /** Transformer name for debugging */
13
- name: string;
14
-
15
- /**
16
- * Transform content by applying merge map
17
- * @param content - Source content to transform
18
- * @param mergeMap - Mapping from "class1 class2" to "merged_class"
19
- * @param options - Transformer-specific options
20
- */
21
- transform(
22
- content: string,
23
- mergeMap: Map<string, string>,
24
- options?: TransformerOptions
25
- ): string;
26
- }
27
-
28
- /**
29
- * Common transformer options
30
- */
31
- export interface TransformerOptions {
32
- /** Class prefix for identifying mergeable classes (default: "_") */
33
- classPrefix?: string;
34
- }
35
-
36
- /**
37
- * HTML Transformer
38
- *
39
- * Transforms HTML by replacing class="" attribute values with merged classes.
40
- */
41
- export class HtmlTransformer implements ClassTransformer {
42
- name = "html";
43
-
44
- private pattern = /class\s*=\s*"([^"]+)"/g;
45
-
46
- transform(
47
- content: string,
48
- mergeMap: Map<string, string>,
49
- options: TransformerOptions = {}
50
- ): string {
51
- if (mergeMap.size === 0) {
52
- return content;
53
- }
54
-
55
- const { classPrefix = "_" } = options;
56
-
57
- // Sort merge keys by length descending (longer patterns first)
58
- const sortedKeys = [...mergeMap.keys()].sort((a, b) => b.length - a.length);
59
-
60
- return content.replace(this.pattern, (match, classValue) => {
61
- const classes = classValue.trim().split(/\s+/);
62
- const prefixedClasses = classes.filter((c: string) => c.startsWith(classPrefix));
63
- const otherClasses = classes.filter((c: string) => !c.startsWith(classPrefix));
64
-
65
- // Sort for consistent matching
66
- prefixedClasses.sort();
67
-
68
- let result = [...prefixedClasses];
69
- const merged: string[] = [];
70
-
71
- // Apply each merge pattern
72
- for (const key of sortedKeys) {
73
- const patternClasses = key.split(" ");
74
- const mergedClass = mergeMap.get(key)!;
75
-
76
- // Check if all pattern classes are present
77
- let allPresent = true;
78
- for (const cls of patternClasses) {
79
- if (!result.includes(cls)) {
80
- allPresent = false;
81
- break;
82
- }
83
- }
84
-
85
- if (allPresent) {
86
- result = result.filter((c) => !patternClasses.includes(c));
87
- merged.push(mergedClass);
88
- }
89
- }
90
-
91
- const finalClasses = [...merged, ...result, ...otherClasses].join(" ");
92
- return `class="${finalClasses}"`;
93
- });
94
- }
95
- }
96
-
97
- /**
98
- * JSX Transformer
99
- *
100
- * Transforms JSX/TSX by replacing className attribute values.
101
- */
102
- export class JsxTransformer implements ClassTransformer {
103
- name = "jsx";
104
-
105
- private stringPattern = /className\s*=\s*"([^"]+)"/g;
106
-
107
- transform(
108
- content: string,
109
- mergeMap: Map<string, string>,
110
- options: TransformerOptions = {}
111
- ): string {
112
- if (mergeMap.size === 0) {
113
- return content;
114
- }
115
-
116
- const { classPrefix = "_" } = options;
117
- const sortedKeys = [...mergeMap.keys()].sort((a, b) => b.length - a.length);
118
-
119
- return content.replace(this.stringPattern, (match, classValue) => {
120
- const classes = classValue.trim().split(/\s+/);
121
- const prefixedClasses = classes.filter((c: string) => c.startsWith(classPrefix));
122
- const otherClasses = classes.filter((c: string) => !c.startsWith(classPrefix));
123
-
124
- prefixedClasses.sort();
125
-
126
- let result = [...prefixedClasses];
127
- const merged: string[] = [];
128
-
129
- for (const key of sortedKeys) {
130
- const patternClasses = key.split(" ");
131
- const mergedClass = mergeMap.get(key)!;
132
-
133
- let allPresent = true;
134
- for (const cls of patternClasses) {
135
- if (!result.includes(cls)) {
136
- allPresent = false;
137
- break;
138
- }
139
- }
140
-
141
- if (allPresent) {
142
- result = result.filter((c) => !patternClasses.includes(c));
143
- merged.push(mergedClass);
144
- }
145
- }
146
-
147
- const finalClasses = [...merged, ...result, ...otherClasses].join(" ");
148
- return `className="${finalClasses}"`;
149
- });
150
- }
151
- }
152
-
153
- /**
154
- * Svelte Transformer
155
- *
156
- * Transforms Svelte templates by replacing class attribute values.
157
- * Preserves dynamic {expression} syntax.
158
- */
159
- export class SvelteTransformer implements ClassTransformer {
160
- name = "svelte";
161
-
162
- private pattern = /class\s*=\s*"([^"]+)"/g;
163
-
164
- transform(
165
- content: string,
166
- mergeMap: Map<string, string>,
167
- options: TransformerOptions = {}
168
- ): string {
169
- if (mergeMap.size === 0) {
170
- return content;
171
- }
172
-
173
- const { classPrefix = "_" } = options;
174
- const sortedKeys = [...mergeMap.keys()].sort((a, b) => b.length - a.length);
175
-
176
- return content.replace(this.pattern, (match, classValue) => {
177
- // Preserve dynamic expressions
178
- const expressions: string[] = [];
179
- const cleanValue = classValue.replace(/\{[^}]+\}/g, (expr: string) => {
180
- expressions.push(expr);
181
- return `__EXPR_${expressions.length - 1}__`;
182
- });
183
-
184
- const classes = cleanValue.trim().split(/\s+/);
185
- const prefixedClasses = classes.filter(
186
- (c: string) => c.startsWith(classPrefix) && !c.startsWith("__EXPR_")
187
- );
188
- const otherClasses = classes.filter(
189
- (c: string) => !c.startsWith(classPrefix) || c.startsWith("__EXPR_")
190
- );
191
-
192
- prefixedClasses.sort();
193
-
194
- let result = [...prefixedClasses];
195
- const merged: string[] = [];
196
-
197
- for (const key of sortedKeys) {
198
- const patternClasses = key.split(" ");
199
- const mergedClass = mergeMap.get(key)!;
200
-
201
- let allPresent = true;
202
- for (const cls of patternClasses) {
203
- if (!result.includes(cls)) {
204
- allPresent = false;
205
- break;
206
- }
207
- }
208
-
209
- if (allPresent) {
210
- result = result.filter((c) => !patternClasses.includes(c));
211
- merged.push(mergedClass);
212
- }
213
- }
214
-
215
- let finalClasses = [...merged, ...result, ...otherClasses].join(" ");
216
-
217
- // Restore expressions
218
- expressions.forEach((expr, i) => {
219
- finalClasses = finalClasses.replace(`__EXPR_${i}__`, expr);
220
- });
221
-
222
- return `class="${finalClasses}"`;
223
- });
224
- }
225
- }
226
-
227
- /**
228
- * Multi-format transformer
229
- *
230
- * Automatically selects the appropriate transformer based on content or file type.
231
- */
232
- export class MultiTransformer implements ClassTransformer {
233
- name = "multi";
234
-
235
- private transformers: Map<string, ClassTransformer>;
236
-
237
- constructor() {
238
- this.transformers = new Map<string, ClassTransformer>([
239
- ["html", new HtmlTransformer()],
240
- ["jsx", new JsxTransformer()],
241
- ["tsx", new JsxTransformer()],
242
- ["svelte", new SvelteTransformer()],
243
- ]);
244
- }
245
-
246
- /**
247
- * Register a custom transformer for a file extension
248
- */
249
- register(extension: string, transformer: ClassTransformer): void {
250
- this.transformers.set(extension, transformer);
251
- }
252
-
253
- transform(
254
- content: string,
255
- mergeMap: Map<string, string>,
256
- options?: TransformerOptions
257
- ): string {
258
- // Default to HTML transformer
259
- const htmlTransformer = this.transformers.get("html")!;
260
- return htmlTransformer.transform(content, mergeMap, options);
261
- }
262
-
263
- /**
264
- * Transform with explicit file type
265
- */
266
- transformWithType(
267
- content: string,
268
- mergeMap: Map<string, string>,
269
- fileType: string,
270
- options?: TransformerOptions
271
- ): string {
272
- const transformer =
273
- this.transformers.get(fileType) || this.transformers.get("html")!;
274
- return transformer.transform(content, mergeMap, options);
275
- }
276
-
277
- /**
278
- * Transform multiple files
279
- */
280
- transformFiles(
281
- files: Array<{ content: string; path: string }>,
282
- mergeMap: Map<string, string>,
283
- options?: TransformerOptions
284
- ): Array<{ content: string; path: string }> {
285
- return files.map((file) => {
286
- const ext = file.path.split(".").pop() || "html";
287
- const transformer =
288
- this.transformers.get(ext) || this.transformers.get("html")!;
289
- return {
290
- path: file.path,
291
- content: transformer.transform(file.content, mergeMap, options),
292
- };
293
- });
294
- }
295
- }
296
-
297
- // Default transformers
298
- export const htmlTransformer = new HtmlTransformer();
299
- export const jsxTransformer = new JsxTransformer();
300
- export const svelteTransformer = new SvelteTransformer();
301
- export const multiTransformer = new MultiTransformer();
@@ -1,128 +0,0 @@
1
- /**
2
- * CSS Co-occurrence Optimizer Types
3
- * Standalone types for CSS class optimization based on co-occurrence analysis
4
- */
5
-
6
- /**
7
- * Represents a set of classes used together on an HTML element
8
- */
9
- export interface ClassUsage {
10
- /** Array of class names used on the element */
11
- classes: string[];
12
- /** Source location for debugging (e.g., "file.html:42") */
13
- source: string;
14
- }
15
-
16
- /**
17
- * Co-occurrence pair with frequency count
18
- */
19
- export interface CoOccurrence {
20
- /** First class name (alphabetically) */
21
- classA: string;
22
- /** Second class name (alphabetically) */
23
- classB: string;
24
- /** Number of times these classes appear together */
25
- frequency: number;
26
- }
27
-
28
- /**
29
- * A pattern of classes that frequently appear together
30
- */
31
- export interface MergePattern {
32
- /** Original class names to merge */
33
- originalClasses: string[];
34
- /** New merged class name (generated) */
35
- mergedClass: string;
36
- /** Combined CSS declarations */
37
- declarations: string[];
38
- /** How many times this pattern appears in HTML */
39
- frequency: number;
40
- /** Estimated bytes saved by merging */
41
- bytesSaved: number;
42
- }
43
-
44
- /**
45
- * Result of CSS optimization
46
- */
47
- export interface OptimizeResult {
48
- /** Optimized CSS output */
49
- css: string;
50
- /** Mapping from original class combination to merged class */
51
- mergeMap: Map<string, string>;
52
- /** Patterns that were merged */
53
- patterns: MergePattern[];
54
- /** Optimization statistics */
55
- stats: {
56
- /** Number of original unique classes */
57
- originalClasses: number;
58
- /** Number of patterns merged */
59
- mergedPatterns: number;
60
- /** Estimated bytes saved */
61
- estimatedBytesSaved: number;
62
- };
63
- }
64
-
65
- /**
66
- * Options for CSS optimization
67
- */
68
- export interface OptimizeOptions {
69
- /** Minimum frequency for a pattern to be considered (default: 2) */
70
- minFrequency?: number;
71
- /** Maximum pattern size to consider (default: 5) */
72
- maxPatternSize?: number;
73
- /** Class name prefix filter (only classes starting with this will be optimized) */
74
- classPrefix?: string;
75
- /** Pretty print CSS output */
76
- pretty?: boolean;
77
- /** Enable verbose logging */
78
- verbose?: boolean;
79
- }
80
-
81
- /**
82
- * Function to generate class names from declarations
83
- */
84
- export type ClassNameGenerator = (decl: string) => string;
85
-
86
- /**
87
- * CSS rule with selector and declarations
88
- */
89
- export interface CssRule {
90
- selector: string;
91
- declarations: string;
92
- }
93
-
94
- // =============================================================================
95
- // MoonBit Static Analyzer Types
96
- // =============================================================================
97
-
98
- /**
99
- * CSS class co-occurrence detected in MoonBit source
100
- */
101
- export interface ClassCooccurrence {
102
- /** CSS declarations (e.g., ["color:red", "font-size:16px"]) */
103
- classes: string[];
104
- /** Source file path */
105
- file: string;
106
- /** Line number in source */
107
- line: number;
108
- /** Whether this can be statically analyzed (no conditionals) */
109
- isStatic: boolean;
110
- }
111
-
112
- /**
113
- * Warning from static analyzer about non-analyzable patterns
114
- */
115
- export interface AnalyzerWarning {
116
- /** Warning type */
117
- kind:
118
- | "dynamic_conditional"
119
- | "dynamic_function_call"
120
- | "untraceable_variable"
121
- | "dynamic_array_construction";
122
- /** Source file path */
123
- file: string;
124
- /** Line number in source */
125
- line: number;
126
- /** Human-readable warning message */
127
- message: string;
128
- }