plutonium 0.36.0 → 0.37.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/app/assets/plutonium.css +11 -1
- data/app/assets/plutonium.js +1188 -1552
- data/app/assets/plutonium.js.map +4 -4
- data/app/assets/plutonium.min.js +70 -70
- data/app/assets/plutonium.min.js.map +4 -4
- data/lib/plutonium/ui/form/base.rb +5 -0
- data/lib/plutonium/ui/form/components/secure_association.rb +3 -3
- data/lib/plutonium/version.rb +1 -1
- data/package.json +1 -1
- data/src/css/slim_select.css +78 -21
- data/src/js/controllers/register_controllers.js +2 -0
- data/src/js/controllers/textarea_autogrow_controller.js +56 -0
- data/yarn.lock +958 -1677
- metadata +2 -2
- data/package-lock.json +0 -6644
|
@@ -10,6 +10,11 @@ module Plutonium
|
|
|
10
10
|
include Phlexi::Field::Common::Tokens
|
|
11
11
|
include Plutonium::UI::Form::Options::InferredTypes
|
|
12
12
|
|
|
13
|
+
def textarea_tag(**attributes, &)
|
|
14
|
+
attributes[:data_controller] = tokens(attributes[:data_controller], "textarea-autogrow")
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
13
18
|
def easymde_tag(**, &)
|
|
14
19
|
create_component(Plutonium::UI::Form::Components::Easymde, :easymde, **, &)
|
|
15
20
|
end
|
|
@@ -8,7 +8,7 @@ module Plutonium
|
|
|
8
8
|
include Plutonium::UI::Component::Methods
|
|
9
9
|
|
|
10
10
|
def view_template
|
|
11
|
-
div(class: "flex space-x-1") do
|
|
11
|
+
div(class: "flex items-center space-x-1") do
|
|
12
12
|
super
|
|
13
13
|
render_add_button
|
|
14
14
|
end
|
|
@@ -23,9 +23,9 @@ module Plutonium
|
|
|
23
23
|
|
|
24
24
|
a(
|
|
25
25
|
href: add_url,
|
|
26
|
-
class: "bg-[var(--pu-surface-alt)] hover:bg-[var(--pu-border)] border border-[var(--pu-border)] rounded-[var(--pu-radius-md)]
|
|
26
|
+
class: "bg-[var(--pu-surface-alt)] hover:bg-[var(--pu-border)] border border-[var(--pu-border)] rounded-[var(--pu-radius-md)] px-4 py-3 focus:ring-2 focus:ring-[var(--pu-border)] focus:outline-none text-[var(--pu-text-muted)] hover:text-[var(--pu-text)] transition-colors"
|
|
27
27
|
) do
|
|
28
|
-
render Phlex::TablerIcons::Plus.new(class: "w-
|
|
28
|
+
render Phlex::TablerIcons::Plus.new(class: "w-6 h-6")
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
data/lib/plutonium/version.rb
CHANGED
data/package.json
CHANGED
data/src/css/slim_select.css
CHANGED
|
@@ -36,11 +36,25 @@
|
|
|
36
36
|
|
|
37
37
|
/* Main container - Updated to match form input theme */
|
|
38
38
|
.ss-main {
|
|
39
|
-
@apply flex flex-row relative select-none w-full
|
|
39
|
+
@apply flex flex-row items-center relative select-none w-full px-4 py-3 cursor-pointer border font-medium text-base leading-normal outline-none transition-colors duration-200 overflow-hidden focus:ring-2;
|
|
40
|
+
background-color: var(--pu-input-bg);
|
|
41
|
+
border-color: var(--pu-input-border);
|
|
42
|
+
border-radius: var(--pu-radius-md);
|
|
43
|
+
color: var(--pu-text);
|
|
44
|
+
}
|
|
45
|
+
.ss-main:hover {
|
|
46
|
+
border-color: var(--pu-border-strong);
|
|
47
|
+
}
|
|
48
|
+
.ss-main:focus,
|
|
49
|
+
.ss-main[aria-expanded="true"] {
|
|
50
|
+
border-color: var(--pu-input-focus-ring);
|
|
51
|
+
box-shadow: 0 0 0 3px theme(colors.primary.500 / 15%);
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
.ss-main.ss-disabled {
|
|
43
|
-
@apply cursor-not-allowed
|
|
55
|
+
@apply cursor-not-allowed;
|
|
56
|
+
background-color: var(--pu-surface-alt);
|
|
57
|
+
color: var(--pu-text-muted);
|
|
44
58
|
}
|
|
45
59
|
|
|
46
60
|
.ss-main.ss-disabled .ss-values .ss-value .ss-value-delete {
|
|
@@ -57,11 +71,12 @@
|
|
|
57
71
|
|
|
58
72
|
/* Values container */
|
|
59
73
|
.ss-main .ss-values {
|
|
60
|
-
@apply inline-flex flex-wrap gap-1 flex-1;
|
|
74
|
+
@apply inline-flex flex-wrap gap-1 flex-1 items-center min-h-[1.5em];
|
|
61
75
|
}
|
|
62
76
|
|
|
63
77
|
.ss-main .ss-values .ss-placeholder {
|
|
64
|
-
@apply flex px-0 py-0 my-auto
|
|
78
|
+
@apply flex px-0 py-0 my-auto items-center w-full overflow-hidden text-ellipsis whitespace-nowrap;
|
|
79
|
+
color: var(--pu-input-placeholder);
|
|
65
80
|
}
|
|
66
81
|
|
|
67
82
|
.ss-main .ss-values .ss-max {
|
|
@@ -111,7 +126,8 @@
|
|
|
111
126
|
}
|
|
112
127
|
|
|
113
128
|
.ss-main .ss-deselect svg path {
|
|
114
|
-
@apply fill-none
|
|
129
|
+
@apply fill-none;
|
|
130
|
+
stroke: var(--pu-text-muted);
|
|
115
131
|
stroke-width: 20;
|
|
116
132
|
stroke-linecap: round;
|
|
117
133
|
stroke-linejoin: round;
|
|
@@ -123,7 +139,8 @@
|
|
|
123
139
|
}
|
|
124
140
|
|
|
125
141
|
.ss-main .ss-arrow path {
|
|
126
|
-
@apply fill-none
|
|
142
|
+
@apply fill-none transition-transform duration-200;
|
|
143
|
+
stroke: var(--pu-text-muted);
|
|
127
144
|
stroke-width: 18;
|
|
128
145
|
stroke-linecap: round;
|
|
129
146
|
stroke-linejoin: round;
|
|
@@ -131,7 +148,10 @@
|
|
|
131
148
|
|
|
132
149
|
/* Content container - Updated to match shadow and borders */
|
|
133
150
|
.ss-content {
|
|
134
|
-
@apply absolute flex h-auto flex-col w-auto max-h-72 border
|
|
151
|
+
@apply absolute flex h-auto flex-col w-auto max-h-72 border transition-all duration-200 opacity-0 z-[10000] overflow-hidden;
|
|
152
|
+
background-color: var(--pu-surface);
|
|
153
|
+
border-color: var(--pu-border);
|
|
154
|
+
box-shadow: var(--pu-shadow-md);
|
|
135
155
|
transform: scaleY(0);
|
|
136
156
|
transform-origin: top;
|
|
137
157
|
}
|
|
@@ -162,14 +182,28 @@
|
|
|
162
182
|
}
|
|
163
183
|
|
|
164
184
|
.ss-content .ss-search input {
|
|
165
|
-
@apply inline-flex flex-auto w-full min-w-0 p-2 m-0 border
|
|
185
|
+
@apply inline-flex flex-auto w-full min-w-0 p-2 m-0 border font-medium text-sm outline-none text-left focus:ring-2;
|
|
186
|
+
background-color: var(--pu-input-bg);
|
|
187
|
+
border-color: var(--pu-input-border);
|
|
188
|
+
border-radius: var(--pu-radius-md);
|
|
189
|
+
color: var(--pu-text);
|
|
166
190
|
box-sizing: border-box;
|
|
167
191
|
font-size: inherit;
|
|
168
192
|
line-height: inherit;
|
|
169
193
|
}
|
|
194
|
+
.ss-content .ss-search input::placeholder {
|
|
195
|
+
color: var(--pu-input-placeholder);
|
|
196
|
+
}
|
|
197
|
+
.ss-content .ss-search input:focus {
|
|
198
|
+
border-color: var(--pu-input-focus-ring);
|
|
199
|
+
box-shadow: 0 0 0 3px theme(colors.primary.500 / 15%);
|
|
200
|
+
}
|
|
170
201
|
|
|
171
202
|
.ss-content .ss-search .ss-addable {
|
|
172
|
-
@apply inline-flex justify-center items-center cursor-pointer flex-none h-auto ml-2 border
|
|
203
|
+
@apply inline-flex justify-center items-center cursor-pointer flex-none h-auto ml-2 border;
|
|
204
|
+
border-color: var(--pu-border);
|
|
205
|
+
border-radius: var(--pu-radius-md);
|
|
206
|
+
box-shadow: var(--pu-shadow-sm);
|
|
173
207
|
}
|
|
174
208
|
|
|
175
209
|
.ss-content .ss-search .ss-addable svg {
|
|
@@ -177,7 +211,8 @@
|
|
|
177
211
|
}
|
|
178
212
|
|
|
179
213
|
.ss-content .ss-search .ss-addable svg path {
|
|
180
|
-
@apply fill-none
|
|
214
|
+
@apply fill-none;
|
|
215
|
+
stroke: var(--pu-text);
|
|
181
216
|
stroke-width: 18;
|
|
182
217
|
stroke-linecap: round;
|
|
183
218
|
stroke-linejoin: round;
|
|
@@ -193,7 +228,8 @@
|
|
|
193
228
|
}
|
|
194
229
|
|
|
195
230
|
.ss-content .ss-list .ss-searching {
|
|
196
|
-
@apply
|
|
231
|
+
@apply p-2;
|
|
232
|
+
color: var(--pu-text);
|
|
197
233
|
}
|
|
198
234
|
|
|
199
235
|
.ss-content .ss-list .ss-optgroup.ss-close .ss-option {
|
|
@@ -202,11 +238,13 @@
|
|
|
202
238
|
|
|
203
239
|
/* Option groups - Updated colors */
|
|
204
240
|
.ss-content .ss-list .ss-optgroup .ss-optgroup-label {
|
|
205
|
-
@apply flex flex-row items-center justify-between p-2
|
|
241
|
+
@apply flex flex-row items-center justify-between p-2;
|
|
242
|
+
background-color: var(--pu-surface-alt);
|
|
206
243
|
}
|
|
207
244
|
|
|
208
245
|
.ss-content .ss-list .ss-optgroup .ss-optgroup-label .ss-optgroup-label-text {
|
|
209
|
-
@apply flex-auto font-bold
|
|
246
|
+
@apply flex-auto font-bold;
|
|
247
|
+
color: var(--pu-text);
|
|
210
248
|
}
|
|
211
249
|
|
|
212
250
|
.ss-content .ss-list .ss-optgroup .ss-optgroup-label:has(.ss-arrow) {
|
|
@@ -256,7 +294,8 @@
|
|
|
256
294
|
}
|
|
257
295
|
|
|
258
296
|
.ss-content .ss-list .ss-optgroup .ss-optgroup-label .ss-optgroup-actions .ss-closable .ss-arrow path {
|
|
259
|
-
@apply fill-none
|
|
297
|
+
@apply fill-none transition-transform duration-200;
|
|
298
|
+
stroke: var(--pu-text);
|
|
260
299
|
stroke-width: 18;
|
|
261
300
|
stroke-linecap: round;
|
|
262
301
|
stroke-linejoin: round;
|
|
@@ -268,7 +307,8 @@
|
|
|
268
307
|
|
|
269
308
|
/* Options - Updated text colors to match theme */
|
|
270
309
|
.ss-content .ss-list .ss-option {
|
|
271
|
-
@apply block p-2 whitespace-normal
|
|
310
|
+
@apply block p-2 whitespace-normal cursor-pointer select-none hover:bg-primary-500 hover:text-white;
|
|
311
|
+
color: var(--pu-text);
|
|
272
312
|
min-height: 0;
|
|
273
313
|
}
|
|
274
314
|
|
|
@@ -282,11 +322,14 @@
|
|
|
282
322
|
}
|
|
283
323
|
|
|
284
324
|
.ss-content .ss-list .ss-option.ss-disabled {
|
|
285
|
-
@apply cursor-not-allowed
|
|
325
|
+
@apply cursor-not-allowed;
|
|
326
|
+
background-color: var(--pu-surface-alt);
|
|
327
|
+
color: var(--pu-text-muted);
|
|
286
328
|
}
|
|
287
329
|
|
|
288
330
|
.ss-content .ss-list .ss-option.ss-disabled:hover {
|
|
289
|
-
|
|
331
|
+
background-color: var(--pu-surface-alt);
|
|
332
|
+
color: var(--pu-text-muted);
|
|
290
333
|
}
|
|
291
334
|
|
|
292
335
|
.ss-content .ss-list .ss-option .ss-search-highlight {
|
|
@@ -295,19 +338,33 @@
|
|
|
295
338
|
|
|
296
339
|
/* Additional state classes to match form validation states */
|
|
297
340
|
.ss-main.ss-invalid {
|
|
298
|
-
@apply
|
|
341
|
+
@apply border-danger-500 bg-danger-50/50 text-danger-900;
|
|
342
|
+
}
|
|
343
|
+
.ss-main.ss-invalid:focus,
|
|
344
|
+
.ss-main.ss-invalid[aria-expanded="true"] {
|
|
345
|
+
box-shadow: 0 0 0 3px theme(colors.danger.500 / 15%);
|
|
346
|
+
}
|
|
347
|
+
.dark .ss-main.ss-invalid {
|
|
348
|
+
@apply bg-danger-950/20 border-danger-500/70 text-danger-200;
|
|
299
349
|
}
|
|
300
350
|
|
|
301
351
|
.ss-main.ss-invalid .ss-values .ss-placeholder {
|
|
302
|
-
@apply text-
|
|
352
|
+
@apply text-danger-400;
|
|
303
353
|
}
|
|
304
354
|
|
|
305
355
|
.ss-main.ss-valid {
|
|
306
|
-
@apply
|
|
356
|
+
@apply border-success-500 bg-success-50/50 text-success-900;
|
|
357
|
+
}
|
|
358
|
+
.ss-main.ss-valid:focus,
|
|
359
|
+
.ss-main.ss-valid[aria-expanded="true"] {
|
|
360
|
+
box-shadow: 0 0 0 3px theme(colors.success.500 / 15%);
|
|
361
|
+
}
|
|
362
|
+
.dark .ss-main.ss-valid {
|
|
363
|
+
@apply bg-success-950/20 border-success-500/70 text-success-200;
|
|
307
364
|
}
|
|
308
365
|
|
|
309
366
|
.ss-main.ss-valid .ss-values .ss-placeholder {
|
|
310
|
-
@apply text-
|
|
367
|
+
@apply text-success-400;
|
|
311
368
|
}
|
|
312
369
|
|
|
313
370
|
/* Modal-specific styles for SlimSelect dropdown */
|
|
@@ -22,6 +22,7 @@ import RemoteModalController from "./remote_modal_controller.js"
|
|
|
22
22
|
import KeyValueStoreController from "./key_value_store_controller.js"
|
|
23
23
|
import BulkActionsController from "./bulk_actions_controller.js"
|
|
24
24
|
import FilterPanelController from "./filter_panel_controller.js"
|
|
25
|
+
import TextareaAutogrowController from "./textarea_autogrow_controller.js"
|
|
25
26
|
|
|
26
27
|
export default function (application) {
|
|
27
28
|
// Register controllers here
|
|
@@ -48,4 +49,5 @@ export default function (application) {
|
|
|
48
49
|
application.register("key-value-store", KeyValueStoreController)
|
|
49
50
|
application.register("bulk-actions", BulkActionsController)
|
|
50
51
|
application.register("filter-panel", FilterPanelController)
|
|
52
|
+
application.register("textarea-autogrow", TextareaAutogrowController)
|
|
51
53
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
export default class extends Controller {
|
|
4
|
+
static values = {
|
|
5
|
+
maxHeight: { type: Number, default: 0 } // 0 means use CSS max-height or 50vh
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
connect() {
|
|
9
|
+
this.resize()
|
|
10
|
+
this.element.addEventListener("input", this.resize)
|
|
11
|
+
window.addEventListener("resize", this.resize)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
disconnect() {
|
|
15
|
+
this.element.removeEventListener("input", this.resize)
|
|
16
|
+
window.removeEventListener("resize", this.resize)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
resize = () => {
|
|
20
|
+
const element = this.element
|
|
21
|
+
const maxHeight = this.#getMaxHeight()
|
|
22
|
+
|
|
23
|
+
// Reset to auto to get the natural scroll height
|
|
24
|
+
element.style.height = "auto"
|
|
25
|
+
element.style.overflow = "hidden"
|
|
26
|
+
|
|
27
|
+
const scrollHeight = element.scrollHeight
|
|
28
|
+
|
|
29
|
+
if (maxHeight > 0 && scrollHeight > maxHeight) {
|
|
30
|
+
element.style.height = `${maxHeight}px`
|
|
31
|
+
element.style.overflow = "auto"
|
|
32
|
+
} else {
|
|
33
|
+
element.style.height = `${scrollHeight}px`
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#getMaxHeight() {
|
|
38
|
+
if (this.maxHeightValue > 0) {
|
|
39
|
+
return this.maxHeightValue
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Check for CSS max-height
|
|
43
|
+
const computedStyle = window.getComputedStyle(this.element)
|
|
44
|
+
const cssMaxHeight = computedStyle.maxHeight
|
|
45
|
+
|
|
46
|
+
if (cssMaxHeight && cssMaxHeight !== "none") {
|
|
47
|
+
const parsed = parseFloat(cssMaxHeight)
|
|
48
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
49
|
+
return parsed
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Default to 300px
|
|
54
|
+
return 300
|
|
55
|
+
}
|
|
56
|
+
}
|