plutonium 0.53.1 → 0.55.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/.claude/skills/plutonium-behavior/SKILL.md +22 -0
- data/.claude/skills/plutonium-resource/SKILL.md +55 -0
- data/.claude/skills/plutonium-ui/SKILL.md +2 -1
- data/CHANGELOG.md +38 -0
- data/app/assets/plutonium.css +1 -1
- data/app/assets/plutonium.js +40 -6
- data/app/assets/plutonium.js.map +4 -4
- data/app/assets/plutonium.min.js +32 -32
- data/app/assets/plutonium.min.js.map +4 -4
- data/app/views/plutonium/_flash_alerts.html.erb +8 -17
- data/app/views/plutonium/_flash_toasts.html.erb +9 -18
- data/docs/public/images/reference/structured-inputs-removed.png +0 -0
- data/docs/public/images/reference/structured-inputs.png +0 -0
- data/docs/reference/resource/definition.md +110 -0
- data/docs/superpowers/plans/2026-06-02-structured-inputs.md +1061 -0
- data/docs/superpowers/plans/2026-06-02-structured-inputs.md.tasks.json +60 -0
- data/docs/superpowers/specs/2026-06-01-structured-inputs-design.md +191 -0
- data/gemfiles/rails_8.1.gemfile.lock +1 -1
- data/lib/plutonium/definition/base.rb +1 -0
- data/lib/plutonium/definition/structured_inputs.rb +67 -0
- data/lib/plutonium/engine/validator.rb +11 -4
- data/lib/plutonium/interaction/README.md +24 -78
- data/lib/plutonium/interaction/base.rb +10 -2
- data/lib/plutonium/resource/controller.rb +6 -1
- data/lib/plutonium/resource/controllers/interactive_actions.rb +10 -6
- data/lib/plutonium/structured_inputs/param_cleaner.rb +36 -0
- data/lib/plutonium/structured_inputs/params_concern.rb +36 -0
- data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +3 -3
- data/lib/plutonium/ui/form/concerns/renders_structured_inputs.rb +178 -0
- data/lib/plutonium/ui/form/concerns/repeater_field_styles.rb +24 -0
- data/lib/plutonium/ui/form/resource.rb +15 -5
- data/lib/plutonium/ui/form/theme.rb +14 -3
- data/lib/plutonium/ui/modal/slideover.rb +9 -3
- data/lib/plutonium/version.rb +1 -1
- data/package.json +1 -1
- data/src/css/components.css +119 -5
- data/src/js/controllers/capture_url_controller.js +20 -7
- data/src/js/controllers/dirty_form_guard_controller.js +28 -4
- data/src/js/controllers/icon_rail_flyout_controller.js +5 -2
- data/src/js/controllers/register_controllers.js +2 -0
- data/src/js/controllers/remote_modal_controller.js +5 -0
- data/src/js/controllers/structured_input_row_controller.js +26 -0
- metadata +14 -4
- data/lib/plutonium/interaction/nested_attributes.rb +0 -93
data/app/assets/plutonium.js
CHANGED
|
@@ -11510,6 +11510,23 @@
|
|
|
11510
11510
|
}
|
|
11511
11511
|
};
|
|
11512
11512
|
|
|
11513
|
+
// src/js/controllers/structured_input_row_controller.js
|
|
11514
|
+
var structured_input_row_controller_default = class extends Controller {
|
|
11515
|
+
static targets = ["content", "removed"];
|
|
11516
|
+
remove(e4) {
|
|
11517
|
+
e4.preventDefault();
|
|
11518
|
+
this.contentTarget.disabled = true;
|
|
11519
|
+
this.contentTarget.hidden = true;
|
|
11520
|
+
this.removedTarget.hidden = false;
|
|
11521
|
+
}
|
|
11522
|
+
restore(e4) {
|
|
11523
|
+
e4.preventDefault();
|
|
11524
|
+
this.contentTarget.disabled = false;
|
|
11525
|
+
this.contentTarget.hidden = false;
|
|
11526
|
+
this.removedTarget.hidden = true;
|
|
11527
|
+
}
|
|
11528
|
+
};
|
|
11529
|
+
|
|
11513
11530
|
// src/js/controllers/form_controller.js
|
|
11514
11531
|
var form_controller_default = class extends Controller {
|
|
11515
11532
|
connect() {
|
|
@@ -27613,6 +27630,7 @@ this.ifd0Offset: ${this.ifd0Offset}, file.byteLength: ${e4.byteLength}`), e4.tif
|
|
|
27613
27630
|
this.#animateClose();
|
|
27614
27631
|
}
|
|
27615
27632
|
#onCancel(event) {
|
|
27633
|
+
if (event.target !== this.element) return;
|
|
27616
27634
|
if (event.defaultPrevented) return;
|
|
27617
27635
|
event.preventDefault();
|
|
27618
27636
|
this.#animateClose();
|
|
@@ -28066,7 +28084,8 @@ this.ifd0Offset: ${this.ifd0Offset}, file.byteLength: ${e4.byteLength}`), e4.tif
|
|
|
28066
28084
|
const viewportH = window.innerHeight;
|
|
28067
28085
|
if (panelRect.bottom > viewportH - 8) {
|
|
28068
28086
|
const overflow = panelRect.bottom - (viewportH - 8);
|
|
28069
|
-
|
|
28087
|
+
const top2 = Math.max(8, parseFloat(panel.style.top) - overflow);
|
|
28088
|
+
panel.style.top = `${top2}px`;
|
|
28070
28089
|
}
|
|
28071
28090
|
});
|
|
28072
28091
|
}
|
|
@@ -28125,9 +28144,12 @@ this.ifd0Offset: ${this.ifd0Offset}, file.byteLength: ${e4.byteLength}`), e4.tif
|
|
|
28125
28144
|
// src/js/controllers/capture_url_controller.js
|
|
28126
28145
|
var capture_url_controller_default = class extends Controller {
|
|
28127
28146
|
connect() {
|
|
28128
|
-
if ("value" in this.element)
|
|
28129
|
-
|
|
28130
|
-
|
|
28147
|
+
if (!("value" in this.element)) return;
|
|
28148
|
+
const base = this.element.value;
|
|
28149
|
+
if (!base) return;
|
|
28150
|
+
const { hash: hash3 } = window.location;
|
|
28151
|
+
if (!hash3) return;
|
|
28152
|
+
this.element.value = base.split("#")[0] + hash3;
|
|
28131
28153
|
}
|
|
28132
28154
|
};
|
|
28133
28155
|
|
|
@@ -28212,9 +28234,9 @@ this.ifd0Offset: ${this.ifd0Offset}, file.byteLength: ${e4.byteLength}`), e4.tif
|
|
|
28212
28234
|
this.confirmDialogTarget.removeEventListener("cancel", this.onConfirmCancel);
|
|
28213
28235
|
}
|
|
28214
28236
|
}
|
|
28215
|
-
|
|
28237
|
+
discard() {
|
|
28216
28238
|
this.forceClose = true;
|
|
28217
|
-
|
|
28239
|
+
this.#snapConfirmClosed();
|
|
28218
28240
|
this.dialog.dispatchEvent(new CustomEvent("modal:request-close"));
|
|
28219
28241
|
}
|
|
28220
28242
|
keepEditing() {
|
|
@@ -28258,6 +28280,7 @@ this.ifd0Offset: ${this.ifd0Offset}, file.byteLength: ${e4.byteLength}`), e4.tif
|
|
|
28258
28280
|
this.#promptDiscard();
|
|
28259
28281
|
}
|
|
28260
28282
|
#onCancel(event) {
|
|
28283
|
+
if (event.target !== this.dialog) return;
|
|
28261
28284
|
if (this.forceClose || this.submitting) return;
|
|
28262
28285
|
if (!this.#isDirty()) return;
|
|
28263
28286
|
event.preventDefault();
|
|
@@ -28285,6 +28308,16 @@ this.ifd0Offset: ${this.ifd0Offset}, file.byteLength: ${e4.byteLength}`), e4.tif
|
|
|
28285
28308
|
this.dialog.dispatchEvent(new CustomEvent("modal:request-close"));
|
|
28286
28309
|
}
|
|
28287
28310
|
}
|
|
28311
|
+
// Close the confirm immediately, skipping its exit transition. Used by
|
|
28312
|
+
// discard(), where the parent modal is about to animate away and a
|
|
28313
|
+
// separate confirm fade would only stutter against the modal's live
|
|
28314
|
+
// backdrop blur.
|
|
28315
|
+
#snapConfirmClosed() {
|
|
28316
|
+
if (!this.hasConfirmDialogTarget) return;
|
|
28317
|
+
const d4 = this.confirmDialogTarget;
|
|
28318
|
+
d4.removeAttribute("data-open");
|
|
28319
|
+
if (d4.open) d4.close();
|
|
28320
|
+
}
|
|
28288
28321
|
async #closeConfirm() {
|
|
28289
28322
|
if (!this.hasConfirmDialogTarget) return;
|
|
28290
28323
|
const d4 = this.confirmDialogTarget;
|
|
@@ -28302,6 +28335,7 @@ this.ifd0Offset: ${this.ifd0Offset}, file.byteLength: ${e4.byteLength}`), e4.tif
|
|
|
28302
28335
|
application2.register("sidebar", sidebar_controller_default);
|
|
28303
28336
|
application2.register("resource-header", resource_header_controller_default);
|
|
28304
28337
|
application2.register("nested-resource-form-fields", nested_resource_form_fields_controller_default);
|
|
28338
|
+
application2.register("structured-input-row", structured_input_row_controller_default);
|
|
28305
28339
|
application2.register("form", form_controller_default);
|
|
28306
28340
|
application2.register("resource-drop-down", resource_drop_down_controller_default);
|
|
28307
28341
|
application2.register("resource-collapse", resource_collapse_controller_default);
|