@rogatio/cli 6.5.0 → 6.6.1

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,58 @@
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
+ .rogatio-editor [data-rule-identity] {
403
+ display: flex;
404
+ flex: 1 1 auto;
405
+ align-items: center;
406
+ gap: 0.35rem;
407
+ min-width: 0;
408
+ }
409
+ .rogatio-editor [data-group-actions] {
410
+ display: flex;
411
+ flex-wrap: wrap;
412
+ align-items: center;
413
+ gap: 0.5rem;
414
+ margin-left: auto;
415
+ }
416
+ .rogatio-editor [data-action-dock] {
417
+ display: grid;
418
+ margin-top: 0.35rem;
419
+ border: 1px solid var(--rogatio-border);
420
+ border-left: 3px solid var(--rogatio-card-rule-edge);
421
+ border-radius: var(--rogatio-radius);
422
+ background: var(--rogatio-surface-inset);
423
+ overflow: hidden;
424
+ }
425
+ .rogatio-editor [data-dock-row] {
426
+ display: grid;
427
+ grid-template-columns: 5.5rem minmax(0, 1fr);
428
+ column-gap: 0.75rem;
429
+ align-items: center;
430
+ padding: 0.65rem 0.85rem;
431
+ }
432
+ .rogatio-editor [data-dock-row] + [data-dock-row] {
433
+ border-top: 1px solid var(--rogatio-border);
434
+ }
435
+ .rogatio-editor [data-dock-label] {
436
+ font-family: var(--rogatio-font-mono);
437
+ font-size: 0.6875rem;
438
+ font-weight: 700;
439
+ letter-spacing: 0.08em;
440
+ text-transform: uppercase;
441
+ color: var(--rogatio-muted);
442
+ }
443
+ .rogatio-editor [data-dock-actions] {
444
+ display: flex;
445
+ flex-wrap: wrap;
446
+ align-items: center;
447
+ justify-content: flex-end;
448
+ gap: 0.5rem 0.75rem;
449
+ min-width: 0;
450
+ }
451
+ .rogatio-editor [data-dock-actions] [data-action-cluster=tools] {
452
+ margin-right: auto;
391
453
  }
392
454
  .rogatio-editor [data-group-heading] h2,
393
455
  .rogatio-editor [data-section-heading] h2,
@@ -478,6 +540,7 @@
478
540
  flex-wrap: wrap;
479
541
  gap: 0.4rem;
480
542
  justify-content: flex-end;
543
+ margin-left: auto;
481
544
  }
482
545
  .rogatio-editor [data-rule-actions] button {
483
546
  font-size: 0.8125rem;
@@ -605,6 +668,22 @@
605
668
  .rogatio-editor [data-section-heading] {
606
669
  align-items: flex-start;
607
670
  }
671
+ .rogatio-editor [data-group-actions] {
672
+ margin-left: 0;
673
+ width: 100%;
674
+ }
675
+ .rogatio-editor [data-dock-row] {
676
+ grid-template-columns: 1fr;
677
+ justify-items: start;
678
+ row-gap: 0.45rem;
679
+ }
680
+ .rogatio-editor [data-dock-actions] {
681
+ justify-content: flex-start;
682
+ width: 100%;
683
+ }
684
+ .rogatio-editor [data-dock-actions] [data-action-cluster=tools] {
685
+ margin-right: 0;
686
+ }
608
687
  .rogatio-editor [data-rule-actions] {
609
688
  justify-content: flex-start;
610
689
  width: 100%;
@@ -630,7 +709,9 @@
630
709
  .rogatio-editor fieldset,
631
710
  .rogatio-editor [data-rule-card],
632
711
  .rogatio-editor [data-group-row],
633
- .rogatio-editor [data-editor-check-group] {
712
+ .rogatio-editor [data-editor-check-group],
713
+ .rogatio-editor [data-action-dock],
714
+ .rogatio-editor [data-action-cluster=danger] {
634
715
  border-color: ButtonText;
635
716
  background: Canvas;
636
717
  }
@@ -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";
@@ -4046,6 +4176,8 @@ var EditorControllerImpl = class {
4046
4176
  card.tabIndex = -1;
4047
4177
  const headingRow = this.document.createElement("div");
4048
4178
  headingRow.dataset.ruleHeading = "true";
4179
+ const identity = this.document.createElement("div");
4180
+ identity.dataset.ruleIdentity = "true";
4049
4181
  const heading = this.document.createElement("h3");
4050
4182
  const headingId = `${this.instanceId}-rule-title-${groupIndex}-${ruleIndex}`;
4051
4183
  card.setAttribute("aria-labelledby", headingId);
@@ -4077,7 +4209,7 @@ var EditorControllerImpl = class {
4077
4209
  )
4078
4210
  );
4079
4211
  this.renderNameHeading({
4080
- row: headingRow,
4212
+ row: identity,
4081
4213
  heading,
4082
4214
  headingId,
4083
4215
  kind: "rule",
@@ -4086,8 +4218,9 @@ var EditorControllerImpl = class {
4086
4218
  namePath: `${rulePath}/name`,
4087
4219
  name: rule.name,
4088
4220
  fallback: "Unnamed rule",
4089
- commands: [actions]
4221
+ commands: []
4090
4222
  });
4223
+ headingRow.append(identity, actions);
4091
4224
  card.append(headingRow);
4092
4225
  this.renderSource(card, rule, rulePath, groupId, ruleId);
4093
4226
  this.renderResourceTypes(card, rule, rulePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogatio/cli",
3
- "version": "6.5.0",
3
+ "version": "6.6.1",
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.",