@radioactive-labs/plutonium 0.34.0 → 0.35.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.
package/README.md CHANGED
@@ -1,33 +1,114 @@
1
- # Plutonium: It's like Rails, but for Rails!
1
+ # Plutonium
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/plutonium.svg)](https://badge.fury.io/rb/plutonium)
3
4
  [![Ruby](https://github.com/radioactive-labs/plutonium-core/actions/workflows/main.yml/badge.svg)](https://github.com/radioactive-labs/plutonium-core/actions/workflows/main.yml)
4
5
 
5
- **Plutonium** is a powerful Rapid Application Development (RAD) toolkit for Rails that picks up where Rails left off, introducing application-level concepts and tooling that transform the way you build applications.
6
+ Build production-ready Rails apps in minutes, not days. Convention-driven, fully customizable, and AI-ready. Plutonium picks up where Rails left off, adding application-level concepts that make building complex apps faster.
6
7
 
7
- ## Overview
8
+ ## Quick Start
8
9
 
9
- Plutonium builds upon Rails' conventions and extends them with:
10
+ ```bash
11
+ rails new myapp -a propshaft -j esbuild -c tailwind \
12
+ -m https://radioactive-labs.github.io/plutonium-core/templates/plutonium.rb
13
+ ```
10
14
 
11
- - **Authentication & Authorization**: Integrates seamlessly with Rodauth or your existing auth system
12
- - **Complete CRUD Operations**: Rich fields, forms, tables, and nested resources out of the box
13
- - **Modular Architecture**: Package system based on Rails engines for better organization
14
- - **Entity Scoping**: Built-in multi-tenancy support that "just works"
15
- - **Smart Generators**: Eliminate boilerplate while maintaining flexibility
16
- - **Modern UI**: Beautiful, responsive interface powered by Tailwind CSS and Hotwire
15
+ Then create your first resource:
17
16
 
18
- ## Project Status
17
+ ```bash
18
+ cd myapp
19
+ rails g pu:res:scaffold Post title:string body:text --dest=main_app
20
+ rails db:migrate
21
+ bin/dev
22
+ ```
19
23
 
20
- > [!WARNING]
21
- > While Plutonium is actively used in production environments, it's still in early development. APIs may change, and some features are still evolving. We recommend thoroughly testing before deploying to production.
24
+ Visit `http://localhost:3000` - you have a complete CRUD interface.
25
+
26
+ ## What You Get
27
+
28
+ **Resource-oriented architecture** - Models, policies, definitions, and controllers that work together:
29
+
30
+ ```ruby
31
+ # Policy controls WHO can do WHAT
32
+ class PostPolicy < ResourcePolicy
33
+ def create? = user.present?
34
+ def update? = record.author == user || user.admin?
35
+
36
+ def permitted_attributes_for_create
37
+ %i[title body]
38
+ end
39
+ end
40
+
41
+ # Definition controls HOW it renders
42
+ class PostDefinition < ResourceDefinition
43
+ input :body, as: :markdown
44
+ search { |scope, q| scope.where("title ILIKE ?", "%#{q}%") }
45
+ scope :published
46
+ scope :drafts
47
+ end
48
+ ```
49
+
50
+ **Packages for organization** - Split your app into feature packages and portals:
51
+
52
+ ```bash
53
+ rails g pu:pkg:package blogging # Business logic
54
+ rails g pu:pkg:portal admin # Web interface
55
+ rails g pu:res:conn Post --dest=admin_portal
56
+ ```
57
+
58
+ **Built-in authentication** via Rodauth:
59
+
60
+ ```bash
61
+ rails g pu:rodauth:install
62
+ rails g pu:rodauth:account user
63
+ ```
64
+
65
+ **Multi-tenancy** with entity scoping:
66
+
67
+ ```ruby
68
+ # In portal engine
69
+ scope_to_entity Organization, strategy: :path
70
+ # Routes become /organizations/:organization_id/posts
71
+ ```
72
+
73
+ **Custom actions** with interactions:
74
+
75
+ ```ruby
76
+ class PublishInteraction < ResourceInteraction
77
+ attribute :resource
78
+ attribute :publish_at, :datetime
79
+
80
+ def execute
81
+ resource.update!(published_at: publish_at)
82
+ succeed(resource).with_message("Published!")
83
+ rescue ActiveRecord::RecordInvalid => e
84
+ failed(e.record.errors)
85
+ end
86
+ end
87
+ ```
22
88
 
23
89
  ## Documentation
24
90
 
25
- Visit our [documentation](https://radioactive-labs.github.io/plutonium-core/) for:
26
- - Getting started guide
27
- - Installation instructions
28
- - Core concepts
29
- - Tutorials
91
+ Full documentation at **[radioactive-labs.github.io/plutonium-core](https://radioactive-labs.github.io/plutonium-core/)**
92
+
93
+ - [Installation](https://radioactive-labs.github.io/plutonium-core/getting-started/installation)
94
+ - [Tutorial](https://radioactive-labs.github.io/plutonium-core/getting-started/tutorial/)
95
+ - [Guides](https://radioactive-labs.github.io/plutonium-core/guides/)
96
+ - [Reference](https://radioactive-labs.github.io/plutonium-core/reference/)
97
+
98
+ ## Requirements
99
+
100
+ - Ruby 3.2+
101
+ - Rails 7.1+ (Rails 8 recommended)
102
+ - Node.js 18+
103
+
104
+ ## Contributing
105
+
106
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
107
+
108
+ ## Status
109
+
110
+ Plutonium is used in production but still evolving. APIs may change between minor versions. Pin your version in Gemfile.
30
111
 
31
112
  ## License
32
113
 
33
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
114
+ MIT License - see [LICENSE](LICENSE).
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@radioactive-labs/plutonium",
3
- "version": "0.34.0",
4
- "description": "Core assets for the Plutonium gem",
3
+ "version": "0.35.0",
4
+ "description": "Build production-ready Rails apps in minutes, not days. Convention-driven, fully customizable, AI-ready.",
5
5
  "type": "module",
6
6
  "main": "src/js/core.js",
7
7
  "files": [
@@ -0,0 +1,471 @@
1
+ /**
2
+ * Plutonium Component Classes
3
+ *
4
+ * Modern, clean component styles with refined aesthetics.
5
+ */
6
+
7
+ /* ===================
8
+ BUTTONS - Modern, refined
9
+ =================== */
10
+
11
+ .pu-btn {
12
+ @apply inline-flex items-center justify-center gap-2
13
+ font-semibold
14
+ transition-all duration-200 ease-out
15
+ focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2;
16
+ border-radius: var(--pu-radius-md);
17
+ }
18
+
19
+ .pu-btn-md {
20
+ @apply px-5 py-2.5 text-sm;
21
+ }
22
+
23
+ .pu-btn-sm {
24
+ @apply px-4 py-2 text-sm;
25
+ }
26
+
27
+ .pu-btn-xs {
28
+ @apply px-3 py-1.5 text-xs;
29
+ }
30
+
31
+ /* Primary - Solid with subtle gradient */
32
+ .pu-btn-primary {
33
+ @apply bg-primary-600 text-white
34
+ hover:bg-primary-500
35
+ active:bg-primary-700
36
+ focus-visible:ring-primary-500;
37
+ box-shadow: var(--pu-shadow-sm), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
38
+ }
39
+ .pu-btn-primary:hover {
40
+ box-shadow: var(--pu-shadow-md), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
41
+ transform: translateY(-1px);
42
+ }
43
+ .pu-btn-primary:active {
44
+ transform: translateY(0);
45
+ box-shadow: var(--pu-shadow-sm);
46
+ }
47
+
48
+ /* Secondary */
49
+ .pu-btn-secondary {
50
+ @apply bg-secondary-600 text-white
51
+ hover:bg-secondary-500
52
+ active:bg-secondary-700
53
+ focus-visible:ring-secondary-500;
54
+ box-shadow: var(--pu-shadow-sm), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
55
+ }
56
+ .pu-btn-secondary:hover {
57
+ box-shadow: var(--pu-shadow-md), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
58
+ transform: translateY(-1px);
59
+ }
60
+
61
+ /* Danger */
62
+ .pu-btn-danger {
63
+ @apply bg-danger-600 text-white
64
+ hover:bg-danger-500
65
+ active:bg-danger-700
66
+ focus-visible:ring-danger-500;
67
+ box-shadow: var(--pu-shadow-sm), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
68
+ }
69
+ .pu-btn-danger:hover {
70
+ box-shadow: var(--pu-shadow-md), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
71
+ transform: translateY(-1px);
72
+ }
73
+
74
+ /* Success */
75
+ .pu-btn-success {
76
+ @apply bg-success-600 text-white
77
+ hover:bg-success-500
78
+ active:bg-success-700
79
+ focus-visible:ring-success-500;
80
+ box-shadow: var(--pu-shadow-sm), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
81
+ }
82
+ .pu-btn-success:hover {
83
+ box-shadow: var(--pu-shadow-md), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
84
+ transform: translateY(-1px);
85
+ }
86
+
87
+ /* Warning */
88
+ .pu-btn-warning {
89
+ @apply bg-warning-600 text-white
90
+ hover:bg-warning-500
91
+ active:bg-warning-700
92
+ focus-visible:ring-warning-500;
93
+ box-shadow: var(--pu-shadow-sm), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
94
+ }
95
+ .pu-btn-warning:hover {
96
+ box-shadow: var(--pu-shadow-md), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
97
+ transform: translateY(-1px);
98
+ }
99
+
100
+ /* Info */
101
+ .pu-btn-info {
102
+ @apply bg-info-600 text-white
103
+ hover:bg-info-500
104
+ active:bg-info-700
105
+ focus-visible:ring-info-500;
106
+ box-shadow: var(--pu-shadow-sm), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
107
+ }
108
+ .pu-btn-info:hover {
109
+ box-shadow: var(--pu-shadow-md), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
110
+ transform: translateY(-1px);
111
+ }
112
+
113
+ /* Accent */
114
+ .pu-btn-accent {
115
+ @apply bg-accent-600 text-white
116
+ hover:bg-accent-500
117
+ active:bg-accent-700
118
+ focus-visible:ring-accent-500;
119
+ box-shadow: var(--pu-shadow-sm), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
120
+ }
121
+ .pu-btn-accent:hover {
122
+ box-shadow: var(--pu-shadow-md), inset 0 1px 0 0 rgb(255 255 255 / 0.1);
123
+ transform: translateY(-1px);
124
+ }
125
+
126
+ /* Ghost - Minimal, text-like */
127
+ .pu-btn-ghost {
128
+ @apply bg-transparent
129
+ text-slate-600 hover:text-slate-900
130
+ hover:bg-slate-100
131
+ active:bg-slate-200
132
+ focus-visible:ring-slate-500;
133
+ }
134
+ .dark .pu-btn-ghost {
135
+ @apply text-slate-400 hover:text-slate-100
136
+ hover:bg-slate-700
137
+ active:bg-slate-600;
138
+ }
139
+
140
+ /* Outline - Bordered, transparent background */
141
+ .pu-btn-outline {
142
+ @apply bg-transparent
143
+ border border-[var(--pu-border)]
144
+ text-[var(--pu-text-muted)]
145
+ hover:text-[var(--pu-text)]
146
+ hover:bg-[var(--pu-surface-alt)]
147
+ hover:border-[var(--pu-border-strong)]
148
+ active:bg-[var(--pu-border-muted)]
149
+ focus-visible:ring-[var(--pu-border)];
150
+ }
151
+
152
+ /* Soft variants - Tinted backgrounds */
153
+ .pu-btn-soft-primary {
154
+ @apply bg-primary-50 text-primary-700
155
+ hover:bg-primary-100
156
+ active:bg-primary-200
157
+ focus-visible:ring-primary-500;
158
+ }
159
+ .dark .pu-btn-soft-primary {
160
+ @apply bg-primary-950/50 text-primary-300
161
+ hover:bg-primary-900/60
162
+ active:bg-primary-900/80;
163
+ }
164
+
165
+ .pu-btn-soft-danger {
166
+ @apply bg-danger-50 text-danger-700
167
+ hover:bg-danger-100
168
+ active:bg-danger-200
169
+ focus-visible:ring-danger-500;
170
+ }
171
+ .dark .pu-btn-soft-danger {
172
+ @apply bg-danger-950/50 text-danger-300
173
+ hover:bg-danger-900/60
174
+ active:bg-danger-900/80;
175
+ }
176
+
177
+ .pu-btn-soft-success {
178
+ @apply bg-success-50 text-success-700
179
+ hover:bg-success-100
180
+ active:bg-success-200
181
+ focus-visible:ring-success-500;
182
+ }
183
+ .dark .pu-btn-soft-success {
184
+ @apply bg-success-950/50 text-success-300
185
+ hover:bg-success-900/60
186
+ active:bg-success-900/80;
187
+ }
188
+
189
+ .pu-btn-soft-warning {
190
+ @apply bg-warning-50 text-warning-700
191
+ hover:bg-warning-100
192
+ active:bg-warning-200
193
+ focus-visible:ring-warning-500;
194
+ }
195
+ .dark .pu-btn-soft-warning {
196
+ @apply bg-warning-950/50 text-warning-300
197
+ hover:bg-warning-900/60
198
+ active:bg-warning-900/80;
199
+ }
200
+
201
+ .pu-btn-soft-info {
202
+ @apply bg-info-50 text-info-700
203
+ hover:bg-info-100
204
+ active:bg-info-200
205
+ focus-visible:ring-info-500;
206
+ }
207
+ .dark .pu-btn-soft-info {
208
+ @apply bg-info-950/50 text-info-300
209
+ hover:bg-info-900/60
210
+ active:bg-info-900/80;
211
+ }
212
+
213
+ .pu-btn-soft-secondary {
214
+ @apply bg-secondary-50 text-secondary-700
215
+ hover:bg-secondary-100
216
+ active:bg-secondary-200
217
+ focus-visible:ring-secondary-500;
218
+ }
219
+ .dark .pu-btn-soft-secondary {
220
+ @apply bg-secondary-950/50 text-secondary-300
221
+ hover:bg-secondary-900/60
222
+ active:bg-secondary-900/80;
223
+ }
224
+
225
+ .pu-btn-soft-accent {
226
+ @apply bg-accent-50 text-accent-700
227
+ hover:bg-accent-100
228
+ active:bg-accent-200
229
+ focus-visible:ring-accent-500;
230
+ }
231
+ .dark .pu-btn-soft-accent {
232
+ @apply bg-accent-950/50 text-accent-300
233
+ hover:bg-accent-900/60
234
+ active:bg-accent-900/80;
235
+ }
236
+
237
+ /* ===================
238
+ CARDS - Clean, elevated
239
+ =================== */
240
+
241
+ .pu-card {
242
+ background-color: var(--pu-card-bg);
243
+ border: 1px solid var(--pu-card-border);
244
+ border-radius: var(--pu-radius-lg);
245
+ box-shadow: var(--pu-shadow-sm);
246
+ }
247
+
248
+ .pu-card-body {
249
+ padding: var(--pu-space-lg);
250
+ }
251
+
252
+ /* ===================
253
+ FORM INPUTS - Clean, modern
254
+ =================== */
255
+
256
+ .pu-input {
257
+ background-color: var(--pu-input-bg);
258
+ border: 1px solid var(--pu-input-border);
259
+ border-radius: var(--pu-radius-md);
260
+ color: var(--pu-text);
261
+ transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);
262
+ @apply w-full px-4 py-3
263
+ text-base
264
+ focus:outline-none;
265
+ }
266
+ .pu-input-icon-left {
267
+ @apply pl-10;
268
+ }
269
+ .pu-input::placeholder {
270
+ color: var(--pu-input-placeholder);
271
+ }
272
+ .pu-input:hover {
273
+ border-color: var(--pu-border-strong);
274
+ }
275
+ .pu-input:focus {
276
+ border-color: var(--pu-input-focus-ring);
277
+ box-shadow: 0 0 0 3px theme(colors.primary.500 / 15%);
278
+ }
279
+
280
+ .pu-input-invalid {
281
+ @apply border-danger-500 bg-danger-50/50
282
+ text-danger-900 placeholder:text-danger-400;
283
+ }
284
+ .pu-input-invalid:focus {
285
+ box-shadow: 0 0 0 3px theme(colors.danger.500 / 15%);
286
+ }
287
+ .dark .pu-input-invalid {
288
+ @apply bg-danger-950/20 border-danger-500/70
289
+ text-danger-200 placeholder:text-danger-400;
290
+ }
291
+
292
+ .pu-input-valid {
293
+ @apply border-success-500 bg-success-50/50
294
+ text-success-900 placeholder:text-success-400;
295
+ }
296
+ .pu-input-valid:focus {
297
+ box-shadow: 0 0 0 3px theme(colors.success.500 / 15%);
298
+ }
299
+ .dark .pu-input-valid {
300
+ @apply bg-success-950/20 border-success-500/70
301
+ text-success-200 placeholder:text-success-400;
302
+ }
303
+
304
+ .pu-label {
305
+ color: var(--pu-text);
306
+ @apply block mb-2 text-base font-semibold;
307
+ }
308
+
309
+ .pu-label-required::after {
310
+ content: " *";
311
+ @apply text-danger-500;
312
+ }
313
+
314
+ .pu-hint {
315
+ color: var(--pu-text-muted);
316
+ @apply mt-2 text-sm;
317
+ }
318
+
319
+ .pu-error {
320
+ @apply mt-2 text-sm font-medium text-danger-600;
321
+ }
322
+ .dark .pu-error {
323
+ @apply text-danger-400;
324
+ }
325
+
326
+ /* ===================
327
+ TABLE - Minimal, clean
328
+ =================== */
329
+
330
+ .pu-table-wrapper {
331
+ background-color: var(--pu-card-bg);
332
+ border: 1px solid var(--pu-card-border);
333
+ border-radius: var(--pu-radius-lg);
334
+ box-shadow: var(--pu-shadow-sm);
335
+ @apply overflow-x-auto;
336
+ }
337
+
338
+ .pu-table {
339
+ color: var(--pu-text);
340
+ @apply w-full text-base text-left;
341
+ }
342
+
343
+ .pu-table-header {
344
+ background-color: var(--pu-table-header-bg);
345
+ color: var(--pu-table-header-text);
346
+ border-bottom: 1px solid var(--pu-table-border);
347
+ @apply text-xs font-semibold uppercase tracking-wider;
348
+ }
349
+
350
+ .pu-table-header-cell {
351
+ @apply px-6 py-4;
352
+ }
353
+
354
+ .pu-table-body-row {
355
+ background-color: var(--pu-table-row-bg);
356
+ border-bottom: 1px solid var(--pu-table-border);
357
+ transition: background-color 150ms ease;
358
+ @apply last:border-b-0;
359
+ }
360
+ .pu-table-body-row:hover {
361
+ background-color: var(--pu-table-row-hover);
362
+ }
363
+
364
+ .pu-table-body-row-selected {
365
+ background-color: var(--pu-table-row-selected);
366
+ }
367
+
368
+ .pu-table-body-cell {
369
+ color: var(--pu-text);
370
+ @apply px-6 py-4;
371
+ }
372
+
373
+ /* ===================
374
+ TOOLBAR - Clean, integrated
375
+ =================== */
376
+
377
+ .pu-toolbar {
378
+ background: linear-gradient(to right, theme(colors.primary.50), theme(colors.primary.100/50%));
379
+ border: 1px solid theme(colors.primary.200);
380
+ border-radius: var(--pu-radius-lg);
381
+ @apply items-center gap-4
382
+ px-5 py-3 mb-4;
383
+ }
384
+ .dark .pu-toolbar {
385
+ background: linear-gradient(to right, theme(colors.primary.950/40%), theme(colors.primary.900/30%));
386
+ border-color: theme(colors.primary.800/50%);
387
+ }
388
+
389
+ .pu-toolbar-text {
390
+ @apply text-base font-semibold text-primary-700;
391
+ }
392
+ .dark .pu-toolbar-text {
393
+ @apply text-primary-300;
394
+ }
395
+
396
+ .pu-toolbar-actions {
397
+ @apply flex items-center gap-2;
398
+ }
399
+
400
+ /* ===================
401
+ CHECKBOX - Modern
402
+ =================== */
403
+
404
+ .pu-checkbox {
405
+ @apply size-5 rounded-md
406
+ bg-white border-2 border-slate-300
407
+ accent-primary-600
408
+ focus:ring-2 focus:ring-primary-500/30 focus:ring-offset-0
409
+ cursor-pointer
410
+ transition-all duration-150
411
+ checked:bg-primary-600 checked:border-primary-600
412
+ indeterminate:bg-primary-600 indeterminate:border-primary-600
413
+ hover:border-primary-400;
414
+ }
415
+ .dark .pu-checkbox {
416
+ @apply bg-slate-700 border-slate-500
417
+ hover:border-primary-400;
418
+ }
419
+
420
+ /* ===================
421
+ EMPTY STATE
422
+ =================== */
423
+
424
+ .pu-empty-state {
425
+ @apply flex flex-col items-center justify-center
426
+ py-16 px-8
427
+ text-center;
428
+ }
429
+
430
+ .pu-empty-state-icon {
431
+ color: var(--pu-text-subtle);
432
+ @apply w-16 h-16 mb-6;
433
+ }
434
+
435
+ .pu-empty-state-title {
436
+ color: var(--pu-text);
437
+ @apply text-xl font-semibold mb-3;
438
+ }
439
+
440
+ .pu-empty-state-description {
441
+ color: var(--pu-text-muted);
442
+ @apply text-base max-w-md leading-relaxed;
443
+ }
444
+
445
+ /* ===================
446
+ PANEL HEADER
447
+ =================== */
448
+
449
+ .pu-panel-header {
450
+ background-color: var(--pu-surface-alt);
451
+ border-bottom: 1px solid var(--pu-border);
452
+ @apply px-6 py-5;
453
+ }
454
+
455
+ .pu-panel-title {
456
+ color: var(--pu-text);
457
+ @apply text-xl font-semibold;
458
+ }
459
+
460
+ .pu-panel-description {
461
+ color: var(--pu-text-muted);
462
+ @apply mt-1 text-base;
463
+ }
464
+
465
+ /* ===================
466
+ SELECTION CELL
467
+ =================== */
468
+
469
+ .pu-selection-cell {
470
+ @apply w-14 px-6 py-4;
471
+ }
@@ -43,7 +43,7 @@
43
43
  .iti input.iti__tel-input[type=tel],
44
44
  .iti input.iti__tel-input[type=text] {
45
45
  @apply w-full border border-gray-300 rounded-md shadow-sm font-medium text-sm bg-white text-gray-700 outline-none transition-colors duration-200 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:placeholder-gray-400;
46
- padding: theme(spacing.2);
46
+ padding: theme(spacing.3) theme(spacing.4);
47
47
  padding-left: 52px;
48
48
  /* Space for country selector */
49
49
  }
@@ -51,7 +51,7 @@
51
51
  /* Country container positioning */
52
52
  .iti .iti__country-container {
53
53
  @apply absolute top-0 bottom-0 left-0 z-10;
54
- padding: theme(spacing.2);
54
+ padding: theme(spacing.3) theme(spacing.2);
55
55
  width: 52px;
56
56
  /* Fixed width to match input padding */
57
57
  }
@@ -1,3 +1,5 @@
1
+ @import "tokens.css";
2
+ @import "components.css";
1
3
  @import "core.css";
2
4
  @import "easymde.css";
3
5
  @import "slim_select.css";