jasmincss 1.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 (76) hide show
  1. package/README.md +524 -0
  2. package/bin/jasmin.js +45 -0
  3. package/dist/index.d.ts +62 -0
  4. package/dist/index.js +14568 -0
  5. package/dist/index.mjs +14524 -0
  6. package/dist/jasmin.css +63308 -0
  7. package/dist/jasmin.min.css +1 -0
  8. package/dist/plugins/nextjs.js +14777 -0
  9. package/dist/plugins/nextjs.mjs +14747 -0
  10. package/dist/plugins/vite.js +14889 -0
  11. package/dist/plugins/vite.mjs +14860 -0
  12. package/package.json +101 -0
  13. package/src/cli/add.js +83 -0
  14. package/src/cli/init.js +210 -0
  15. package/src/cli/run.js +142 -0
  16. package/src/components/accordion.js +309 -0
  17. package/src/components/alerts.js +357 -0
  18. package/src/components/avatars.js +331 -0
  19. package/src/components/badges.js +353 -0
  20. package/src/components/buttons.js +412 -0
  21. package/src/components/cards.js +342 -0
  22. package/src/components/carousel.js +495 -0
  23. package/src/components/chips.js +440 -0
  24. package/src/components/command-palette.js +434 -0
  25. package/src/components/datepicker.js +517 -0
  26. package/src/components/dropdown.js +411 -0
  27. package/src/components/forms.js +516 -0
  28. package/src/components/index.js +81 -0
  29. package/src/components/modals.js +349 -0
  30. package/src/components/navigation.js +463 -0
  31. package/src/components/offcanvas.js +390 -0
  32. package/src/components/popover.js +427 -0
  33. package/src/components/progress.js +396 -0
  34. package/src/components/rating.js +394 -0
  35. package/src/components/skeleton.js +408 -0
  36. package/src/components/spinner.js +453 -0
  37. package/src/components/stepper.js +389 -0
  38. package/src/components/tables.js +304 -0
  39. package/src/components/timeline.js +452 -0
  40. package/src/components/timepicker.js +529 -0
  41. package/src/components/tooltips.js +345 -0
  42. package/src/components/upload.js +490 -0
  43. package/src/config/defaults.js +263 -0
  44. package/src/config/loader.js +109 -0
  45. package/src/core/base.js +241 -0
  46. package/src/core/compiler.js +135 -0
  47. package/src/core/utilities/accessibility.js +290 -0
  48. package/src/core/utilities/animations.js +205 -0
  49. package/src/core/utilities/background.js +109 -0
  50. package/src/core/utilities/colors.js +234 -0
  51. package/src/core/utilities/columns.js +161 -0
  52. package/src/core/utilities/effects.js +261 -0
  53. package/src/core/utilities/filters.js +135 -0
  54. package/src/core/utilities/icons.js +806 -0
  55. package/src/core/utilities/index.js +239 -0
  56. package/src/core/utilities/layout.js +321 -0
  57. package/src/core/utilities/scroll.js +205 -0
  58. package/src/core/utilities/spacing.js +120 -0
  59. package/src/core/utilities/svg.js +191 -0
  60. package/src/core/utilities/transforms.js +116 -0
  61. package/src/core/utilities/typography.js +188 -0
  62. package/src/index.js +7 -0
  63. package/src/js/components/accordion.js +154 -0
  64. package/src/js/components/alert.js +198 -0
  65. package/src/js/components/carousel.js +226 -0
  66. package/src/js/components/dropdown.js +166 -0
  67. package/src/js/components/modal.js +169 -0
  68. package/src/js/components/offcanvas.js +175 -0
  69. package/src/js/components/popover.js +221 -0
  70. package/src/js/components/tabs.js +163 -0
  71. package/src/js/components/tooltip.js +200 -0
  72. package/src/js/index.js +79 -0
  73. package/src/js/types/config.d.ts +228 -0
  74. package/src/js/types/index.d.ts +439 -0
  75. package/src/plugins/nextjs.js +100 -0
  76. package/src/plugins/vite.js +133 -0
@@ -0,0 +1,439 @@
1
+ /**
2
+ * JasminCSS TypeScript Definitions
3
+ * @version 1.0.0
4
+ */
5
+
6
+ // ============================================================================
7
+ // Dropdown
8
+ // ============================================================================
9
+
10
+ export interface DropdownOptions {
11
+ /** Close dropdown when clicking outside. Default: true */
12
+ closeOnClickOutside?: boolean;
13
+ /** Close dropdown when pressing Escape. Default: true */
14
+ closeOnEscape?: boolean;
15
+ }
16
+
17
+ export class Dropdown {
18
+ constructor(element: HTMLElement, options?: DropdownOptions);
19
+
20
+ /** Toggle dropdown visibility */
21
+ toggle(): void;
22
+
23
+ /** Open dropdown */
24
+ open(): void;
25
+
26
+ /** Close dropdown */
27
+ close(): void;
28
+
29
+ /** Destroy instance and remove event listeners */
30
+ destroy(): void;
31
+
32
+ /** Initialize all dropdowns matching selector */
33
+ static initAll(selector?: string): Dropdown[];
34
+ }
35
+
36
+ // ============================================================================
37
+ // Modal
38
+ // ============================================================================
39
+
40
+ export interface ModalOptions {
41
+ /** Show backdrop overlay. Default: true */
42
+ backdrop?: boolean;
43
+ /** Close on Escape key. Default: true */
44
+ keyboard?: boolean;
45
+ /** Trap focus inside modal. Default: true */
46
+ focus?: boolean;
47
+ }
48
+
49
+ export interface ModalEvents {
50
+ 'modal:open': CustomEvent<{ modal: Modal }>;
51
+ 'modal:close': CustomEvent<{ modal: Modal }>;
52
+ }
53
+
54
+ export class Modal {
55
+ constructor(element: HTMLElement, options?: ModalOptions);
56
+
57
+ /** Open modal */
58
+ open(): void;
59
+
60
+ /** Close modal */
61
+ close(): void;
62
+
63
+ /** Toggle modal visibility */
64
+ toggle(): void;
65
+
66
+ /** Check if modal is open */
67
+ isOpen(): boolean;
68
+
69
+ /** Destroy instance and remove event listeners */
70
+ destroy(): void;
71
+
72
+ /** Initialize all modals matching selector */
73
+ static initAll(selector?: string): Modal[];
74
+ }
75
+
76
+ // ============================================================================
77
+ // Accordion
78
+ // ============================================================================
79
+
80
+ export interface AccordionOptions {
81
+ /** Allow multiple panels open simultaneously. Default: false */
82
+ multipleOpen?: boolean;
83
+ }
84
+
85
+ export class Accordion {
86
+ constructor(element: HTMLElement, options?: AccordionOptions);
87
+
88
+ /** Open panel by index */
89
+ openItem(index: number): void;
90
+
91
+ /** Close panel by index */
92
+ closeItem(index: number): void;
93
+
94
+ /** Toggle panel by index */
95
+ toggleItem(index: number): void;
96
+
97
+ /** Open all panels */
98
+ openAll(): void;
99
+
100
+ /** Close all panels */
101
+ closeAll(): void;
102
+
103
+ /** Destroy instance and remove event listeners */
104
+ destroy(): void;
105
+
106
+ /** Initialize all accordions matching selector */
107
+ static initAll(selector?: string): Accordion[];
108
+ }
109
+
110
+ // ============================================================================
111
+ // Tabs
112
+ // ============================================================================
113
+
114
+ export interface TabsOptions {
115
+ /** Tab orientation. Default: 'horizontal' */
116
+ orientation?: 'horizontal' | 'vertical';
117
+ }
118
+
119
+ export interface TabsEvents {
120
+ 'tabs:change': CustomEvent<{ index: number; tab: HTMLElement; panel: HTMLElement }>;
121
+ }
122
+
123
+ export class Tabs {
124
+ constructor(element: HTMLElement, options?: TabsOptions);
125
+
126
+ /** Select tab by index */
127
+ selectTab(index: number): void;
128
+
129
+ /** Get currently selected tab index */
130
+ getSelectedIndex(): number;
131
+
132
+ /** Destroy instance and remove event listeners */
133
+ destroy(): void;
134
+
135
+ /** Initialize all tabs matching selector */
136
+ static initAll(selector?: string): Tabs[];
137
+ }
138
+
139
+ // ============================================================================
140
+ // Offcanvas
141
+ // ============================================================================
142
+
143
+ export interface OffcanvasOptions {
144
+ /** Show backdrop overlay. Default: true */
145
+ backdrop?: boolean;
146
+ /** Close on Escape key. Default: true */
147
+ keyboard?: boolean;
148
+ /** Disable body scroll when open. Default: true */
149
+ scroll?: boolean;
150
+ }
151
+
152
+ export interface OffcanvasEvents {
153
+ 'offcanvas:open': CustomEvent<{ offcanvas: Offcanvas }>;
154
+ 'offcanvas:close': CustomEvent<{ offcanvas: Offcanvas }>;
155
+ }
156
+
157
+ export class Offcanvas {
158
+ constructor(element: HTMLElement, options?: OffcanvasOptions);
159
+
160
+ /** Open offcanvas */
161
+ open(): void;
162
+
163
+ /** Close offcanvas */
164
+ close(): void;
165
+
166
+ /** Toggle offcanvas visibility */
167
+ toggle(): void;
168
+
169
+ /** Check if offcanvas is open */
170
+ isOpen(): boolean;
171
+
172
+ /** Destroy instance and remove event listeners */
173
+ destroy(): void;
174
+
175
+ /** Initialize all offcanvas elements matching selector */
176
+ static initAll(selector?: string): Offcanvas[];
177
+ }
178
+
179
+ // ============================================================================
180
+ // Tooltip
181
+ // ============================================================================
182
+
183
+ export type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
184
+ export type TooltipTrigger = 'hover' | 'focus' | 'hover focus';
185
+
186
+ export interface TooltipOptions {
187
+ /** Tooltip position. Default: 'top' */
188
+ position?: TooltipPosition;
189
+ /** Trigger events. Default: 'hover focus' */
190
+ trigger?: TooltipTrigger;
191
+ /** Delay before showing (ms). Default: 0 */
192
+ delay?: number;
193
+ /** Tooltip content (overrides data-tooltip attribute) */
194
+ content?: string;
195
+ }
196
+
197
+ export class Tooltip {
198
+ constructor(element: HTMLElement, options?: TooltipOptions);
199
+
200
+ /** Show tooltip */
201
+ show(): void;
202
+
203
+ /** Hide tooltip */
204
+ hide(): void;
205
+
206
+ /** Update tooltip content */
207
+ setContent(content: string): void;
208
+
209
+ /** Update tooltip position */
210
+ setPosition(position: TooltipPosition): void;
211
+
212
+ /** Destroy instance and remove event listeners */
213
+ destroy(): void;
214
+
215
+ /** Initialize all tooltips matching selector */
216
+ static initAll(selector?: string): Tooltip[];
217
+ }
218
+
219
+ // ============================================================================
220
+ // Popover
221
+ // ============================================================================
222
+
223
+ export type PopoverPosition = 'top' | 'bottom' | 'left' | 'right';
224
+ export type PopoverTrigger = 'click' | 'hover' | 'focus';
225
+
226
+ export interface PopoverOptions {
227
+ /** Popover position. Default: 'top' */
228
+ position?: PopoverPosition;
229
+ /** Trigger event. Default: 'click' */
230
+ trigger?: PopoverTrigger;
231
+ /** Popover title */
232
+ title?: string;
233
+ /** Popover content */
234
+ content?: string;
235
+ /** Allow HTML in content. Default: false */
236
+ html?: boolean;
237
+ }
238
+
239
+ export class Popover {
240
+ constructor(element: HTMLElement, options?: PopoverOptions);
241
+
242
+ /** Show popover */
243
+ show(): void;
244
+
245
+ /** Hide popover */
246
+ hide(): void;
247
+
248
+ /** Toggle popover visibility */
249
+ toggle(): void;
250
+
251
+ /** Update popover title */
252
+ setTitle(title: string): void;
253
+
254
+ /** Update popover content */
255
+ setContent(content: string): void;
256
+
257
+ /** Destroy instance and remove event listeners */
258
+ destroy(): void;
259
+
260
+ /** Initialize all popovers matching selector */
261
+ static initAll(selector?: string): Popover[];
262
+ }
263
+
264
+ // ============================================================================
265
+ // Carousel
266
+ // ============================================================================
267
+
268
+ export interface CarouselOptions {
269
+ /** Enable autoplay. Default: false */
270
+ autoplay?: boolean;
271
+ /** Autoplay interval in ms. Default: 5000 */
272
+ interval?: number;
273
+ /** Wrap around at ends. Default: true */
274
+ wrap?: boolean;
275
+ /** Enable keyboard navigation. Default: true */
276
+ keyboard?: boolean;
277
+ /** Enable touch/swipe support. Default: true */
278
+ touch?: boolean;
279
+ /** Pause autoplay on hover. Default: true */
280
+ pauseOnHover?: boolean;
281
+ }
282
+
283
+ export interface CarouselEvents {
284
+ 'carousel:slide': CustomEvent<{ from: number; to: number }>;
285
+ 'carousel:slid': CustomEvent<{ from: number; to: number }>;
286
+ }
287
+
288
+ export class Carousel {
289
+ constructor(element: HTMLElement, options?: CarouselOptions);
290
+
291
+ /** Go to next slide */
292
+ next(): void;
293
+
294
+ /** Go to previous slide */
295
+ prev(): void;
296
+
297
+ /** Go to specific slide */
298
+ goTo(index: number): void;
299
+
300
+ /** Pause autoplay */
301
+ pause(): void;
302
+
303
+ /** Resume autoplay */
304
+ play(): void;
305
+
306
+ /** Get current slide index */
307
+ getCurrentIndex(): number;
308
+
309
+ /** Get total number of slides */
310
+ getSlideCount(): number;
311
+
312
+ /** Destroy instance and remove event listeners */
313
+ destroy(): void;
314
+
315
+ /** Initialize all carousels matching selector */
316
+ static initAll(selector?: string): Carousel[];
317
+ }
318
+
319
+ // ============================================================================
320
+ // Alert
321
+ // ============================================================================
322
+
323
+ export interface AlertOptions {
324
+ /** Animation duration in ms. Default: 150 */
325
+ animationDuration?: number;
326
+ }
327
+
328
+ export interface AlertEvents {
329
+ 'alert:close': CustomEvent<{ alert: Alert }>;
330
+ 'alert:closed': CustomEvent<{ alert: Alert }>;
331
+ }
332
+
333
+ export class Alert {
334
+ constructor(element: HTMLElement, options?: AlertOptions);
335
+
336
+ /** Close and remove alert */
337
+ close(): void;
338
+
339
+ /** Destroy instance and remove event listeners */
340
+ destroy(): void;
341
+
342
+ /** Initialize all alerts matching selector */
343
+ static initAll(selector?: string): Alert[];
344
+ }
345
+
346
+ // ============================================================================
347
+ // Toast
348
+ // ============================================================================
349
+
350
+ export type ToastType = 'success' | 'error' | 'warning' | 'info' | 'default';
351
+ export type ToastPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center';
352
+
353
+ export interface ToastOptions {
354
+ /** Toast message */
355
+ message: string;
356
+ /** Toast type/style. Default: 'default' */
357
+ type?: ToastType;
358
+ /** Auto-dismiss duration in ms. 0 for no auto-dismiss. Default: 5000 */
359
+ duration?: number;
360
+ /** Toast position. Default: 'top-right' */
361
+ position?: ToastPosition;
362
+ /** Show dismiss button. Default: true */
363
+ dismissible?: boolean;
364
+ /** Toast title (optional) */
365
+ title?: string;
366
+ /** Custom icon class (optional) */
367
+ icon?: string;
368
+ }
369
+
370
+ export class Toast {
371
+ /** Show a toast notification */
372
+ static show(options: ToastOptions): HTMLElement;
373
+
374
+ /** Show success toast */
375
+ static success(message: string, options?: Partial<ToastOptions>): HTMLElement;
376
+
377
+ /** Show error toast */
378
+ static error(message: string, options?: Partial<ToastOptions>): HTMLElement;
379
+
380
+ /** Show warning toast */
381
+ static warning(message: string, options?: Partial<ToastOptions>): HTMLElement;
382
+
383
+ /** Show info toast */
384
+ static info(message: string, options?: Partial<ToastOptions>): HTMLElement;
385
+
386
+ /** Dismiss all toasts */
387
+ static dismissAll(): void;
388
+
389
+ /** Dismiss toast by element */
390
+ static dismiss(element: HTMLElement): void;
391
+ }
392
+
393
+ // ============================================================================
394
+ // Main Jasmin Object
395
+ // ============================================================================
396
+
397
+ export interface JasminStatic {
398
+ Dropdown: typeof Dropdown;
399
+ Modal: typeof Modal;
400
+ Accordion: typeof Accordion;
401
+ Tabs: typeof Tabs;
402
+ Offcanvas: typeof Offcanvas;
403
+ Tooltip: typeof Tooltip;
404
+ Popover: typeof Popover;
405
+ Carousel: typeof Carousel;
406
+ Alert: typeof Alert;
407
+ Toast: typeof Toast;
408
+
409
+ /** Initialize all components */
410
+ initAll(): void;
411
+
412
+ /** Auto-initialize on DOMContentLoaded */
413
+ autoInit(): void;
414
+
415
+ /** JasminCSS version */
416
+ version: string;
417
+ }
418
+
419
+ declare const Jasmin: JasminStatic;
420
+
421
+ export default Jasmin;
422
+
423
+ // ============================================================================
424
+ // Module Augmentation for Custom Events
425
+ // ============================================================================
426
+
427
+ declare global {
428
+ interface HTMLElementEventMap {
429
+ 'modal:open': CustomEvent<{ modal: Modal }>;
430
+ 'modal:close': CustomEvent<{ modal: Modal }>;
431
+ 'offcanvas:open': CustomEvent<{ offcanvas: Offcanvas }>;
432
+ 'offcanvas:close': CustomEvent<{ offcanvas: Offcanvas }>;
433
+ 'tabs:change': CustomEvent<{ index: number; tab: HTMLElement; panel: HTMLElement }>;
434
+ 'carousel:slide': CustomEvent<{ from: number; to: number }>;
435
+ 'carousel:slid': CustomEvent<{ from: number; to: number }>;
436
+ 'alert:close': CustomEvent<{ alert: Alert }>;
437
+ 'alert:closed': CustomEvent<{ alert: Alert }>;
438
+ }
439
+ }
@@ -0,0 +1,100 @@
1
+ // JasminCSS Next.js Plugin
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+
5
+ /**
6
+ * JasminCSS plugin for Next.js
7
+ *
8
+ * @param {Object} pluginOptions
9
+ * @param {string} pluginOptions.configPath - Path to jasmin.config.js
10
+ * @param {boolean} pluginOptions.optimizeFonts - Optimize Google Fonts loading
11
+ *
12
+ * @example
13
+ * // next.config.js
14
+ * const withJasminCSS = require('jasmincss/plugin/nextjs');
15
+ *
16
+ * module.exports = withJasminCSS({
17
+ * configPath: './jasmin.config.js',
18
+ * optimizeFonts: true
19
+ * })({
20
+ * // your Next.js config
21
+ * });
22
+ */
23
+ export default function withJasminCSS(pluginOptions = {}) {
24
+ const {
25
+ configPath = './jasmin.config.js',
26
+ optimizeFonts = true
27
+ } = pluginOptions;
28
+
29
+ return (nextConfig = {}) => {
30
+ return {
31
+ ...nextConfig,
32
+
33
+ // Enable CSS optimization
34
+ experimental: {
35
+ ...nextConfig.experimental,
36
+ optimizeCss: true
37
+ },
38
+
39
+ // Optimize fonts if enabled
40
+ ...(optimizeFonts && {
41
+ optimizeFonts: true
42
+ }),
43
+
44
+ webpack(config, options) {
45
+ const { dev, isServer } = options;
46
+
47
+ // Add JasminCSS loader for .jasmin.css files
48
+ config.module.rules.push({
49
+ test: /\.jasmin\.css$/,
50
+ use: [
51
+ {
52
+ loader: 'postcss-loader',
53
+ options: {
54
+ postcssOptions: {
55
+ plugins: [
56
+ ['cssnano', { preset: 'default' }]
57
+ ]
58
+ }
59
+ }
60
+ }
61
+ ]
62
+ });
63
+
64
+ // Run user's webpack config if provided
65
+ if (typeof nextConfig.webpack === 'function') {
66
+ return nextConfig.webpack(config, options);
67
+ }
68
+
69
+ return config;
70
+ }
71
+ };
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Get JasminCSS config for App Router
77
+ * Useful for server components
78
+ */
79
+ export async function getJasminConfig(configPath = './jasmin.config.js') {
80
+ const { loadConfig } = await import('../config/loader.js');
81
+ const absolutePath = path.resolve(process.cwd(), configPath);
82
+ return loadConfig(absolutePath);
83
+ }
84
+
85
+ /**
86
+ * Compile JasminCSS for a specific page/component
87
+ * Useful for generating critical CSS
88
+ */
89
+ export async function compileForPage(usedClasses, configPath = './jasmin.config.js') {
90
+ const { compileCSS } = await import('../core/compiler.js');
91
+ const config = await getJasminConfig(configPath);
92
+
93
+ const { minified } = await compileCSS(config, {
94
+ usedClasses: new Set(usedClasses),
95
+ minify: true,
96
+ includeAll: false
97
+ });
98
+
99
+ return minified;
100
+ }
@@ -0,0 +1,133 @@
1
+ // JasminCSS Vite Plugin
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+
5
+ /**
6
+ * JasminCSS plugin for Vite
7
+ *
8
+ * @param {Object} options
9
+ * @param {string} options.configPath - Path to jasmin.config.js
10
+ * @param {boolean} options.devMode - Include full library in development
11
+ * @param {string[]} options.content - Files to scan for class usage
12
+ *
13
+ * @example
14
+ * // vite.config.js
15
+ * import { defineConfig } from 'vite';
16
+ * import jasmin from 'jasmincss/plugin/vite';
17
+ *
18
+ * export default defineConfig({
19
+ * plugins: [
20
+ * jasmin({
21
+ * configPath: './jasmin.config.js'
22
+ * })
23
+ * ]
24
+ * });
25
+ */
26
+ export default function jasminVitePlugin(options = {}) {
27
+ const {
28
+ configPath = './jasmin.config.js',
29
+ devMode = true,
30
+ content = ['./src/**/*.{vue,js,ts,jsx,tsx,svelte}', './index.html']
31
+ } = options;
32
+
33
+ let config;
34
+ let generatedCSS = '';
35
+ const virtualModuleId = 'virtual:jasmin.css';
36
+ const resolvedVirtualModuleId = '\0' + virtualModuleId;
37
+
38
+ return {
39
+ name: 'jasmin-css',
40
+
41
+ async configResolved(resolvedConfig) {
42
+ const isDev = resolvedConfig.command === 'serve';
43
+
44
+ try {
45
+ const { loadConfig } = await import('../config/loader.js');
46
+ const absolutePath = path.resolve(resolvedConfig.root, configPath);
47
+
48
+ if (fs.existsSync(absolutePath)) {
49
+ config = await loadConfig(absolutePath);
50
+ } else {
51
+ const { defaultConfig } = await import('../config/defaults.js');
52
+ config = defaultConfig;
53
+ }
54
+
55
+ // Override content patterns
56
+ config.content = content;
57
+
58
+ // Generate CSS
59
+ const { compileCSS, scanForUsedClasses } = await import('../core/compiler.js');
60
+
61
+ if (isDev && devMode) {
62
+ // In dev mode, include full library for faster HMR
63
+ const result = await compileCSS(config, {
64
+ includeAll: true,
65
+ minify: false
66
+ });
67
+ generatedCSS = result.css;
68
+ } else {
69
+ // In production, tree-shake based on usage
70
+ const usedClasses = await scanForUsedClasses(resolvedConfig.root, content);
71
+ const result = await compileCSS(config, {
72
+ usedClasses,
73
+ minify: !isDev,
74
+ includeAll: false
75
+ });
76
+ generatedCSS = isDev ? result.css : result.minified;
77
+ }
78
+ } catch (err) {
79
+ console.warn('[jasmin] Could not load config:', err.message);
80
+ // Fall back to default
81
+ const { compileCSS } = await import('../core/compiler.js');
82
+ const { defaultConfig } = await import('../config/defaults.js');
83
+ const result = await compileCSS(defaultConfig, { includeAll: true, minify: false });
84
+ generatedCSS = result.css;
85
+ }
86
+ },
87
+
88
+ resolveId(id) {
89
+ if (id === virtualModuleId || id === 'jasmincss/css') {
90
+ return resolvedVirtualModuleId;
91
+ }
92
+ },
93
+
94
+ load(id) {
95
+ if (id === resolvedVirtualModuleId) {
96
+ return generatedCSS;
97
+ }
98
+ },
99
+
100
+ handleHotUpdate({ file, server }) {
101
+ // Reload CSS when config changes
102
+ if (file.endsWith('jasmin.config.js')) {
103
+ server.ws.send({
104
+ type: 'full-reload',
105
+ path: '*'
106
+ });
107
+ }
108
+ }
109
+ };
110
+ }
111
+
112
+ /**
113
+ * PostCSS plugin for JasminCSS
114
+ * Use when you need PostCSS integration
115
+ */
116
+ export function jasminPostCSS(options = {}) {
117
+ return {
118
+ postcssPlugin: 'jasmin-css',
119
+ async Once(root, { result }) {
120
+ const { compileCSS } = await import('../core/compiler.js');
121
+ const { defaultConfig } = await import('../config/defaults.js');
122
+
123
+ const { css } = await compileCSS({ ...defaultConfig, ...options }, {
124
+ includeAll: true,
125
+ minify: false
126
+ });
127
+
128
+ root.append(css);
129
+ }
130
+ };
131
+ }
132
+
133
+ jasminPostCSS.postcss = true;