plutonium 0.34.1 → 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.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/skill.md +53 -0
  3. data/.claude/skills/{assets → plutonium-assets}/SKILL.md +13 -8
  4. data/.claude/skills/{connect-resource → plutonium-connect-resource}/SKILL.md +1 -1
  5. data/.claude/skills/{controller → plutonium-controller}/SKILL.md +27 -13
  6. data/.claude/skills/{create-resource → plutonium-create-resource}/SKILL.md +1 -1
  7. data/.claude/skills/{definition → plutonium-definition}/SKILL.md +10 -10
  8. data/.claude/skills/{definition-actions → plutonium-definition-actions}/SKILL.md +34 -9
  9. data/.claude/skills/{definition-fields → plutonium-definition-fields}/SKILL.md +38 -10
  10. data/.claude/skills/plutonium-definition-query/SKILL.md +356 -0
  11. data/.claude/skills/{forms → plutonium-forms}/SKILL.md +6 -6
  12. data/.claude/skills/{installation → plutonium-installation}/SKILL.md +9 -9
  13. data/.claude/skills/{interaction → plutonium-interaction}/SKILL.md +20 -19
  14. data/.claude/skills/{model → plutonium-model}/SKILL.md +3 -3
  15. data/.claude/skills/{model-features → plutonium-model-features}/SKILL.md +3 -3
  16. data/.claude/skills/{nested-resources → plutonium-nested-resources}/SKILL.md +5 -5
  17. data/.claude/skills/{package → plutonium-package}/SKILL.md +7 -8
  18. data/.claude/skills/{policy → plutonium-policy}/SKILL.md +26 -4
  19. data/.claude/skills/{portal → plutonium-portal}/SKILL.md +33 -31
  20. data/.claude/skills/{resource → plutonium-resource}/SKILL.md +27 -27
  21. data/.claude/skills/{rodauth → plutonium-rodauth}/SKILL.md +5 -5
  22. data/.claude/skills/plutonium-theming/SKILL.md +424 -0
  23. data/.claude/skills/{views → plutonium-views}/SKILL.md +7 -7
  24. data/CHANGELOG.md +52 -0
  25. data/CLAUDE.md +215 -0
  26. data/CONTRIBUTING.md +72 -18
  27. data/README.md +100 -19
  28. data/app/assets/plutonium.css +1 -11
  29. data/app/assets/plutonium.js +1685 -1146
  30. data/app/assets/plutonium.js.map +4 -4
  31. data/app/assets/plutonium.min.js +70 -70
  32. data/app/assets/plutonium.min.js.map +4 -4
  33. data/app/views/resource/interactive_bulk_action.html.erb +1 -5
  34. data/app/views/rodauth/_email_auth_request_form.html.erb +1 -1
  35. data/app/views/rodauth/_login_form.html.erb +15 -55
  36. data/app/views/rodauth/_login_form_footer.html.erb +2 -2
  37. data/app/views/rodauth/_password_visibility.html.erb +2 -8
  38. data/app/views/rodauth/add_recovery_codes.html.erb +2 -2
  39. data/app/views/rodauth/change_login.html.erb +36 -19
  40. data/app/views/rodauth/change_password.html.erb +34 -10
  41. data/app/views/rodauth/close_account.html.erb +12 -4
  42. data/app/views/rodauth/confirm_password.html.erb +19 -17
  43. data/app/views/rodauth/create_account.html.erb +30 -109
  44. data/app/views/rodauth/email_auth.html.erb +1 -1
  45. data/app/views/rodauth/logout.html.erb +4 -4
  46. data/app/views/rodauth/otp_auth.html.erb +13 -4
  47. data/app/views/rodauth/otp_disable.html.erb +12 -4
  48. data/app/views/rodauth/otp_setup.html.erb +29 -12
  49. data/app/views/rodauth/otp_unlock.html.erb +19 -10
  50. data/app/views/rodauth/otp_unlock_not_available.html.erb +7 -7
  51. data/app/views/rodauth/recovery_auth.html.erb +12 -4
  52. data/app/views/rodauth/recovery_codes.html.erb +12 -4
  53. data/app/views/rodauth/remember.html.erb +7 -7
  54. data/app/views/rodauth/reset_password.html.erb +23 -7
  55. data/app/views/rodauth/reset_password_request.html.erb +14 -10
  56. data/app/views/rodauth/sms_auth.html.erb +13 -4
  57. data/app/views/rodauth/sms_confirm.html.erb +13 -4
  58. data/app/views/rodauth/sms_disable.html.erb +12 -4
  59. data/app/views/rodauth/sms_request.html.erb +1 -1
  60. data/app/views/rodauth/sms_setup.html.erb +23 -7
  61. data/app/views/rodauth/two_factor_auth.html.erb +2 -2
  62. data/app/views/rodauth/two_factor_disable.html.erb +12 -4
  63. data/app/views/rodauth/two_factor_manage.html.erb +7 -7
  64. data/app/views/rodauth/unlock_account.html.erb +13 -5
  65. data/app/views/rodauth/unlock_account_request.html.erb +2 -2
  66. data/app/views/rodauth/verify_account.html.erb +25 -7
  67. data/app/views/rodauth/verify_account_resend.html.erb +14 -10
  68. data/app/views/rodauth/verify_login_change.html.erb +1 -1
  69. data/app/views/rodauth/webauthn_auth.html.erb +1 -1
  70. data/app/views/rodauth/webauthn_remove.html.erb +18 -8
  71. data/app/views/rodauth/webauthn_setup.html.erb +12 -4
  72. data/docs/.vitepress/config.ts +15 -26
  73. data/docs/.vitepress/theme/custom.css +388 -29
  74. data/docs/getting-started/index.md +1 -1
  75. data/docs/getting-started/tutorial/02-first-resource.md +9 -0
  76. data/docs/getting-started/tutorial/06-nested-resources.md +2 -2
  77. data/docs/getting-started/tutorial/07-author-portal.md +191 -0
  78. data/docs/getting-started/tutorial/{07-customizing-ui.md → 08-customizing-ui.md} +7 -7
  79. data/docs/getting-started/tutorial/index.md +5 -2
  80. data/docs/guides/authorization.md +33 -0
  81. data/docs/guides/creating-packages.md +12 -16
  82. data/docs/guides/custom-actions.md +36 -0
  83. data/docs/guides/search-filtering.md +121 -42
  84. data/docs/guides/theming.md +232 -36
  85. data/docs/index.md +203 -57
  86. data/docs/public/og-image.png +0 -0
  87. data/docs/reference/controller/index.md +14 -16
  88. data/docs/reference/definition/actions.md +38 -3
  89. data/docs/reference/definition/fields.md +3 -3
  90. data/docs/reference/definition/index.md +2 -2
  91. data/docs/reference/generators/index.md +0 -1
  92. data/docs/reference/interaction/index.md +14 -10
  93. data/docs/reference/model/index.md +0 -1
  94. data/docs/reference/portal/index.md +13 -27
  95. data/gemfiles/rails_7.gemfile.lock +1 -1
  96. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  97. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  98. data/lib/generators/pu/pkg/portal/portal_generator.rb +0 -2
  99. data/lib/generators/pu/pkg/portal/templates/app/views/package/dashboard/index.html.erb +28 -72
  100. data/lib/plutonium/action/interactive.rb +2 -2
  101. data/lib/plutonium/core/controller.rb +2 -1
  102. data/lib/plutonium/definition/actions.rb +2 -2
  103. data/lib/plutonium/lib/deep_freezer.rb +3 -7
  104. data/lib/plutonium/query/filter.rb +14 -0
  105. data/lib/plutonium/query/filters/association.rb +49 -0
  106. data/lib/plutonium/query/filters/boolean.rb +35 -0
  107. data/lib/plutonium/query/filters/date.rb +97 -0
  108. data/lib/plutonium/query/filters/date_range.rb +58 -0
  109. data/lib/plutonium/query/filters/select.rb +55 -0
  110. data/lib/plutonium/resource/controllers/crud_actions.rb +24 -6
  111. data/lib/plutonium/resource/controllers/interactive_actions.rb +76 -58
  112. data/lib/plutonium/resource/controllers/queryable.rb +4 -2
  113. data/lib/plutonium/resource/query_object.rb +1 -1
  114. data/lib/plutonium/ui/action_button.rb +23 -65
  115. data/lib/plutonium/ui/actions_dropdown.rb +103 -0
  116. data/lib/plutonium/ui/block.rb +1 -1
  117. data/lib/plutonium/ui/breadcrumbs.rb +12 -19
  118. data/lib/plutonium/ui/color_mode_selector.rb +1 -1
  119. data/lib/plutonium/ui/component/kit.rb +6 -0
  120. data/lib/plutonium/ui/component_classes.rb +102 -0
  121. data/lib/plutonium/ui/display/base.rb +15 -0
  122. data/lib/plutonium/ui/display/components/attachment.rb +6 -5
  123. data/lib/plutonium/ui/display/components/boolean.rb +23 -0
  124. data/lib/plutonium/ui/display/components/color.rb +23 -0
  125. data/lib/plutonium/ui/display/resource.rb +1 -1
  126. data/lib/plutonium/ui/display/theme.rb +29 -15
  127. data/lib/plutonium/ui/empty_card.rb +3 -3
  128. data/lib/plutonium/ui/form/base.rb +20 -0
  129. data/lib/plutonium/ui/form/components/key_value_store.rb +11 -11
  130. data/lib/plutonium/ui/form/components/resource_select.rb +31 -0
  131. data/lib/plutonium/ui/form/components/secure_association.rb +1 -2
  132. data/lib/plutonium/ui/form/components/uppy.rb +5 -4
  133. data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +4 -4
  134. data/lib/plutonium/ui/form/interaction.rb +17 -1
  135. data/lib/plutonium/ui/form/query.rb +133 -80
  136. data/lib/plutonium/ui/form/theme.rb +50 -35
  137. data/lib/plutonium/ui/frame_navigator_panel.rb +2 -2
  138. data/lib/plutonium/ui/layout/base.rb +1 -1
  139. data/lib/plutonium/ui/layout/header.rb +4 -7
  140. data/lib/plutonium/ui/layout/rodauth_layout.rb +7 -7
  141. data/lib/plutonium/ui/layout/sidebar.rb +1 -1
  142. data/lib/plutonium/ui/nav_grid_menu.rb +7 -6
  143. data/lib/plutonium/ui/nav_user.rb +9 -8
  144. data/lib/plutonium/ui/page/interactive_action.rb +5 -5
  145. data/lib/plutonium/ui/page_header.rb +29 -10
  146. data/lib/plutonium/ui/panel.rb +4 -4
  147. data/lib/plutonium/ui/sidebar_menu.rb +8 -8
  148. data/lib/plutonium/ui/skeleton_table.rb +7 -8
  149. data/lib/plutonium/ui/tab_list.rb +5 -5
  150. data/lib/plutonium/ui/table/base.rb +3 -0
  151. data/lib/plutonium/ui/table/components/attachment.rb +4 -3
  152. data/lib/plutonium/ui/table/components/bulk_actions_toolbar.rb +82 -0
  153. data/lib/plutonium/ui/table/components/pagy_info.rb +2 -2
  154. data/lib/plutonium/ui/table/components/pagy_pagination.rb +13 -8
  155. data/lib/plutonium/ui/table/components/row_actions_dropdown.rb +101 -0
  156. data/lib/plutonium/ui/table/components/scopes_bar.rb +2 -2
  157. data/lib/plutonium/ui/table/components/selection_column.rb +100 -0
  158. data/lib/plutonium/ui/table/display_theme.rb +6 -6
  159. data/lib/plutonium/ui/table/resource.rb +93 -52
  160. data/lib/plutonium/ui/table/theme.rb +28 -15
  161. data/lib/plutonium/version.rb +1 -1
  162. data/package.json +2 -2
  163. data/plutonium.gemspec +5 -4
  164. data/src/css/components.css +471 -0
  165. data/src/css/intl_tel_input.css +2 -2
  166. data/src/css/plutonium.css +2 -0
  167. data/src/css/tokens.css +149 -0
  168. data/src/js/controllers/bulk_actions_controller.js +109 -0
  169. data/src/js/controllers/filter_panel_controller.js +35 -0
  170. data/src/js/controllers/register_controllers.js +5 -1
  171. data/src/js/controllers/resource_drop_down_controller.js +25 -1
  172. data/src/js/controllers/slim_select_controller.js +6 -2
  173. data/src/js/turbo/turbo_actions.js +1 -1
  174. metadata +52 -39
  175. data/.claude/skills/definition-query/SKILL.md +0 -334
  176. data/docs/concepts/architecture.md +0 -226
  177. data/docs/concepts/auto-detection.md +0 -254
  178. data/docs/concepts/index.md +0 -61
  179. data/docs/concepts/packages-portals.md +0 -304
  180. data/docs/concepts/resources.md +0 -224
  181. data/docs/cookbook/blog.md +0 -411
  182. data/docs/cookbook/index.md +0 -289
  183. data/docs/cookbook/saas.md +0 -481
  184. data/docs/public/CLAUDE.md +0 -578
  185. data/lib/generators/pu/pkg/portal/templates/app/controllers/resource_controller.rb.tt +0 -5
data/plutonium.gemspec CHANGED
@@ -6,9 +6,10 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["Stefan Froelich"]
7
7
  spec.email = ["sfroelich01@gmail.com"]
8
8
 
9
- spec.summary = "The Ultimate Rapid Application Development Toolkit (RADKit) for Rails"
10
- spec.description = "Plutonium extends Rails' capabilities with a powerful, generator-driven toolkit designed to supercharge your development process. " \
11
- "It transforms the way you build applications with Rails, optimizing for rapid application development."
9
+ spec.summary = "Build production-ready Rails apps in minutes, not days"
10
+ spec.description = "Plutonium is a Rapid Application Development toolkit for Rails. " \
11
+ "Convention-driven and fully customizable, it adds application-level concepts like resources, policies, " \
12
+ "definitions, and portals that make building complex apps faster. Built for the AI era with Claude Code skills."
12
13
  spec.homepage = "https://radioactive-labs.github.io/plutonium-core/"
13
14
  spec.license = "MIT"
14
15
  spec.required_ruby_version = ">= 3.2.2"
@@ -43,7 +44,7 @@ Gem::Specification.new do |spec|
43
44
  spec.add_dependency "phlex-rails"
44
45
  spec.add_dependency "phlex-tabler_icons"
45
46
  spec.add_dependency "phlexi-field", ">= 0.2.0"
46
- spec.add_dependency "phlexi-form", ">= 0.10.0"
47
+ spec.add_dependency "phlexi-form", ">= 0.13.0"
47
48
  spec.add_dependency "phlexi-table", ">= 0.2.0"
48
49
  spec.add_dependency "phlexi-display", ">= 0.2.0"
49
50
  spec.add_dependency "phlexi-menu", ">= 0.4.0"
@@ -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";
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Design Tokens for Plutonium UI
3
+ *
4
+ * Modern design system with refined colors, shadows, and spacing.
5
+ */
6
+
7
+ :root {
8
+ /* ===================
9
+ Body/Page Background
10
+ =================== */
11
+ --pu-body: #f8fafc;
12
+
13
+ /* ===================
14
+ Surface Colors - Softer, more refined
15
+ =================== */
16
+ --pu-surface: #ffffff;
17
+ --pu-surface-alt: #f1f5f9;
18
+ --pu-surface-raised: #ffffff;
19
+ --pu-surface-overlay: rgba(255, 255, 255, 0.95);
20
+
21
+ /* ===================
22
+ Border Colors - Subtle
23
+ =================== */
24
+ --pu-border: #e2e8f0;
25
+ --pu-border-muted: #f1f5f9;
26
+ --pu-border-strong: #cbd5e1;
27
+
28
+ /* ===================
29
+ Text Colors - Better hierarchy
30
+ =================== */
31
+ --pu-text: #0f172a;
32
+ --pu-text-muted: #64748b;
33
+ --pu-text-subtle: #94a3b8;
34
+
35
+ /* ===================
36
+ Table Tokens - Clean minimal design
37
+ =================== */
38
+ --pu-table-header-bg: #f8fafc;
39
+ --pu-table-header-text: #475569;
40
+ --pu-table-row-bg: #ffffff;
41
+ --pu-table-row-hover: #f8fafc;
42
+ --pu-table-row-selected: theme(colors.primary.50);
43
+ --pu-table-border: #f1f5f9;
44
+
45
+ /* ===================
46
+ Form Tokens
47
+ =================== */
48
+ --pu-input-bg: #ffffff;
49
+ --pu-input-border: #e2e8f0;
50
+ --pu-input-focus-ring: theme(colors.primary.500);
51
+ --pu-input-placeholder: #94a3b8;
52
+
53
+ /* ===================
54
+ Card Tokens - Refined shadows
55
+ =================== */
56
+ --pu-card-bg: #ffffff;
57
+ --pu-card-border: #e2e8f0;
58
+
59
+ /* ===================
60
+ Shadow System - Layered, soft
61
+ =================== */
62
+ --pu-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.03), 0 1px 3px 0 rgb(0 0 0 / 0.05);
63
+ --pu-shadow-md: 0 2px 4px -1px rgb(0 0 0 / 0.04), 0 4px 6px -1px rgb(0 0 0 / 0.06);
64
+ --pu-shadow-lg: 0 4px 6px -2px rgb(0 0 0 / 0.03), 0 10px 15px -3px rgb(0 0 0 / 0.08);
65
+
66
+ /* ===================
67
+ Spacing Scale
68
+ =================== */
69
+ --pu-space-xs: 0.25rem;
70
+ --pu-space-sm: 0.5rem;
71
+ --pu-space-md: 1rem;
72
+ --pu-space-lg: 1.5rem;
73
+ --pu-space-xl: 2rem;
74
+
75
+ /* ===================
76
+ Border Radius - Refined
77
+ =================== */
78
+ --pu-radius-sm: 0.375rem;
79
+ --pu-radius-md: 0.5rem;
80
+ --pu-radius-lg: 0.75rem;
81
+ --pu-radius-xl: 1rem;
82
+ --pu-radius-full: 9999px;
83
+
84
+ /* ===================
85
+ Transitions - Smooth
86
+ =================== */
87
+ --pu-transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
88
+ --pu-transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);
89
+ --pu-transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);
90
+ }
91
+
92
+ .dark {
93
+ /* ===================
94
+ Body/Page Background (Dark)
95
+ =================== */
96
+ --pu-body: #0f172a;
97
+
98
+ /* ===================
99
+ Surface Colors (Dark) - Rich, not too dark
100
+ =================== */
101
+ --pu-surface: #1e293b;
102
+ --pu-surface-alt: #0f172a;
103
+ --pu-surface-raised: #334155;
104
+ --pu-surface-overlay: rgba(30, 41, 59, 0.95);
105
+
106
+ /* ===================
107
+ Border Colors (Dark)
108
+ =================== */
109
+ --pu-border: #334155;
110
+ --pu-border-muted: #1e293b;
111
+ --pu-border-strong: #475569;
112
+
113
+ /* ===================
114
+ Text Colors (Dark)
115
+ =================== */
116
+ --pu-text: #f8fafc;
117
+ --pu-text-muted: #94a3b8;
118
+ --pu-text-subtle: #64748b;
119
+
120
+ /* ===================
121
+ Table Tokens (Dark)
122
+ =================== */
123
+ --pu-table-header-bg: #0f172a;
124
+ --pu-table-header-text: #cbd5e1;
125
+ --pu-table-row-bg: #1e293b;
126
+ --pu-table-row-hover: #334155;
127
+ --pu-table-row-selected: theme(colors.primary.900 / 40%);
128
+ --pu-table-border: #334155;
129
+
130
+ /* ===================
131
+ Form Tokens (Dark)
132
+ =================== */
133
+ --pu-input-bg: #1e293b;
134
+ --pu-input-border: #475569;
135
+ --pu-input-placeholder: #64748b;
136
+
137
+ /* ===================
138
+ Card Tokens (Dark)
139
+ =================== */
140
+ --pu-card-bg: #1e293b;
141
+ --pu-card-border: #334155;
142
+
143
+ /* ===================
144
+ Shadow System (Dark)
145
+ =================== */
146
+ --pu-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.2), 0 1px 3px 0 rgb(0 0 0 / 0.3);
147
+ --pu-shadow-md: 0 2px 4px -1px rgb(0 0 0 / 0.25), 0 4px 6px -1px rgb(0 0 0 / 0.35);
148
+ --pu-shadow-lg: 0 4px 6px -2px rgb(0 0 0 / 0.2), 0 10px 15px -3px rgb(0 0 0 / 0.4);
149
+ }