@rogatio/cli 6.5.0 → 6.6.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.
@@ -276,13 +276,26 @@
276
276
  .rogatio-editor [data-editor-command-bar] {
277
277
  display: flex;
278
278
  flex-wrap: wrap;
279
- gap: 0.5rem;
279
+ align-items: center;
280
+ justify-content: space-between;
281
+ gap: 0.75rem 1rem;
280
282
  margin-block: 1rem;
281
283
  padding: 0.65rem 0.75rem;
282
284
  border: 1px solid var(--rogatio-border);
283
285
  border-radius: var(--rogatio-radius);
284
286
  background: var(--rogatio-surface-raised);
285
287
  }
288
+ .rogatio-editor [data-action-cluster] {
289
+ display: flex;
290
+ flex-wrap: wrap;
291
+ align-items: center;
292
+ gap: 0.5rem;
293
+ }
294
+ .rogatio-editor [data-action-cluster=danger] {
295
+ margin-left: 0.15rem;
296
+ padding-left: 0.65rem;
297
+ border-left: 1px solid var(--rogatio-border);
298
+ }
286
299
  .rogatio-editor [data-editor-form] {
287
300
  display: grid;
288
301
  gap: 1rem;
@@ -385,9 +398,57 @@
385
398
  justify-content: space-between;
386
399
  gap: 0.65rem;
387
400
  }
388
- .rogatio-editor [data-group-heading] button[data-group-enable] {
389
- padding: 0.55rem 1.05rem;
390
- font-size: 0.95rem;
401
+ .rogatio-editor [data-group-identity] {
402
+ display: flex;
403
+ flex: 1 1 auto;
404
+ align-items: center;
405
+ gap: 0.35rem;
406
+ min-width: 0;
407
+ }
408
+ .rogatio-editor [data-group-actions] {
409
+ display: flex;
410
+ flex-wrap: wrap;
411
+ align-items: center;
412
+ gap: 0.5rem;
413
+ margin-left: auto;
414
+ }
415
+ .rogatio-editor [data-action-dock] {
416
+ display: grid;
417
+ margin-top: 0.35rem;
418
+ border: 1px solid var(--rogatio-border);
419
+ border-left: 3px solid var(--rogatio-card-rule-edge);
420
+ border-radius: var(--rogatio-radius);
421
+ background: var(--rogatio-surface-inset);
422
+ overflow: hidden;
423
+ }
424
+ .rogatio-editor [data-dock-row] {
425
+ display: grid;
426
+ grid-template-columns: 5.5rem minmax(0, 1fr);
427
+ column-gap: 0.75rem;
428
+ align-items: center;
429
+ padding: 0.65rem 0.85rem;
430
+ }
431
+ .rogatio-editor [data-dock-row] + [data-dock-row] {
432
+ border-top: 1px solid var(--rogatio-border);
433
+ }
434
+ .rogatio-editor [data-dock-label] {
435
+ font-family: var(--rogatio-font-mono);
436
+ font-size: 0.6875rem;
437
+ font-weight: 700;
438
+ letter-spacing: 0.08em;
439
+ text-transform: uppercase;
440
+ color: var(--rogatio-muted);
441
+ }
442
+ .rogatio-editor [data-dock-actions] {
443
+ display: flex;
444
+ flex-wrap: wrap;
445
+ align-items: center;
446
+ justify-content: flex-end;
447
+ gap: 0.5rem 0.75rem;
448
+ min-width: 0;
449
+ }
450
+ .rogatio-editor [data-dock-actions] [data-action-cluster=tools] {
451
+ margin-right: auto;
391
452
  }
392
453
  .rogatio-editor [data-group-heading] h2,
393
454
  .rogatio-editor [data-section-heading] h2,
@@ -605,6 +666,22 @@
605
666
  .rogatio-editor [data-section-heading] {
606
667
  align-items: flex-start;
607
668
  }
669
+ .rogatio-editor [data-group-actions] {
670
+ margin-left: 0;
671
+ width: 100%;
672
+ }
673
+ .rogatio-editor [data-dock-row] {
674
+ grid-template-columns: 1fr;
675
+ justify-items: start;
676
+ row-gap: 0.45rem;
677
+ }
678
+ .rogatio-editor [data-dock-actions] {
679
+ justify-content: flex-start;
680
+ width: 100%;
681
+ }
682
+ .rogatio-editor [data-dock-actions] [data-action-cluster=tools] {
683
+ margin-right: 0;
684
+ }
608
685
  .rogatio-editor [data-rule-actions] {
609
686
  justify-content: flex-start;
610
687
  width: 100%;
@@ -630,7 +707,9 @@
630
707
  .rogatio-editor fieldset,
631
708
  .rogatio-editor [data-rule-card],
632
709
  .rogatio-editor [data-group-row],
633
- .rogatio-editor [data-editor-check-group] {
710
+ .rogatio-editor [data-editor-check-group],
711
+ .rogatio-editor [data-action-dock],
712
+ .rogatio-editor [data-action-cluster=danger] {
634
713
  border-color: ButtonText;
635
714
  background: Canvas;
636
715
  }
@@ -2238,7 +2238,7 @@ var EditorControllerImpl = class {
2238
2238
  this.commandBar = this.document.createElement("div");
2239
2239
  this.commandBar.dataset.editorCommandBar = "true";
2240
2240
  this.commandBar.setAttribute("role", "toolbar");
2241
- this.commandBar.setAttribute("aria-label", "Editor commands");
2241
+ this.commandBar.setAttribute("aria-label", "Project actions");
2242
2242
  this.form = this.document.createElement("form");
2243
2243
  this.form.dataset.editorForm = "true";
2244
2244
  this.form.noValidate = true;
@@ -3485,7 +3485,7 @@ var EditorControllerImpl = class {
3485
3485
  const draftGroup = this.draftGroupForSavedId(groupId);
3486
3486
  const groupName = displayName(
3487
3487
  draftGroup?.name,
3488
- button.parentElement?.querySelector("h2")?.textContent?.trim() ?? ""
3488
+ this.host.querySelector("[data-group-heading] h2")?.textContent?.trim() ?? ""
3489
3489
  );
3490
3490
  this.applyGroupEnablementLabel(button, enabled.has(groupId), groupName);
3491
3491
  }
@@ -3616,6 +3616,7 @@ var EditorControllerImpl = class {
3616
3616
  } else {
3617
3617
  this.renderGroup(this.route.groupId);
3618
3618
  }
3619
+ this.renderActionDock();
3619
3620
  this.decorateExtensionControls();
3620
3621
  this.renderSummary();
3621
3622
  this.renderMigrationNotices();
@@ -3722,24 +3723,185 @@ var EditorControllerImpl = class {
3722
3723
  renderCommandBar() {
3723
3724
  this.commandBar.replaceChildren();
3724
3725
  this.commandBar.setAttribute("aria-busy", this.saving ? "true" : "false");
3726
+ this.commandBar.setAttribute("aria-label", "Project actions");
3727
+ const tools = this.document.createElement("div");
3728
+ tools.dataset.actionCluster = "tools";
3725
3729
  if (this.aiAssistPanel) {
3726
- this.commandBar.append(
3730
+ tools.append(
3727
3731
  this.createCommandButton("AI Assist", "ai-assist", this.saving)
3728
3732
  );
3729
3733
  }
3730
- this.commandBar.append(
3731
- this.createCommandButton("Validate", "validate", this.saving),
3734
+ tools.append(this.createCommandButton("Validate", "validate", this.saving));
3735
+ if (this.route.kind === "project") {
3736
+ tools.append(
3737
+ this.createCommandButton(
3738
+ "Add group",
3739
+ "add-group",
3740
+ this.saving,
3741
+ {},
3742
+ "primary"
3743
+ )
3744
+ );
3745
+ } else if (this.route.kind === "test") {
3746
+ tools.append(
3747
+ this.createCommandButton(
3748
+ "Run test",
3749
+ "test:run",
3750
+ this.saving || this.testRunning,
3751
+ {},
3752
+ "primary"
3753
+ )
3754
+ );
3755
+ }
3756
+ const commit = this.document.createElement("div");
3757
+ commit.dataset.actionCluster = "commit";
3758
+ commit.append(
3759
+ this.createCommandButton("Cancel", "cancel", this.saving),
3732
3760
  this.createCommandButton(
3733
3761
  "Save",
3734
3762
  "save",
3735
3763
  this.saving || !this.isDirty(),
3736
3764
  {},
3737
3765
  "primary"
3738
- ),
3739
- this.createCommandButton("Cancel", "cancel", this.saving)
3766
+ )
3740
3767
  );
3741
- if (this.route.kind === "project") {
3742
- this.commandBar.append(
3768
+ this.commandBar.append(tools, commit);
3769
+ }
3770
+ createGroupEnableButton(savedGroupId, groupName) {
3771
+ const enablement = this.options.groupEnablement;
3772
+ const enableButton = this.document.createElement("button");
3773
+ enableButton.type = "button";
3774
+ enableButton.dataset.groupEnable = "true";
3775
+ enableButton.dataset.groupId = savedGroupId;
3776
+ enableButton.dataset.btn = "primary";
3777
+ this.applyGroupEnablementLabel(
3778
+ enableButton,
3779
+ enablement?.isEnabled(savedGroupId) === true,
3780
+ groupName
3781
+ );
3782
+ enableButton.addEventListener("click", (event) => {
3783
+ event.preventDefault();
3784
+ event.stopPropagation();
3785
+ if (enableButton.disabled || !enablement) return;
3786
+ const next = enablement.isEnabled(savedGroupId) !== true;
3787
+ const peers = Array.from(
3788
+ this.host.querySelectorAll(
3789
+ "button[data-group-enable]"
3790
+ )
3791
+ ).filter((peer) => peer.dataset.groupId === savedGroupId);
3792
+ for (const peer of peers) peer.disabled = true;
3793
+ void Promise.resolve(enablement.setEnabled(savedGroupId, next)).finally(
3794
+ () => {
3795
+ for (const peer of peers) {
3796
+ if (peer.isConnected) peer.disabled = false;
3797
+ }
3798
+ }
3799
+ );
3800
+ });
3801
+ return enableButton;
3802
+ }
3803
+ /** Enable/Disable, Copy, and Remove as one toolbar. Remove stays visually last. */
3804
+ createGroupActionClusters(groupId, groupName) {
3805
+ const actions = this.document.createElement("div");
3806
+ actions.dataset.groupActions = "true";
3807
+ actions.setAttribute("role", "toolbar");
3808
+ actions.setAttribute("aria-label", `Actions for group ${groupName}`);
3809
+ const safe = this.document.createElement("div");
3810
+ safe.dataset.actionCluster = "safe";
3811
+ const group = this.groupById(groupId);
3812
+ const savedGroupId = group ? this.savedGroupId(group) : void 0;
3813
+ if (this.options.groupEnablement && savedGroupId) {
3814
+ safe.append(this.createGroupEnableButton(savedGroupId, groupName));
3815
+ }
3816
+ safe.append(
3817
+ this.createCommandButton("Copy group", "copy-group", this.saving, {
3818
+ groupId
3819
+ })
3820
+ );
3821
+ const danger = this.document.createElement("div");
3822
+ danger.dataset.actionCluster = "danger";
3823
+ danger.append(
3824
+ this.createCommandButton(
3825
+ "Remove group",
3826
+ "remove-group",
3827
+ this.saving,
3828
+ { groupId },
3829
+ "danger"
3830
+ )
3831
+ );
3832
+ actions.append(safe, danger);
3833
+ return actions;
3834
+ }
3835
+ createProjectActionRow() {
3836
+ const actions = this.document.createElement("div");
3837
+ const tools = this.document.createElement("div");
3838
+ tools.dataset.actionCluster = "tools";
3839
+ if (this.aiAssistPanel) {
3840
+ tools.append(
3841
+ this.createCommandButton("AI Assist", "ai-assist", this.saving)
3842
+ );
3843
+ }
3844
+ tools.append(this.createCommandButton("Validate", "validate", this.saving));
3845
+ const commit = this.document.createElement("div");
3846
+ commit.dataset.actionCluster = "commit";
3847
+ commit.append(
3848
+ this.createCommandButton("Cancel", "cancel", this.saving),
3849
+ this.createCommandButton(
3850
+ "Save",
3851
+ "save",
3852
+ this.saving || !this.isDirty(),
3853
+ {},
3854
+ "primary"
3855
+ )
3856
+ );
3857
+ actions.append(tools, commit);
3858
+ return actions;
3859
+ }
3860
+ appendDockRow(dock, label, actions) {
3861
+ const row = this.document.createElement("div");
3862
+ row.dataset.dockRow = "true";
3863
+ const labelEl = this.document.createElement("span");
3864
+ labelEl.dataset.dockLabel = "true";
3865
+ labelEl.textContent = label;
3866
+ actions.dataset.dockActions = "true";
3867
+ row.append(labelEl, actions);
3868
+ dock.append(row);
3869
+ }
3870
+ /**
3871
+ * Repeats the actions a long page would otherwise hide: under the last rule,
3872
+ * under the project group list, or under the test results.
3873
+ */
3874
+ renderActionDock() {
3875
+ const dock = this.document.createElement("section");
3876
+ dock.dataset.actionDock = "end";
3877
+ dock.setAttribute("aria-label", "Repeated actions");
3878
+ if (this.route.kind === "group") {
3879
+ const groupId = this.route.groupId;
3880
+ const group = this.groupById(groupId);
3881
+ if (group) {
3882
+ const groupName = displayName(group.name, "Unnamed group");
3883
+ const addRule = this.document.createElement("div");
3884
+ addRule.dataset.actionCluster = "safe";
3885
+ addRule.append(
3886
+ this.createCommandButton(
3887
+ "Add rule",
3888
+ "add-rule",
3889
+ this.saving,
3890
+ { groupId },
3891
+ "primary"
3892
+ )
3893
+ );
3894
+ this.appendDockRow(dock, "Rules", addRule);
3895
+ this.appendDockRow(
3896
+ dock,
3897
+ "Group",
3898
+ this.createGroupActionClusters(groupId, groupName)
3899
+ );
3900
+ }
3901
+ } else if (this.route.kind === "project") {
3902
+ const addGroup = this.document.createElement("div");
3903
+ addGroup.dataset.actionCluster = "safe";
3904
+ addGroup.append(
3743
3905
  this.createCommandButton(
3744
3906
  "Add group",
3745
3907
  "add-group",
@@ -3748,19 +3910,23 @@ var EditorControllerImpl = class {
3748
3910
  "primary"
3749
3911
  )
3750
3912
  );
3751
- return;
3752
- }
3753
- if (this.route.kind === "test") {
3754
- this.commandBar.append(
3913
+ this.appendDockRow(dock, "Groups", addGroup);
3914
+ } else {
3915
+ const run = this.document.createElement("div");
3916
+ run.dataset.actionCluster = "safe";
3917
+ run.append(
3755
3918
  this.createCommandButton(
3756
3919
  "Run test",
3757
3920
  "test:run",
3758
- this.saving,
3921
+ this.saving || this.testRunning,
3759
3922
  {},
3760
3923
  "primary"
3761
3924
  )
3762
3925
  );
3926
+ this.appendDockRow(dock, "Test", run);
3763
3927
  }
3928
+ this.appendDockRow(dock, "Project", this.createProjectActionRow());
3929
+ this.form.append(dock);
3764
3930
  }
3765
3931
  renderProject() {
3766
3932
  const heading = this.document.createElement("h2");
@@ -3841,51 +4007,11 @@ var EditorControllerImpl = class {
3841
4007
  const groupName = displayName(group.name, "Unnamed group");
3842
4008
  const headingRow = this.document.createElement("div");
3843
4009
  headingRow.dataset.groupHeading = "true";
4010
+ const identity = this.document.createElement("div");
4011
+ identity.dataset.groupIdentity = "true";
3844
4012
  const heading = this.document.createElement("h2");
3845
- const copyGroup = this.createCommandButton(
3846
- "Copy group",
3847
- "copy-group",
3848
- this.saving,
3849
- { groupId }
3850
- );
3851
- const removeGroup = this.createCommandButton(
3852
- "Remove group",
3853
- "remove-group",
3854
- this.saving,
3855
- { groupId },
3856
- "danger"
3857
- );
3858
- const savedGroupId = this.savedGroupId(group);
3859
- const enablement = this.options.groupEnablement;
3860
- const commands = [];
3861
- if (enablement && savedGroupId) {
3862
- const enableButton = this.document.createElement("button");
3863
- enableButton.type = "button";
3864
- enableButton.dataset.groupEnable = "true";
3865
- enableButton.dataset.groupId = savedGroupId;
3866
- enableButton.dataset.btn = "primary";
3867
- this.applyGroupEnablementLabel(
3868
- enableButton,
3869
- enablement.isEnabled(savedGroupId) === true,
3870
- groupName
3871
- );
3872
- enableButton.addEventListener("click", (event) => {
3873
- event.preventDefault();
3874
- event.stopPropagation();
3875
- if (enableButton.disabled) return;
3876
- const next = enablement.isEnabled(savedGroupId) !== true;
3877
- enableButton.disabled = true;
3878
- void Promise.resolve(enablement.setEnabled(savedGroupId, next)).finally(
3879
- () => {
3880
- if (enableButton.isConnected) enableButton.disabled = false;
3881
- }
3882
- );
3883
- });
3884
- commands.push(enableButton);
3885
- }
3886
- commands.push(copyGroup, removeGroup);
3887
4013
  this.renderNameHeading({
3888
- row: headingRow,
4014
+ row: identity,
3889
4015
  heading,
3890
4016
  headingId: `${this.instanceId}-group-title-${groupIndex}`,
3891
4017
  kind: "group",
@@ -3893,8 +4019,12 @@ var EditorControllerImpl = class {
3893
4019
  namePath: pointer("groups", groupIndex, "name"),
3894
4020
  name: group.name,
3895
4021
  fallback: "Unnamed group",
3896
- commands
4022
+ commands: []
3897
4023
  });
4024
+ headingRow.append(
4025
+ identity,
4026
+ this.createGroupActionClusters(groupId, groupName)
4027
+ );
3898
4028
  this.form.append(headingRow);
3899
4029
  const rulesSection = this.document.createElement("section");
3900
4030
  rulesSection.dataset.rulesSection = "true";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogatio/cli",
3
- "version": "6.5.0",
3
+ "version": "6.6.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Local-first browser request and response rules — editor host, file verification, test runner, and runtime dispatch.",