@qoretechnologies/reqraft 0.10.10 → 0.10.11

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.
Files changed (37) hide show
  1. package/package.json +1 -1
  2. package/src/components/dpqlEditor/DpqlEditor.stories.tsx +74 -2
  3. package/src/components/form/engine/FormEngine.stories.tsx +654 -32
  4. package/src/components/form/engine/FormEngineRemote.stories.tsx +48 -0
  5. package/src/components/form/engine/_structuredData/StructuredDataView.stories.tsx +8 -0
  6. package/src/components/form/engine/variants/FormEngineVariants.stories.tsx +40 -0
  7. package/src/components/form/expressions/ExpressionField.stories.tsx +74 -2
  8. package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +187 -0
  9. package/src/components/form/fields/Field.stories.tsx +40 -0
  10. package/src/components/form/fields/array/ArrayAutoField.stories.tsx +64 -0
  11. package/src/components/form/fields/auto/AutoFormField.stories.tsx +136 -0
  12. package/src/components/form/fields/binary/Binary.stories.tsx +32 -0
  13. package/src/components/form/fields/boolean/Boolean.stories.tsx +24 -0
  14. package/src/components/form/fields/byte-size/ByteSize.stories.tsx +24 -0
  15. package/src/components/form/fields/color/Color.stories.tsx +30 -0
  16. package/src/components/form/fields/cron/Cron.stories.tsx +8 -0
  17. package/src/components/form/fields/date/Date.stories.tsx +22 -0
  18. package/src/components/form/fields/file/File.stories.tsx +48 -0
  19. package/src/components/form/fields/long-string/LongString.stories.tsx +24 -0
  20. package/src/components/form/fields/markdown/Markdown.stories.tsx +8 -0
  21. package/src/components/form/fields/number/Number.stories.tsx +31 -0
  22. package/src/components/form/fields/object/Object.stories.tsx +88 -0
  23. package/src/components/form/fields/radio-group/RadioGroup.stories.tsx +24 -0
  24. package/src/components/form/fields/rich-text/RichText.stories.tsx +23 -0
  25. package/src/components/form/fields/schema-definition/SchemaDefinitionField.stories.tsx +72 -0
  26. package/src/components/form/fields/select/Select.stories.tsx +104 -0
  27. package/src/components/form/fields/string/String.stories.tsx +16 -0
  28. package/src/components/form/fields/template/TemplateField.stories.tsx +160 -0
  29. package/src/components/form/fields/url/Url.stories.tsx +24 -0
  30. package/src/components/log/Log.stories.tsx +96 -0
  31. package/src/components/menu/Menu.stories.tsx +54 -0
  32. package/src/components/qonsoleSmartInput/QonsoleSmartInput.stories.tsx +14 -0
  33. package/src/components/smartEditor/SmartEditor.stories.tsx +32 -0
  34. package/src/hooks/useFetch/useFetch.stories.tsx +30 -0
  35. package/src/hooks/useStorage/useStorage.stories.tsx +30 -0
  36. package/src/hooks/useWebSocket/useWebsocket.stories.tsx +127 -1
  37. package/src/stores/currentUser/currentUser.stories.tsx +17 -0
@@ -35,6 +35,14 @@ export const Items: Story = {
35
35
  { display_name: 'Item 2', value: 'item2' },
36
36
  ],
37
37
  },
38
+ parameters: {
39
+ docs: {
40
+ description: {
41
+ story:
42
+ 'Renders the Select field with two simple items and no value. Clicking the trigger opens the popover with the item list.',
43
+ },
44
+ },
45
+ },
38
46
  async play({ canvasElement }) {
39
47
  const canvas = within(canvasElement);
40
48
  await fireEvent.click(canvas.getByRole('button'));
@@ -45,6 +53,14 @@ export const Items: Story = {
45
53
  };
46
54
 
47
55
  export const ItemsWithDescription: Story = {
56
+ parameters: {
57
+ docs: {
58
+ description: {
59
+ story:
60
+ 'Renders the Select field with twenty items, each carrying a description, icon or image. Opening the picker mounts a modal collection with all twenty entries.',
61
+ },
62
+ },
63
+ },
48
64
  args: {
49
65
  items: [
50
66
  { display_name: 'Item 1', desc: 'This is item 1', value: 'item1', icon: 'MoneyEuroCircleFill', groups: ['Miscellaneous'] },
@@ -81,6 +97,14 @@ export const ItemsWithDescription: Story = {
81
97
  };
82
98
 
83
99
  export const ItemsWithDescriptionAndMessages: Story = {
100
+ parameters: {
101
+ docs: {
102
+ description: {
103
+ story:
104
+ 'Renders the Select field with two items that carry inline messages of different intents. The picker modal shows the messages beneath each item.',
105
+ },
106
+ },
107
+ },
84
108
  args: {
85
109
  items: [
86
110
  {
@@ -121,6 +145,14 @@ export const DisabledItemsWithIntent: Story = {
121
145
  { display_name: 'Disabled Item with Intent', intent: 'danger', disabled: true, value: 'item5' },
122
146
  ],
123
147
  },
148
+ parameters: {
149
+ docs: {
150
+ description: {
151
+ story:
152
+ 'Renders the Select field with a mix of enabled, disabled and intent-tagged items — the disabled entries are non-interactive while success/danger items carry their intent styling.',
153
+ },
154
+ },
155
+ },
124
156
  async play({ canvasElement }) {
125
157
  const canvas = within(canvasElement);
126
158
  await fireEvent.click(canvas.getByRole('button'));
@@ -138,6 +170,14 @@ export const DisabledItemsWithIntentAndDescriptions: Story = {
138
170
  { display_name: 'Disabled Item with Intent', intent: 'danger', disabled: true, short_desc: 'This is item 5', value: 'item5' },
139
171
  ],
140
172
  },
173
+ parameters: {
174
+ docs: {
175
+ description: {
176
+ story:
177
+ 'Renders the Select field with five items mixing intents, descriptions and disabled states — the picker modal shows all five so their combined presentation can be reviewed.',
178
+ },
179
+ },
180
+ },
141
181
  async play({ canvasElement }) {
142
182
  const canvas = within(canvasElement);
143
183
  await fireEvent.click(canvas.getByRole('button'));
@@ -157,6 +197,14 @@ export const WithValue: Story = {
157
197
  { display_name: 'Item 2', value: 'item2' },
158
198
  ],
159
199
  },
200
+ parameters: {
201
+ docs: {
202
+ description: {
203
+ story:
204
+ 'Renders the Select field with two items and item2 pre-selected — the trigger shows the selected label and clicking it opens the popover.',
205
+ },
206
+ },
207
+ },
160
208
  async play({ canvasElement }) {
161
209
  const canvas = within(canvasElement);
162
210
  await expect(canvas.getByRole('button')).toBeInTheDocument();
@@ -173,6 +221,14 @@ export const WithValueAndErrors: Story = {
173
221
  { display_name: 'Item 2', desc: 'This is item 1', value: 'item2', image: 'https://avatars.githubusercontent.com/u/8861481?v=4' },
174
222
  ],
175
223
  },
224
+ parameters: {
225
+ docs: {
226
+ description: {
227
+ story:
228
+ 'Renders the Select field with a danger-intent item in the list, but the selected value points at the healthy item — the trigger stays clean while the picker highlights the danger item.',
229
+ },
230
+ },
231
+ },
176
232
  };
177
233
 
178
234
  export const WithValueAndErrorsSelected: Story = {
@@ -183,6 +239,14 @@ export const WithValueAndErrorsSelected: Story = {
183
239
  { display_name: 'Item 2', desc: 'This is item 1', value: 'item2' },
184
240
  ],
185
241
  },
242
+ parameters: {
243
+ docs: {
244
+ description: {
245
+ story:
246
+ 'Renders the Select field with the danger-intent item pre-selected — the trigger carries the danger styling so the operator can see the selected item has an error.',
247
+ },
248
+ },
249
+ },
186
250
  };
187
251
 
188
252
  export const WithValueAndWarningsSelected: Story = {
@@ -193,6 +257,14 @@ export const WithValueAndWarningsSelected: Story = {
193
257
  { display_name: 'Item 2', desc: 'This is item 1', value: 'item2' },
194
258
  ],
195
259
  },
260
+ parameters: {
261
+ docs: {
262
+ description: {
263
+ story:
264
+ 'Renders the Select field with a pre-selected item whose metadata declares needs_auth — the trigger surfaces the warning so the operator knows the item needs configuration.',
265
+ },
266
+ },
267
+ },
196
268
  };
197
269
 
198
270
  export const AutoSelect: Story = {
@@ -200,6 +272,14 @@ export const AutoSelect: Story = {
200
272
  autoSelect: true,
201
273
  items: [{ display_name: 'Item 1', value: 'item1' }],
202
274
  },
275
+ parameters: {
276
+ docs: {
277
+ description: {
278
+ story:
279
+ 'Renders the Select field with autoSelect and a single item — the field auto-selects the only option and the trigger shows its label on mount.',
280
+ },
281
+ },
282
+ },
203
283
  async play({ canvasElement }) {
204
284
  const canvas = within(canvasElement);
205
285
  await waitFor(() => expect(canvas.getByText('Item 1')).toBeInTheDocument(), { timeout: 500 });
@@ -211,6 +291,14 @@ export const AutoSelectWithShortDescriptions: Story = {
211
291
  autoSelect: true,
212
292
  items: [{ display_name: 'Item 1', short_desc: 'Short item 1 description', value: 'item1' }],
213
293
  },
294
+ parameters: {
295
+ docs: {
296
+ description: {
297
+ story:
298
+ 'Renders the Select field with autoSelect and a single item that carries a short description — the field auto-selects and the trigger shows both the label and the short description.',
299
+ },
300
+ },
301
+ },
214
302
  async play({ canvasElement }) {
215
303
  const canvas = within(canvasElement);
216
304
  await waitFor(() => expect(canvas.getByText('Item 1')).toBeInTheDocument(), { timeout: 500 });
@@ -222,6 +310,14 @@ export const AutoSelectWithDescriptions: Story = {
222
310
  autoSelect: true,
223
311
  items: [{ display_name: 'Item 1', desc: 'This is item 1', value: 'item1' }],
224
312
  },
313
+ parameters: {
314
+ docs: {
315
+ description: {
316
+ story:
317
+ 'Renders the Select field with autoSelect and a single item that carries a full description — the field auto-selects and the trigger shows the label with the description.',
318
+ },
319
+ },
320
+ },
225
321
  async play({ canvasElement }) {
226
322
  const canvas = within(canvasElement);
227
323
  await waitFor(() => expect(canvas.getByText('Item 1')).toBeInTheDocument(), { timeout: 500 });
@@ -240,6 +336,14 @@ export const ItemValuesAreObjectsAndCanBeSelected: Story = {
240
336
  },
241
337
  ],
242
338
  },
339
+ parameters: {
340
+ docs: {
341
+ description: {
342
+ story:
343
+ 'Renders the Select field with items whose values are hashes rather than primitives. The unlabelled first item shows its JSON as the trigger label; picking the second item swaps the selection to its display_name.',
344
+ },
345
+ },
346
+ },
243
347
  async play({ canvasElement }) {
244
348
  const canvas = within(canvasElement);
245
349
  await waitFor(
@@ -38,6 +38,14 @@ export const Default: Story = {
38
38
  args: {
39
39
  value: 'Qore',
40
40
  },
41
+ parameters: {
42
+ docs: {
43
+ description: {
44
+ story:
45
+ 'Renders the String field pre-populated with "Qore". Clicking clear empties the input and fires onClearClick; typing new text updates the value and fires onChange.',
46
+ },
47
+ },
48
+ },
41
49
  play: async ({ canvasElement, args }) => {
42
50
  const canvas = within(canvasElement);
43
51
  const input = canvas.getByLabelText('Name');
@@ -60,6 +68,14 @@ export const Sensitive: Story = {
60
68
  sensitive: true,
61
69
  value: 'password',
62
70
  },
71
+ parameters: {
72
+ docs: {
73
+ description: {
74
+ story:
75
+ 'Renders the String field in sensitive mode — the input renders as type="password" so the value is masked.',
76
+ },
77
+ },
78
+ },
63
79
  play: async ({ canvasElement }) => {
64
80
  const canvas = within(canvasElement);
65
81
  const input = canvas.getByLabelText('Name');
@@ -209,6 +209,14 @@ export const StringComponent: StoryObj<typeof meta> = {
209
209
  value: 'Some string',
210
210
  type: 'string',
211
211
  },
212
+ parameters: {
213
+ docs: {
214
+ description: {
215
+ story:
216
+ 'Renders TemplateField wrapping a LongString component with a plain string value — the field shows the literal string in a textarea, no template selected.',
217
+ },
218
+ },
219
+ },
212
220
  };
213
221
 
214
222
  export const BooleanComponent: StoryObj<typeof meta> = {
@@ -218,6 +226,14 @@ export const BooleanComponent: StoryObj<typeof meta> = {
218
226
  allowTemplates: true,
219
227
  componentFromType: true,
220
228
  },
229
+ parameters: {
230
+ docs: {
231
+ description: {
232
+ story:
233
+ 'Renders TemplateField for a boolean value with templates allowed — the boolean toggle is shown with the template toggle available on the side.',
234
+ },
235
+ },
236
+ },
221
237
  };
222
238
 
223
239
  export const NumberComponent: StoryObj<typeof meta> = {
@@ -227,6 +243,14 @@ export const NumberComponent: StoryObj<typeof meta> = {
227
243
  allowTemplates: true,
228
244
  componentFromType: true,
229
245
  },
246
+ parameters: {
247
+ docs: {
248
+ description: {
249
+ story:
250
+ 'Renders TemplateField for an int value of 25 with templates allowed — the numeric input is shown alongside the template toggle.',
251
+ },
252
+ },
253
+ },
230
254
  };
231
255
 
232
256
  export const AutoComponent: StoryObj<typeof meta> = {
@@ -235,6 +259,14 @@ export const AutoComponent: StoryObj<typeof meta> = {
235
259
  allowTemplates: true,
236
260
  component: auto,
237
261
  },
262
+ parameters: {
263
+ docs: {
264
+ description: {
265
+ story:
266
+ 'Renders TemplateField wrapping the AutoFormField dispatcher — the operator can pick a type from the auto picker or switch to a template value.',
267
+ },
268
+ },
269
+ },
238
270
  };
239
271
 
240
272
  export const AllowedValuesWithTemplate: StoryObj<typeof meta> = {
@@ -249,6 +281,14 @@ export const AllowedValuesWithTemplate: StoryObj<typeof meta> = {
249
281
  ],
250
282
  component: auto,
251
283
  },
284
+ parameters: {
285
+ docs: {
286
+ description: {
287
+ story:
288
+ 'Renders TemplateField restricted to a single allowed value ("Test") but with templates also allowed — the operator can pick the allowed value or switch to a template.',
289
+ },
290
+ },
291
+ },
252
292
  };
253
293
 
254
294
  export const TemplateValue: StoryObj<typeof meta> = {
@@ -257,6 +297,14 @@ export const TemplateValue: StoryObj<typeof meta> = {
257
297
  type: 'int',
258
298
  value: '$local:id',
259
299
  },
300
+ parameters: {
301
+ docs: {
302
+ description: {
303
+ story:
304
+ 'Renders TemplateField for an int wrapped over the Number component with a template value ($local:id) — the template selector replaces the number input.',
305
+ },
306
+ },
307
+ },
260
308
  };
261
309
 
262
310
  export const ElementTypeInListShowsCorrectTemplates: StoryObj<typeof meta> = {
@@ -271,6 +319,14 @@ export const ElementTypeInListShowsCorrectTemplates: StoryObj<typeof meta> = {
271
319
  { type: 'number', value: 3 },
272
320
  ],
273
321
  },
322
+ parameters: {
323
+ docs: {
324
+ description: {
325
+ story:
326
+ 'Renders TemplateField in list mode with three number items. Adding a new item and opening the templates popover shows the templates that resolve to the number element type.',
327
+ },
328
+ },
329
+ },
274
330
  play: async () => {
275
331
  await _testsClickButton({ label: 'Add new item for "Test"' });
276
332
  await _testsOpenTemplates();
@@ -280,6 +336,14 @@ export const ElementTypeInListShowsCorrectTemplates: StoryObj<typeof meta> = {
280
336
 
281
337
  export const ShowsTemplatesList: StoryObj<typeof meta> = {
282
338
  ...TemplateValue,
339
+ parameters: {
340
+ docs: {
341
+ description: {
342
+ story:
343
+ 'Renders TemplateField with the $local:id template value, then opens the templates popover — the operator sees the available templates that resolve to an int.',
344
+ },
345
+ },
346
+ },
283
347
  play: async () => {
284
348
  await _testsOpenTemplates();
285
349
  },
@@ -287,6 +351,14 @@ export const ShowsTemplatesList: StoryObj<typeof meta> = {
287
351
 
288
352
  export const ShowsTemplatesListForString: StoryObj<typeof meta> = {
289
353
  ...StringComponent,
354
+ parameters: {
355
+ docs: {
356
+ description: {
357
+ story:
358
+ 'Renders TemplateField over a LongString component with a plain string value, then opens the templates popover — the templates list is shown for a string target type.',
359
+ },
360
+ },
361
+ },
290
362
  play: async () => {
291
363
  await _testsOpenTemplates();
292
364
  },
@@ -294,6 +366,14 @@ export const ShowsTemplatesListForString: StoryObj<typeof meta> = {
294
366
 
295
367
  export const ShowsTemplatesListForBoolean: StoryObj<typeof meta> = {
296
368
  ...BooleanComponent,
369
+ parameters: {
370
+ docs: {
371
+ description: {
372
+ story:
373
+ 'Renders TemplateField for a boolean value, switches to template mode and opens the templates popover — the templates list is shown for a boolean target type.',
374
+ },
375
+ },
376
+ },
297
377
  play: async () => {
298
378
  await _testsSetTemplate();
299
379
  await _testsOpenTemplates();
@@ -302,6 +382,14 @@ export const ShowsTemplatesListForBoolean: StoryObj<typeof meta> = {
302
382
 
303
383
  export const ShowsTemplatesListForNumber: StoryObj<typeof meta> = {
304
384
  ...NumberComponent,
385
+ parameters: {
386
+ docs: {
387
+ description: {
388
+ story:
389
+ 'Renders TemplateField for an int value, then opens the templates popover — the templates list is shown for an int target type.',
390
+ },
391
+ },
392
+ },
305
393
  play: async () => {
306
394
  await _testsOpenTemplates();
307
395
  },
@@ -314,6 +402,14 @@ export const TemplateValueCanBeRemoved: StoryObj<typeof meta> = {
314
402
  allowTemplates: true,
315
403
  componentFromType: true,
316
404
  },
405
+ parameters: {
406
+ docs: {
407
+ description: {
408
+ story:
409
+ 'Renders TemplateField holding a $config:boolean template value. Clicking the template-remove action clears the template and the underlying boolean checkbox is shown instead.',
410
+ },
411
+ },
412
+ },
317
413
  play: async () => {
318
414
  await expect(document.querySelector('.template-selector')).toBeInTheDocument();
319
415
 
@@ -333,6 +429,14 @@ export const TemplateWithFunctions: StoryObj<typeof meta> = {
333
429
  fluid: false,
334
430
  expressions: storyExpressions as any,
335
431
  },
432
+ parameters: {
433
+ docs: {
434
+ description: {
435
+ story:
436
+ 'Renders TemplateField with allowFunctions enabled — the template menu now exposes a "Use Expression" entry alongside the plain templates.',
437
+ },
438
+ },
439
+ },
336
440
  play: async () => {
337
441
  await _testsOpenTemplateMenu();
338
442
  await _testsWaitForText('Use Expression');
@@ -358,6 +462,14 @@ export const TemplateWithFunctionValue: StoryObj<typeof meta> = {
358
462
  fluid: false,
359
463
  expressions: storyExpressions as any,
360
464
  },
465
+ parameters: {
466
+ docs: {
467
+ description: {
468
+ story:
469
+ 'Renders TemplateField holding a substr function value with three arguments — the expression builder shows the function name and each argument slot.',
470
+ },
471
+ },
472
+ },
361
473
  };
362
474
 
363
475
  export const TemplateWithNestedFunctionValue: StoryObj<typeof meta> = {
@@ -389,6 +501,14 @@ export const TemplateWithNestedFunctionValue: StoryObj<typeof meta> = {
389
501
  fluid: false,
390
502
  expressions: storyExpressions as any,
391
503
  },
504
+ parameters: {
505
+ docs: {
506
+ description: {
507
+ story:
508
+ 'Renders TemplateField holding a substr function whose second argument is itself a PLUS-INT expression — the expression builder shows the nested function inline within the outer call.',
509
+ },
510
+ },
511
+ },
392
512
  };
393
513
 
394
514
  export const TemplateCanBeSelected: StoryObj<typeof meta> = {
@@ -397,6 +517,14 @@ export const TemplateCanBeSelected: StoryObj<typeof meta> = {
397
517
  defaultType: 'string',
398
518
  defaultInternalType: 'string',
399
519
  },
520
+ parameters: {
521
+ docs: {
522
+ description: {
523
+ story:
524
+ 'Renders TemplateField for a string, opens the templates popover and clicks the Interface ID template — the field switches to the $local:id template value.',
525
+ },
526
+ },
527
+ },
400
528
  play: async ({ canvasElement, ...rest }) => {
401
529
  const canvas = within(canvasElement);
402
530
 
@@ -410,6 +538,14 @@ export const TemplateCanBeSelected: StoryObj<typeof meta> = {
410
538
  };
411
539
 
412
540
  export const ValueIsResetWhenChangingToCustom: StoryObj<typeof meta> = {
541
+ parameters: {
542
+ docs: {
543
+ description: {
544
+ story:
545
+ 'Renders TemplateField over a number type holding a $config:something template value. Clicking template-remove resets the value to undefined and fires onChange with the cleared value.',
546
+ },
547
+ },
548
+ },
413
549
  render: (args) => {
414
550
  const [value, setValue] = useState(args.value);
415
551
 
@@ -449,6 +585,14 @@ export const TemplatesWithMultipleLevels: StoryObj<typeof meta> = {
449
585
  type: 'string',
450
586
  templates: buildTemplates(multiLevelTemplates as any),
451
587
  },
588
+ parameters: {
589
+ docs: {
590
+ description: {
591
+ story:
592
+ 'Renders TemplateField for a string with a hierarchical template catalogue. Drilling into "Testing Hash" narrows the list to templates that resolve to a string (Testing Int Item is filtered out).',
593
+ },
594
+ },
595
+ },
452
596
  play: async () => {
453
597
  await _testsOpenTemplates();
454
598
  await _testsClickButton({ label: 'Testing Hash' });
@@ -458,6 +602,14 @@ export const TemplatesWithMultipleLevels: StoryObj<typeof meta> = {
458
602
  };
459
603
 
460
604
  export const TemplatesWithMultipleLevelsAndHashField: StoryObj<typeof meta> = {
605
+ parameters: {
606
+ docs: {
607
+ description: {
608
+ story:
609
+ 'Renders TemplateField for a hash type with a hierarchical template catalogue — switching to template mode and opening the popover exposes the nested template groups.',
610
+ },
611
+ },
612
+ },
461
613
  render: (args) => {
462
614
  const [value, setValue] = useState(args.value);
463
615
 
@@ -486,6 +638,14 @@ export const TemplatesWithMultipleLevelsAndHashField: StoryObj<typeof meta> = {
486
638
 
487
639
  export const TemplateWithItemsCanBeSelected: StoryObj<typeof meta> = {
488
640
  ...TemplatesWithMultipleLevelsAndHashField,
641
+ parameters: {
642
+ docs: {
643
+ description: {
644
+ story:
645
+ 'Renders TemplateField for a hash type with a hierarchical catalogue. Selecting an item from a nested group updates the template value to the picked entry (Testing Hash).',
646
+ },
647
+ },
648
+ },
489
649
  play: async (args) => {
490
650
  await TemplatesWithMultipleLevelsAndHashField.play(args);
491
651
  await _testsClickButton({ selector: '.reqore-menu-item-left-action' });
@@ -30,6 +30,14 @@ export default meta;
30
30
  type Story = StoryObj<typeof meta>;
31
31
 
32
32
  export const Default: Story = {
33
+ parameters: {
34
+ docs: {
35
+ description: {
36
+ story:
37
+ 'Renders the Url field with no value. Typing into the address input recomposes the URL and fires onChange after the debounce; because no protocol is selected, the composed value keeps a bare "://" prefix.',
38
+ },
39
+ },
40
+ },
33
41
  play: async ({ canvasElement, args }) => {
34
42
  const canvas = within(canvasElement);
35
43
  const input = canvas.getByLabelText('URL address');
@@ -49,6 +57,14 @@ export const WithValue: Story = {
49
57
  args: {
50
58
  value: 'https://example.com',
51
59
  },
60
+ parameters: {
61
+ docs: {
62
+ description: {
63
+ story:
64
+ 'Renders the Url field pre-populated with "https://example.com" — the URL is split across the https protocol selector and the example.com address input.',
65
+ },
66
+ },
67
+ },
52
68
  play: async ({ canvasElement }) => {
53
69
  const canvas = within(canvasElement);
54
70
  await expect(await canvas.findByDisplayValue('example.com')).toBeInTheDocument();
@@ -60,6 +76,14 @@ export const KeepsSeparatorInsideAddress: Story = {
60
76
  args: {
61
77
  value: 'https://proxy/forward?to=http://inner',
62
78
  },
79
+ parameters: {
80
+ docs: {
81
+ description: {
82
+ story:
83
+ 'Renders the Url field with a URL whose query-string embeds a second "://". The protocol split only consumes the leading separator; the inner "://" survives inside the address input.',
84
+ },
85
+ },
86
+ },
63
87
  play: async ({ canvasElement }) => {
64
88
  const canvas = within(canvasElement);
65
89
  // `://` inside the address survives the protocol/address split.