@qoretechnologies/reqraft 0.10.47-pr.108.gf8e602d → 0.10.47

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.
@@ -964,9 +964,7 @@ export const CompactRowCancelEdit: Story = {
964
964
  const row = canvasElement.querySelector<HTMLElement>('[data-field="cookie_name"]');
965
965
  expect(row).toBeTruthy();
966
966
  fireEvent.click(row!);
967
- await waitFor(() =>
968
- expect(canvasElement.querySelector('.readfirst-row-editing')).toBeTruthy()
969
- );
967
+ await waitFor(() => expect(canvasElement.querySelector('.readfirst-row-editing')).toBeTruthy());
970
968
 
971
969
  // An untouched field offers no Cancel — it would do exactly what Done does.
972
970
  expect(canvasElement.querySelector('.options-readfirst-cancel')).toBeNull();
@@ -1051,9 +1049,7 @@ export const CompactRowAbsorbsLanguage: Story = {
1051
1049
 
1052
1050
  // Opening the host renders the language control inside its container.
1053
1051
  fireEvent.click(sourceRow as HTMLElement);
1054
- await waitFor(() =>
1055
- expect(canvasElement.querySelector('.readfirst-row-editing')).toBeTruthy()
1056
- );
1052
+ await waitFor(() => expect(canvasElement.querySelector('.readfirst-row-editing')).toBeTruthy());
1057
1053
  await waitFor(() =>
1058
1054
  expect(canvasElement.querySelector('.options-readfirst-absorbed')).toBeTruthy()
1059
1055
  );
@@ -1078,9 +1074,7 @@ export const CompactRowCancelEditAffordance: Story = {
1078
1074
  const row = canvasElement.querySelector<HTMLElement>('[data-field="cookie_name"]');
1079
1075
  expect(row).toBeTruthy();
1080
1076
  fireEvent.click(row!);
1081
- await waitFor(() =>
1082
- expect(canvasElement.querySelector('.readfirst-row-editing')).toBeTruthy()
1083
- );
1077
+ await waitFor(() => expect(canvasElement.querySelector('.readfirst-row-editing')).toBeTruthy());
1084
1078
 
1085
1079
  const input = canvasElement.querySelector<HTMLInputElement>(
1086
1080
  '[data-field="cookie_name"] input, [data-field="cookie_name"] textarea'
@@ -1169,7 +1163,7 @@ export const CompactRowCodeEditorMessage: Story = {
1169
1163
  docs: {
1170
1164
  description: {
1171
1165
  story:
1172
- "A schema `messages` entry on a code-editor field. Every other field surfaces its messages on the collapsed row; a code field draws a preview in the same cell, and the message has to survive beside it — a diagnostic the reader only finds by opening the field is not reported. Qorus puts source-validation results here, so an invalid service is called out on the row rather than at save time.",
1166
+ 'A schema `messages` entry on a code-editor field. Every other field surfaces its messages on the collapsed row; a code field draws a preview in the same cell, and the message has to survive beside it — a diagnostic the reader only finds by opening the field is not reported. Qorus puts source-validation results here, so an invalid service is called out on the row rather than at save time.',
1173
1167
  },
1174
1168
  },
1175
1169
  },
@@ -1268,7 +1262,7 @@ export const CompactRowMessageWhileEditing: Story = {
1268
1262
  docs: {
1269
1263
  description: {
1270
1264
  story:
1271
- "The same message, with the row OPEN. A schema message is guidance about the value, so the moment it matters most is while the value is being edited — and a validation diagnostic is useless anywhere else: it names a line the author can only fix with the editor in front of them. Qorus opens the Source Code row on arrival, so a message that only survives on the collapsed row was never seen at all.",
1265
+ 'The same message, with the row OPEN. A schema message is guidance about the value, so the moment it matters most is while the value is being edited — and a validation diagnostic is useless anywhere else: it names a line the author can only fix with the editor in front of them. Qorus opens the Source Code row on arrival, so a message that only survives on the collapsed row was never seen at all.',
1272
1266
  },
1273
1267
  },
1274
1268
  },
@@ -1474,7 +1468,7 @@ export const NestedOptionInheritsRenderPropFromAncestorCompact: Story = {
1474
1468
  docs: {
1475
1469
  description: {
1476
1470
  story:
1477
- "Renders the NestedOptionInheritsRenderPropFromAncestor schema with compact=true — the compact renderer previews the list-of-hash rows through their arg_schema, naming each method, rather than printing [object Object].",
1471
+ 'Renders the NestedOptionInheritsRenderPropFromAncestor schema with compact=true — the compact renderer previews the list-of-hash rows through their arg_schema, naming each method, rather than printing [object Object].',
1478
1472
  },
1479
1473
  },
1480
1474
  },
@@ -1774,7 +1768,7 @@ export const CompactWithholdsFieldsWithUnmetDependencies: Story = {
1774
1768
  docs: {
1775
1769
  description: {
1776
1770
  story:
1777
- "A field whose `depends_on` is not fulfilled is not offered as an addable one. The scheme here is Permissive, so the two cookie-only fields are absent from the Optional box entirely — only the field that depends on nothing is offered. Setting the scheme to Cookie brings them back (and flashes them). Before this, they were listed, and clicking one opened a row that said it was disabled: an affordance leading nowhere.",
1771
+ 'A field whose `depends_on` is not fulfilled is not offered as an addable one. The scheme here is Permissive, so the two cookie-only fields are absent from the Optional box entirely — only the field that depends on nothing is offered. Setting the scheme to Cookie brings them back (and flashes them). Before this, they were listed, and clicking one opened a row that said it was disabled: an affordance leading nowhere.',
1778
1772
  },
1779
1773
  },
1780
1774
  },
@@ -1821,10 +1815,9 @@ export const CompactWithholdsFieldsWithUnmetDependencies: Story = {
1821
1815
  // The independent field IS offered — without this the two absences below
1822
1816
  // would also be explained by an Optional box that never opened.
1823
1817
  await _testsWaitForText('Note');
1824
- await waitFor(
1825
- () => expect(document.querySelector('[data-field="note"]')).toBeTruthy(),
1826
- { timeout: 10000 }
1827
- );
1818
+ await waitFor(() => expect(document.querySelector('[data-field="note"]')).toBeTruthy(), {
1819
+ timeout: 10000,
1820
+ });
1828
1821
 
1829
1822
  await waitFor(
1830
1823
  () => {
@@ -2457,7 +2450,7 @@ export const CompactReadOnly: Story = {
2457
2450
  docs: {
2458
2451
  description: {
2459
2452
  story:
2460
- 'Renders the Compact fixture with readOnly enabled — the Draft/Ready progress badge is hidden and rows open in view (non-editable) mode.',
2453
+ 'Renders the Compact fixture with readOnly enabled — no completion meter, no Needs attention / Set / Optional boxes and no required asterisks; every set field is one flat list of inert rows: nothing is a button, a click opens nothing, and a value that does not fit its line wraps instead of being cut.',
2461
2454
  },
2462
2455
  },
2463
2456
  chromatic: { disable: true },
@@ -2468,14 +2461,35 @@ export const CompactReadOnly: Story = {
2468
2461
  },
2469
2462
  play: async () => {
2470
2463
  await _testsWaitForText('order-fulfilment');
2471
- // Read-only hides the Draft/Ready badge (the meter itself stays)…
2464
+ // Nothing that reports progress: no meter, no Draft/Ready, no boxes.
2465
+ expect(document.querySelector('.options-readfirst-completion')).toBeNull();
2466
+ expect(document.querySelector('.options-readfirst-group')).toBeNull();
2472
2467
  await _testsWaitForTextToNotExist('Draft');
2473
- // …and rows open in view mode: the card's done (✓/close) button collapses
2474
- // back. The button is icon-only now, so assert it by class, not text.
2468
+ await _testsWaitForTextToNotExist('Needs attention');
2469
+ await _testsWaitForTextToNotExist('Optional');
2470
+ // A required field nobody set is listed, unset, with no amber dot.
2471
+ await _testsWaitForText('Description');
2472
+ expect(
2473
+ document.querySelector(
2474
+ '.readfirst-row[data-field="description"] .options-readfirst-statusdot-slot > *'
2475
+ )
2476
+ ).toBeNull();
2477
+ // Rows are not controls: no button role, and a click opens nothing — not
2478
+ // an editor, not a view.
2479
+ expect(document.querySelector('.readfirst-row[role="button"]')).toBeNull();
2475
2480
  await _testsClickText('order-fulfilment');
2476
- await waitFor(() => expect(document.querySelector('.options-readfirst-done')).toBeTruthy());
2477
- await _testsClickButton({ selector: '.options-readfirst-done' });
2478
- await waitFor(() => expect(document.querySelector('.options-readfirst-done')).toBeNull());
2481
+ await _testsClickText('Python');
2482
+ await sleep(400);
2483
+ expect(
2484
+ document.querySelector(
2485
+ '.options-readfirst-inline, .options-readfirst-card, .options-readfirst-done'
2486
+ )
2487
+ ).toBeNull();
2488
+ expect(
2489
+ document.querySelector(
2490
+ '.options-readfirst-read input, .options-readfirst-read textarea, .options-readfirst-read select, .options-readfirst-read [contenteditable]'
2491
+ )
2492
+ ).toBeNull();
2479
2493
  },
2480
2494
  };
2481
2495
 
@@ -2658,18 +2672,18 @@ export const CompactBasic: Story = {
2658
2672
  },
2659
2673
  };
2660
2674
 
2661
- // Read-only richtext + template picker. Opening a field in a read-only form
2662
- // must not yield an editable surface: a richtext value renders as a NON-editable
2663
- // rich-text view (formatted content, contenteditable=false, no toolbar), and a
2664
- // field whose value is a template ($local:…) as a read-only template-picker chip
2665
- // ($-token + resolved name). Regression cover for the review note "this should
2666
- // show as a readonly richtext or a readonly template picker".
2675
+ // Read-only richtext + template. A read-only form mounts no editing surface at
2676
+ // all: a richtext value reads as its text with its template chips (an earlier
2677
+ // fix had left a Slate instance mounted with contenteditable="false", which is
2678
+ // still an editor wearing a lock), and a field whose value is a template
2679
+ // ($local:…) reads as the resolved-name chip. Regression cover for the review
2680
+ // note "this should show as a readonly richtext or a readonly template picker".
2667
2681
  export const CompactReadOnlyRichText: Story = {
2668
2682
  parameters: {
2669
2683
  docs: {
2670
2684
  description: {
2671
2685
  story:
2672
- 'Renders the CompactBasic fixture with readOnly enabled — opening the Rich Text row shows a non-editable Slate surface, and the Template row renders as a read-only template-picker chip showing the resolved template name (never the raw $local reference).',
2686
+ 'Renders the CompactBasic fixture with readOnly enabled — the Rich Text row reads as its text with its template chip and mounts no editor, the Template row reads as a chip showing the resolved template name (never the raw $local reference), and clicking either opens nothing.',
2673
2687
  },
2674
2688
  },
2675
2689
  chromatic: { disable: true },
@@ -2677,45 +2691,243 @@ export const CompactReadOnlyRichText: Story = {
2677
2691
  args: {
2678
2692
  ...CompactBasic.args,
2679
2693
  readOnly: true,
2680
- expandMode: 'multi' as const,
2681
2694
  },
2682
2695
  play: async () => {
2683
2696
  await _testsWaitForText('Rich Text option');
2684
-
2685
- // Read-only rows open in view mode (not edit mode). The richtext field's
2686
- // Slate surface must be non-editable — the bug was it stayed
2687
- // contenteditable="true", so a read-only form was fully editable.
2697
+ // Editor verdicts stay in the editor: the fixture's invalid value and its
2698
+ // dependency-locked field print no "fix this" hint in a read view.
2699
+ await _testsWaitForTextToNotExist('Text value is empty');
2700
+ await _testsWaitForTextToNotExist('dependencies are not fulfilled');
2701
+
2702
+ const row = (name: string) => document.querySelector(`.readfirst-row[data-field="${name}"]`);
2703
+ // Richtext: the text and its chip, no Slate.
2704
+ expect(row('richTextOption')?.textContent).toContain('This is a rich text option');
2705
+ expect(row('richTextOption')?.querySelector('.reqore-tag')?.textContent).toContain(
2706
+ 'Richtext Template'
2707
+ );
2708
+ // Template: the resolved-name chip. The raw value is tooltip-only
2709
+ // (portalled, not in the tag), so the visible label is the resolved name.
2710
+ const tag = row('templateOption')?.querySelector('.reqore-tag');
2711
+ expect(tag?.textContent).toContain('Test (local)');
2712
+ expect(tag?.textContent).not.toContain('$local:test');
2713
+
2714
+ // Clicking either opens nothing.
2688
2715
  await _testsClickText('Rich Text option');
2689
- await waitFor(
2690
- () => {
2691
- const editable = document.querySelector(
2692
- '.options-readfirst-card[data-field="richTextOption"] [contenteditable]'
2693
- );
2694
- expect(editable).toBeTruthy();
2695
- expect(editable?.getAttribute('contenteditable')).toBe('false');
2716
+ await _testsClickText('Template option');
2717
+ await sleep(400);
2718
+ expect(
2719
+ document.querySelector(
2720
+ '.options-readfirst-card, .options-readfirst-inline, .options-readfirst-done'
2721
+ )
2722
+ ).toBeNull();
2723
+ expect(
2724
+ document.querySelector(
2725
+ '.options-readfirst-read [contenteditable], .options-readfirst-read input, .options-readfirst-read textarea'
2726
+ )
2727
+ ).toBeNull();
2728
+ },
2729
+ };
2730
+
2731
+ // Read mode as a fact sheet. Every kind of value the engine can hold, set,
2732
+ // plus one optional field nobody set (`notes`) and one required field nobody
2733
+ // set (`owner`): the first must not appear at all, the second appears unset
2734
+ // with no amber. Every value is drawn in full in the row itself; nothing on
2735
+ // the page is a control.
2736
+ const ReadModeSchema: Record<string, TCompactField> = {
2737
+ id: {
2738
+ type: 'string',
2739
+ ui_type: 'string',
2740
+ display_name: 'ID',
2741
+ short_desc: 'Assigned by Qorus when the schema is created',
2742
+ desc: 'The identifier is allocated by the server and is what every reference to this schema uses. It never changes, even when the schema is renamed.',
2743
+ required: true,
2744
+ preselected: true,
2745
+ readonly: true,
2746
+ group: 'identity',
2747
+ },
2748
+ audience: {
2749
+ type: 'string',
2750
+ ui_type: 'string',
2751
+ display_name: 'Who can call this',
2752
+ short_desc: 'Which callers the gateway admits',
2753
+ required: true,
2754
+ preselected: true,
2755
+ group: 'identity',
2756
+ allowed_values: [
2757
+ {
2758
+ value: { type: 'string', value: 'anyone' },
2759
+ display_name: 'Anyone',
2760
+ short_desc: 'No credentials are checked.',
2696
2761
  },
2697
- { timeout: 10000 }
2698
- );
2762
+ {
2763
+ value: { type: 'string', value: 'authenticated' },
2764
+ display_name: 'Authenticated users',
2765
+ desc: 'Callers must present a valid token; the gateway rejects anonymous requests before they reach the handler.',
2766
+ },
2767
+ ],
2768
+ },
2769
+ summary: {
2770
+ type: 'string',
2771
+ ui_type: 'long-string',
2772
+ display_name: 'Summary',
2773
+ short_desc: 'What this API is for',
2774
+ preselected: true,
2775
+ group: 'identity',
2776
+ },
2777
+ owner: {
2778
+ type: 'string',
2779
+ ui_type: 'string',
2780
+ display_name: 'Owner',
2781
+ short_desc: 'The team that answers for this API',
2782
+ required: true,
2783
+ preselected: true,
2784
+ group: 'identity',
2785
+ },
2786
+ handler: {
2787
+ type: 'string',
2788
+ ui_type: 'code-editor',
2789
+ display_name: 'Handler',
2790
+ short_desc: 'Runs on every call',
2791
+ preselected: true,
2792
+ group: 'behaviour',
2793
+ },
2794
+ retry: {
2795
+ type: 'hash',
2796
+ ui_type: 'hash',
2797
+ display_name: 'Retry policy',
2798
+ preselected: true,
2799
+ group: 'behaviour',
2800
+ arg_schema: {
2801
+ attempts: { type: 'number', ui_type: 'number', display_name: 'Attempts' },
2802
+ backoff: {
2803
+ type: 'string',
2804
+ ui_type: 'string',
2805
+ display_name: 'Backoff',
2806
+ allowed_values: [
2807
+ { value: { type: 'string', value: 'exponential' }, display_name: 'Exponential' },
2808
+ { value: { type: 'string', value: 'fixed' }, display_name: 'Fixed' },
2809
+ ],
2810
+ },
2811
+ },
2812
+ },
2813
+ tags: {
2814
+ type: 'list',
2815
+ ui_type: 'list',
2816
+ display_name: 'Tags',
2817
+ preselected: true,
2818
+ group: 'behaviour',
2819
+ },
2820
+ enabled: {
2821
+ type: 'bool',
2822
+ ui_type: 'bool',
2823
+ display_name: 'Enabled',
2824
+ preselected: true,
2825
+ group: 'behaviour',
2826
+ },
2827
+ notes: {
2828
+ type: 'string',
2829
+ ui_type: 'string',
2830
+ display_name: 'Notes',
2831
+ short_desc: 'Free-form notes',
2832
+ group: 'behaviour',
2833
+ },
2834
+ };
2699
2835
 
2700
- // A template-valued field renders the read-only template-picker chip — a
2701
- // $-token tag with the resolved name — never an editable input.
2702
- await _testsClickText('Template option');
2703
- await waitFor(
2704
- () => {
2705
- const card = document.querySelector('.options-readfirst-card[data-field="templateOption"]');
2706
- expect(card).toBeTruthy();
2707
- const tag = card?.querySelector('.reqore-tag');
2708
- expect(tag).toBeTruthy();
2709
- // The chip resolves the catalogue display name ('$local:test' →
2710
- // 'Test (local)') — the whole point of the read-only picker. The raw
2711
- // value is tooltip-only (portalled, not in the tag), so the visible
2712
- // label must be the resolved name, never the raw reference.
2713
- expect(tag?.textContent).toContain('Test (local)');
2714
- expect(tag?.textContent).not.toContain('$local:test');
2715
- expect(card?.querySelector('input, textarea, [contenteditable="true"]')).toBeFalsy();
2836
+ const ReadModeValue: IOptions = {
2837
+ id: { type: 'string', value: 'api-schema-7f3c' },
2838
+ audience: { type: 'string', value: 'authenticated' },
2839
+ summary: {
2840
+ type: 'string',
2841
+ value:
2842
+ 'Customer master data for the storefront: the record of who a customer is, where they are billed and where they are shipped, kept once and read by every channel.\n\nEvery operation is idempotent; clients retry freely. A write carries the revision it was based on, and a stale revision is refused rather than merged, so two channels editing the same customer cannot silently overwrite each other.\n\nResponses are cached at the edge for sixty seconds, so a write is visible to readers within a minute — the "eventually" in eventually consistent is short here, but it is not zero.',
2843
+ },
2844
+ handler: {
2845
+ type: 'string',
2846
+ value:
2847
+ '# Reject calls without a tenant header before they reach the service.\nif (!ctx.headers["x-tenant"]) {\n return { status: 400, body: { error: "tenant required" } };\n}\n\nconst customer = await store.get(ctx.params.id);\nif (!customer) {\n return { status: 404 };\n}\n\nreturn { status: 200, body: customer };',
2848
+ },
2849
+ retry: { type: 'hash', value: { attempts: 3, backoff: 'exponential' } },
2850
+ tags: { type: 'list', value: ['customers', 'public'] },
2851
+ enabled: { type: 'bool', value: true },
2852
+ };
2853
+
2854
+ export const CompactReadOnlyValues: Story = {
2855
+ parameters: {
2856
+ docs: {
2857
+ description: {
2858
+ story:
2859
+ 'Read-only as a fact sheet, not a disabled editor: no completion meter, no Needs attention / Set / Optional boxes, no required asterisks; an optional field nobody set is not listed, a required one nobody set reads as unset without the amber; every value is drawn in full in its row — long text wrapped under a Show more cap, the whole code block, every field of the hash, the chosen option with its description — and no row is a control: nothing is a button, and a click opens nothing.',
2716
2860
  },
2717
- { timeout: 10000 }
2861
+ },
2862
+ chromatic: { disable: true },
2863
+ },
2864
+ args: {
2865
+ compact: true,
2866
+ minColumnWidth: '300px',
2867
+ options: ReadModeSchema,
2868
+ value: ReadModeValue,
2869
+ groups: {
2870
+ identity: { icon: 'IdCardLine', subtitle: 'What this is and who may use it', sort: 0 },
2871
+ behaviour: { icon: 'FlashlightLine', sort: 1 },
2872
+ },
2873
+ readOnly: true,
2874
+ },
2875
+ play: async () => {
2876
+ await _testsWaitForText('api-schema-7f3c');
2877
+ // No progress, no boxes, no offers.
2878
+ expect(document.querySelector('.options-readfirst-completion')).toBeNull();
2879
+ expect(document.querySelector('.options-readfirst-group')).toBeNull();
2880
+ await _testsWaitForTextToNotExist('Needs attention');
2881
+ await _testsWaitForTextToNotExist('Optional');
2882
+ // An optional field nobody set is not listed at all…
2883
+ await _testsWaitForTextToNotExist('Notes');
2884
+ // …a required one nobody set is, as unset, with no amber dot.
2885
+ await _testsWaitForText('Owner');
2886
+ expect(
2887
+ document.querySelector(
2888
+ '.readfirst-row[data-field="owner"] .options-readfirst-statusdot-slot > *'
2889
+ )
2890
+ ).toBeNull();
2891
+
2892
+ const row = (name: string) =>
2893
+ document.querySelector(`.readfirst-row[data-field="${name}"]`) as HTMLElement;
2894
+ // A choice reads as the option and what it means — not a select.
2895
+ expect(row('audience').textContent).toContain('Authenticated users');
2896
+ expect(row('audience').textContent).toContain('Callers must present a valid token');
2897
+ // A server-set id reads as the value — no lock, no disabled input.
2898
+ expect(row('id').textContent).toContain('api-schema-7f3c');
2899
+ expect(row('id').querySelector('.options-readfirst-locked')).toBeNull();
2900
+ // Long text is drawn in full under the row, capped by Show more.
2901
+ expect(row('summary').querySelector('.options-readfirst-text')?.textContent).toContain(
2902
+ 'but it is not zero.'
2718
2903
  );
2904
+ await waitFor(() =>
2905
+ expect(row('summary').querySelector('.options-readfirst-viewmore')).toBeTruthy()
2906
+ );
2907
+ // Code is the whole block.
2908
+ expect(row('handler').querySelector('.options-readfirst-code')?.textContent).toContain(
2909
+ 'return { status: 200, body: customer };'
2910
+ );
2911
+ // A hash is every field, by name.
2912
+ expect(row('retry').textContent).toMatch(/Attempts/);
2913
+ expect(row('retry').textContent).toMatch(/Exponential|exponential/);
2914
+
2915
+ // Nothing is a control: no row is a button, a click opens nothing, and
2916
+ // there is no editor anywhere in the list.
2917
+ expect(document.querySelector('.readfirst-row[role="button"]')).toBeNull();
2918
+ await _testsClickText('Who can call this');
2919
+ await _testsClickText('Handler');
2920
+ await sleep(400);
2921
+ expect(
2922
+ document.querySelector(
2923
+ '.options-readfirst-inline, .options-readfirst-card, .options-readfirst-done'
2924
+ )
2925
+ ).toBeNull();
2926
+ expect(
2927
+ document.querySelector(
2928
+ '.options-readfirst-read input, .options-readfirst-read textarea, .options-readfirst-read select, .options-readfirst-read [contenteditable]'
2929
+ )
2930
+ ).toBeNull();
2719
2931
  },
2720
2932
  };
2721
2933
 
@@ -6297,11 +6509,21 @@ const RichtextMultilineTemplateValue: IOptions = {
6297
6509
  type: 'paragraph',
6298
6510
  children: [
6299
6511
  { text: 'Alert: ' },
6300
- { type: 'tag', value: '$fsminput:alert_code', label: 'alert_code', children: [{ text: '' }] },
6512
+ {
6513
+ type: 'tag',
6514
+ value: '$fsminput:alert_code',
6515
+ label: 'alert_code',
6516
+ children: [{ text: '' }],
6517
+ },
6301
6518
  { text: '\nSeverity: ' },
6302
6519
  { type: 'tag', value: '$fsminput:severity', label: 'severity', children: [{ text: '' }] },
6303
6520
  { text: '\nRule: ' },
6304
- { type: 'tag', value: '$fsminput:rule_name', label: 'rule_name', children: [{ text: '' }] },
6521
+ {
6522
+ type: 'tag',
6523
+ value: '$fsminput:rule_name',
6524
+ label: 'rule_name',
6525
+ children: [{ text: '' }],
6526
+ },
6305
6527
  ],
6306
6528
  },
6307
6529
  ],
@@ -6329,7 +6551,8 @@ export const CompactReadFirstRichtextMultilineTemplate: Story = {
6329
6551
  const proseSpans = Array.from(canvasElement.querySelectorAll('span')).filter(
6330
6552
  // the collapsed newline leaves the segment with a leading space
6331
6553
  (element) =>
6332
- element.children.length === 0 && /^\s*(Alert|Severity|Rule):/.test(element.textContent || '')
6554
+ element.children.length === 0 &&
6555
+ /^\s*(Alert|Severity|Rule):/.test(element.textContent || '')
6333
6556
  ) as HTMLElement[];
6334
6557
  await expect(proseSpans.length).toBe(3);
6335
6558
 
@@ -6701,9 +6924,7 @@ export const CompactListOfHashReadsInSchemaWordsMobile: Story = {
6701
6924
 
6702
6925
  // The narrow branch is actually engaged — otherwise this is the desktop
6703
6926
  // story with a border round it, and it would pass while proving nothing.
6704
- await waitFor(() =>
6705
- expect(canvasElement.querySelector('.readfirst-narrow')).toBeTruthy()
6706
- );
6927
+ await waitFor(() => expect(canvasElement.querySelector('.readfirst-narrow')).toBeTruthy());
6707
6928
 
6708
6929
  const preview = await waitFor(() => {
6709
6930
  const element = canvasElement.querySelector('.schema-data-view');
@@ -6908,7 +7129,7 @@ export const CompactChosenCollapsedBoxes: Story = {
6908
7129
  docs: {
6909
7130
  description: {
6910
7131
  story:
6911
- 'Renders a compact form with `compactCollapsedGroups={[\'set\', \'optional\']}` — the Set and Optional boxes start collapsed while Needs attention stays open, and typing a search query forces every box open (a collapsed panel unmounts its content, so a match inside one would be unreachable); clearing the query collapses them again.',
7132
+ "Renders a compact form with `compactCollapsedGroups={['set', 'optional']}` — the Set and Optional boxes start collapsed while Needs attention stays open, and typing a search query forces every box open (a collapsed panel unmounts its content, so a match inside one would be unreachable); clearing the query collapses them again.",
6912
7133
  },
6913
7134
  },
6914
7135
  },