@qoretechnologies/reqraft 0.10.10 → 0.10.12
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.
- package/dist/providers/StorageProvider.d.ts.map +1 -1
- package/dist/providers/StorageProvider.js +14 -4
- package/dist/providers/StorageProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/components/dpqlEditor/DpqlEditor.stories.tsx +74 -2
- package/src/components/form/engine/FormEngine.stories.tsx +654 -32
- package/src/components/form/engine/FormEngineRemote.stories.tsx +48 -0
- package/src/components/form/engine/_structuredData/StructuredDataView.stories.tsx +8 -0
- package/src/components/form/engine/variants/FormEngineVariants.stories.tsx +40 -0
- package/src/components/form/expressions/ExpressionField.stories.tsx +74 -2
- package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +187 -0
- package/src/components/form/fields/Field.stories.tsx +40 -0
- package/src/components/form/fields/array/ArrayAutoField.stories.tsx +64 -0
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +136 -0
- package/src/components/form/fields/binary/Binary.stories.tsx +32 -0
- package/src/components/form/fields/boolean/Boolean.stories.tsx +24 -0
- package/src/components/form/fields/byte-size/ByteSize.stories.tsx +24 -0
- package/src/components/form/fields/color/Color.stories.tsx +30 -0
- package/src/components/form/fields/cron/Cron.stories.tsx +8 -0
- package/src/components/form/fields/date/Date.stories.tsx +22 -0
- package/src/components/form/fields/file/File.stories.tsx +48 -0
- package/src/components/form/fields/long-string/LongString.stories.tsx +24 -0
- package/src/components/form/fields/markdown/Markdown.stories.tsx +8 -0
- package/src/components/form/fields/number/Number.stories.tsx +31 -0
- package/src/components/form/fields/object/Object.stories.tsx +88 -0
- package/src/components/form/fields/radio-group/RadioGroup.stories.tsx +24 -0
- package/src/components/form/fields/rich-text/RichText.stories.tsx +23 -0
- package/src/components/form/fields/schema-definition/SchemaDefinitionField.stories.tsx +72 -0
- package/src/components/form/fields/select/Select.stories.tsx +104 -0
- package/src/components/form/fields/string/String.stories.tsx +16 -0
- package/src/components/form/fields/template/TemplateField.stories.tsx +160 -0
- package/src/components/form/fields/url/Url.stories.tsx +24 -0
- package/src/components/log/Log.stories.tsx +96 -0
- package/src/components/menu/Menu.stories.tsx +54 -0
- package/src/components/qonsoleSmartInput/QonsoleSmartInput.stories.tsx +14 -0
- package/src/components/smartEditor/SmartEditor.stories.tsx +32 -0
- package/src/hooks/useFetch/useFetch.stories.tsx +30 -0
- package/src/hooks/useStorage/useStorage.stories.tsx +82 -0
- package/src/hooks/useWebSocket/useWebsocket.stories.tsx +127 -1
- package/src/providers/StorageProvider.tsx +12 -4
- package/src/stores/currentUser/currentUser.stories.tsx +17 -0
|
@@ -123,6 +123,14 @@ export const SchemaFromUrl: Story = {
|
|
|
123
123
|
name: 'remoteBasic',
|
|
124
124
|
url: 'sb-remote/basic',
|
|
125
125
|
},
|
|
126
|
+
parameters: {
|
|
127
|
+
docs: {
|
|
128
|
+
description: {
|
|
129
|
+
story:
|
|
130
|
+
'Renders FormEngine with a url — the options schema is fetched from options/{url}, three fields mount with the preselected localhost default seeded and onOptionsLoaded fires with the fetched schema.',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
126
134
|
async beforeEach() {
|
|
127
135
|
return mockFetchRoutes({ 'options/sb-remote/basic': { body: BASIC_SCHEMA } });
|
|
128
136
|
},
|
|
@@ -153,6 +161,14 @@ export const OperatorsFromUrl: Story = {
|
|
|
153
161
|
hostname: { type: 'string', value: 'qore', op: ['like'] },
|
|
154
162
|
} as any,
|
|
155
163
|
},
|
|
164
|
+
parameters: {
|
|
165
|
+
docs: {
|
|
166
|
+
description: {
|
|
167
|
+
story:
|
|
168
|
+
'Renders FormEngine with both url and operatorsUrl — the operator select resolves the "like" op against the fetched operator schema and the WHERE/IS summary tags appear alongside the option.',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
156
172
|
async beforeEach() {
|
|
157
173
|
return mockFetchRoutes({
|
|
158
174
|
'options/sb-remote/search': { body: SEARCH_SCHEMA },
|
|
@@ -181,6 +197,14 @@ export const FetchFailure: Story = {
|
|
|
181
197
|
name: 'remoteFail',
|
|
182
198
|
url: 'sb-remote/fail',
|
|
183
199
|
},
|
|
200
|
+
parameters: {
|
|
201
|
+
docs: {
|
|
202
|
+
description: {
|
|
203
|
+
story:
|
|
204
|
+
'Renders FormEngine when the schema fetch returns 500 — the skeleton resolves into the "No options available" empty state instead of crashing.',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
184
208
|
async beforeEach() {
|
|
185
209
|
return mockFetchRoutes({
|
|
186
210
|
'options/sb-remote/fail': { status: 500, body: { err: 'boom' } },
|
|
@@ -202,6 +226,14 @@ export const UrlChangeResetsValue: Story = {
|
|
|
202
226
|
name: 'remoteSwitch',
|
|
203
227
|
url: 'sb-remote/first',
|
|
204
228
|
},
|
|
229
|
+
parameters: {
|
|
230
|
+
docs: {
|
|
231
|
+
description: {
|
|
232
|
+
story:
|
|
233
|
+
'Renders FormEngine wired to url="first". Clicking the switch button re-points the engine to a different schema — the previous value (localhost) is dropped and the new Token field mounts.',
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
205
237
|
render(args) {
|
|
206
238
|
const [url, setUrl] = useState(args.url);
|
|
207
239
|
return (
|
|
@@ -256,6 +288,14 @@ export const InjectedOptionActions: Story = {
|
|
|
256
288
|
},
|
|
257
289
|
],
|
|
258
290
|
},
|
|
291
|
+
parameters: {
|
|
292
|
+
docs: {
|
|
293
|
+
description: {
|
|
294
|
+
story:
|
|
295
|
+
'Renders FormEngine with an optionActions factory that injects a per-option AI-assist button. Hovering an option reveals the injected action next to it.',
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
},
|
|
259
299
|
async play() {
|
|
260
300
|
await waitFor(() => expect(optionCount()).toBe(3), { timeout: 10000 });
|
|
261
301
|
|
|
@@ -278,6 +318,14 @@ export const TemplatesFromContext: Story = {
|
|
|
278
318
|
options: BASIC_SCHEMA as any,
|
|
279
319
|
interfaceContext: 'sb-ctx',
|
|
280
320
|
},
|
|
321
|
+
parameters: {
|
|
322
|
+
docs: {
|
|
323
|
+
description: {
|
|
324
|
+
story:
|
|
325
|
+
'Renders FormEngine with an interfaceContext — useTemplates hits system/getContextData so template values are available in the schema fields.',
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
},
|
|
281
329
|
async beforeEach() {
|
|
282
330
|
return mockFetchRoutes({
|
|
283
331
|
'system/getContextData': {
|
|
@@ -57,6 +57,14 @@ export const WorkflowOrderData: Story = {
|
|
|
57
57
|
// Expand deep enough that the parsed-YAML sub-tree is visible.
|
|
58
58
|
defaultExpandDepth: 3,
|
|
59
59
|
},
|
|
60
|
+
parameters: {
|
|
61
|
+
docs: {
|
|
62
|
+
description: {
|
|
63
|
+
story:
|
|
64
|
+
'Renders StructuredDataView over a workflow-order payload — UI-encoded envelopes unwrap to scalars, embedded YAML strings parse into sub-trees and Qorus timestamps format to YYYY-MM-DD HH:mm:ss.SSS in the viewer\'s zone.',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
60
68
|
play: async () => {
|
|
61
69
|
await _testsWaitForText('ORD-1002');
|
|
62
70
|
await _testsWaitForText('order-process');
|
|
@@ -59,6 +59,14 @@ type Story = StoryObj<typeof meta>;
|
|
|
59
59
|
|
|
60
60
|
export const V1CalmTable: Story = {
|
|
61
61
|
name: '1 · Calm Table',
|
|
62
|
+
parameters: {
|
|
63
|
+
docs: {
|
|
64
|
+
description: {
|
|
65
|
+
story:
|
|
66
|
+
'Renders the "Calm Table" compact-form variant over the shared basic schema — one of four visual candidates for the read-first FormEngine view.',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
62
70
|
render: () => (
|
|
63
71
|
<Frame>
|
|
64
72
|
<VariantCalmTable options={options} values={values} />
|
|
@@ -68,6 +76,14 @@ export const V1CalmTable: Story = {
|
|
|
68
76
|
|
|
69
77
|
export const V2Cards: Story = {
|
|
70
78
|
name: '2 · Cards',
|
|
79
|
+
parameters: {
|
|
80
|
+
docs: {
|
|
81
|
+
description: {
|
|
82
|
+
story:
|
|
83
|
+
'Renders the "Cards" compact-form variant over the shared basic schema — each field group is a card so the presentation reads as chunked panels.',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
71
87
|
render: () => (
|
|
72
88
|
<Frame>
|
|
73
89
|
<VariantCards options={options} values={values} />
|
|
@@ -77,6 +93,14 @@ export const V2Cards: Story = {
|
|
|
77
93
|
|
|
78
94
|
export const V3Focus: Story = {
|
|
79
95
|
name: '3 · Focus',
|
|
96
|
+
parameters: {
|
|
97
|
+
docs: {
|
|
98
|
+
description: {
|
|
99
|
+
story:
|
|
100
|
+
'Renders the "Focus" compact-form variant over the richer focus-demo schema (named groups, required-group choices) so the variant is compared under full engine parity.',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
80
104
|
render: () => (
|
|
81
105
|
<Frame>
|
|
82
106
|
<VariantFocus options={focusOptions} values={focusValues} config={focusConfig} />
|
|
@@ -86,6 +110,14 @@ export const V3Focus: Story = {
|
|
|
86
110
|
|
|
87
111
|
export const V4Minimal: Story = {
|
|
88
112
|
name: '4 · Minimal',
|
|
113
|
+
parameters: {
|
|
114
|
+
docs: {
|
|
115
|
+
description: {
|
|
116
|
+
story:
|
|
117
|
+
'Renders the "Minimal" compact-form variant over the shared basic schema — the sparest of the four candidates, only labels and values.',
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
89
121
|
render: () => (
|
|
90
122
|
<Frame>
|
|
91
123
|
<VariantMinimal options={options} values={values} />
|
|
@@ -96,6 +128,14 @@ export const V4Minimal: Story = {
|
|
|
96
128
|
/** All four stacked, labelled — for a quick scroll-through comparison. */
|
|
97
129
|
export const CompareAll: Story = {
|
|
98
130
|
name: '★ Compare all',
|
|
131
|
+
parameters: {
|
|
132
|
+
docs: {
|
|
133
|
+
description: {
|
|
134
|
+
story:
|
|
135
|
+
'Renders all four compact-form variants stacked in a single scroll — the Calm Table, Cards, Focus and Minimal layouts sit under labelled panels so they can be compared side by side.',
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
99
139
|
render: () => {
|
|
100
140
|
const items: [string, React.ReactNode][] = [
|
|
101
141
|
['1 · Calm Table', <VariantCalmTable key='v1' options={options} values={values} />],
|
|
@@ -50,6 +50,14 @@ export const Default: Story = {
|
|
|
50
50
|
args: {
|
|
51
51
|
value: SAMPLE,
|
|
52
52
|
},
|
|
53
|
+
parameters: {
|
|
54
|
+
docs: {
|
|
55
|
+
description: {
|
|
56
|
+
story:
|
|
57
|
+
'Renders ExpressionField holding a "$local:name == John" expression — the Visual builder shows the Logical Equals operator with its two operands and the Visual/Text mode toggle.',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
53
61
|
async play({ canvasElement }) {
|
|
54
62
|
const canvas = within(canvasElement);
|
|
55
63
|
|
|
@@ -73,6 +81,14 @@ export const Empty: Story = {
|
|
|
73
81
|
value: { is_expression: true, value: { args: [] } },
|
|
74
82
|
defaultMode: 'text',
|
|
75
83
|
},
|
|
84
|
+
parameters: {
|
|
85
|
+
docs: {
|
|
86
|
+
description: {
|
|
87
|
+
story:
|
|
88
|
+
'Renders ExpressionField in Text mode with an empty expression AST — the "Parsed" preview shows the "(empty)" placeholder for an empty expression.',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
76
92
|
async beforeEach() {
|
|
77
93
|
const stop = startDpqlMockLsp();
|
|
78
94
|
return () => stop();
|
|
@@ -102,6 +118,14 @@ export const Empty: Story = {
|
|
|
102
118
|
* builder, and the Visual/Text toggle is present.
|
|
103
119
|
*/
|
|
104
120
|
export const ViaFormEngine: Story = {
|
|
121
|
+
parameters: {
|
|
122
|
+
docs: {
|
|
123
|
+
description: {
|
|
124
|
+
story:
|
|
125
|
+
'Renders a FormEngine schema with a bool option that carries supports_expressions and a stored expression value — the engine routes through TemplateField and mounts the ExpressionField shell with the Visual builder and the Visual/Text toggle.',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
105
129
|
render: () => {
|
|
106
130
|
const [value, setValue] = useState<any>({
|
|
107
131
|
condition: { type: 'bool', value: SAMPLE.value, is_expression: true },
|
|
@@ -150,6 +174,14 @@ export const ViaFormEngine: Story = {
|
|
|
150
174
|
* renders the same AST.
|
|
151
175
|
*/
|
|
152
176
|
export const ViaFormEngineTextMode: Story = {
|
|
177
|
+
parameters: {
|
|
178
|
+
docs: {
|
|
179
|
+
description: {
|
|
180
|
+
story:
|
|
181
|
+
'Renders the FormEngine expression field, then switches to Text mode — the DPQL editor seeds from the stored AST via the mock LSP\'s dpql/serialize call and the "Parsed" preview mirrors it.',
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
153
185
|
render: ViaFormEngine.render,
|
|
154
186
|
async beforeEach() {
|
|
155
187
|
const stop = startDpqlMockLsp();
|
|
@@ -200,6 +232,14 @@ export const ViaFormEngineTextMode: Story = {
|
|
|
200
232
|
* the seeded direction is covered by `ViaFormEngineTextMode` above.)
|
|
201
233
|
*/
|
|
202
234
|
export const ViaFormEngineTextTyping: Story = {
|
|
235
|
+
parameters: {
|
|
236
|
+
docs: {
|
|
237
|
+
description: {
|
|
238
|
+
story:
|
|
239
|
+
'Renders the FormEngine expression field with an empty AST in Text mode. Typing DPQL text triggers the mock LSP\'s dpql/parse and the parsed expression lands in the form value with is_expression set.',
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
203
243
|
render: (args) => {
|
|
204
244
|
const [value, setValue] = useState<any>({
|
|
205
245
|
condition: { type: 'bool', value: { args: [] }, is_expression: true },
|
|
@@ -277,6 +317,14 @@ export const TextMode: Story = {
|
|
|
277
317
|
value: { is_expression: true, value: { args: [] } },
|
|
278
318
|
defaultMode: 'text',
|
|
279
319
|
},
|
|
320
|
+
parameters: {
|
|
321
|
+
docs: {
|
|
322
|
+
description: {
|
|
323
|
+
story:
|
|
324
|
+
'Renders ExpressionField in Text (DPQL) mode over a mock-socket LSP. Typing DPQL text triggers dpql/parse and the "Parsed" preview reflects the resulting AST.',
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
},
|
|
280
328
|
async beforeEach() {
|
|
281
329
|
const stop = startDpqlMockLsp();
|
|
282
330
|
return () => stop();
|
|
@@ -309,6 +357,14 @@ export const TextMode: Story = {
|
|
|
309
357
|
* Driven live for the toggle interaction.
|
|
310
358
|
*/
|
|
311
359
|
export const ToggleInFormEngine: Story = {
|
|
360
|
+
parameters: {
|
|
361
|
+
docs: {
|
|
362
|
+
description: {
|
|
363
|
+
story:
|
|
364
|
+
'Renders a FormEngine schema with a plain bool option (supports_expressions, no value). Clicking More then "Use Expression" flips the field to expression mode and the ExpressionField shell with the Visual builder mounts in place of the checkbox.',
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
},
|
|
312
368
|
render: () => {
|
|
313
369
|
const [value, setValue] = useState<any>({});
|
|
314
370
|
return (
|
|
@@ -380,7 +436,15 @@ export const Live: Story = {
|
|
|
380
436
|
// (network/auth), still snapshotted by Chromatic. Mirrors the DpqlEditor
|
|
381
437
|
// live stories.
|
|
382
438
|
tags: ['!test'],
|
|
383
|
-
parameters: {
|
|
439
|
+
parameters: {
|
|
440
|
+
live: true,
|
|
441
|
+
docs: {
|
|
442
|
+
description: {
|
|
443
|
+
story:
|
|
444
|
+
'Renders ExpressionField against a live Qorus instance — the picker fetches the real ~121-function catalogue rather than the mock, and the seeded "contains" expression exercises the schema-driven operators and operands.',
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
},
|
|
384
448
|
args: {
|
|
385
449
|
type: 'bool',
|
|
386
450
|
value: {
|
|
@@ -423,7 +487,15 @@ export const Live: Story = {
|
|
|
423
487
|
*/
|
|
424
488
|
export const LiveExplain: Story = {
|
|
425
489
|
tags: ['!test'],
|
|
426
|
-
parameters: {
|
|
490
|
+
parameters: {
|
|
491
|
+
live: true,
|
|
492
|
+
docs: {
|
|
493
|
+
description: {
|
|
494
|
+
story:
|
|
495
|
+
'Renders ExpressionField in Text mode against a live Qorus instance — the "Parsed" preview uses the server-rendered form via dpql/renderExpression rather than the client-side approximation.',
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
},
|
|
427
499
|
args: {
|
|
428
500
|
value: {
|
|
429
501
|
is_expression: true,
|
|
@@ -113,6 +113,14 @@ export const Default: Story = {
|
|
|
113
113
|
args: {
|
|
114
114
|
returnType: ['string', 'int'],
|
|
115
115
|
},
|
|
116
|
+
parameters: {
|
|
117
|
+
docs: {
|
|
118
|
+
description: {
|
|
119
|
+
story:
|
|
120
|
+
'Renders the ExpressionBuilder with no value and a string-or-int return type — a single empty expression card is shown so the operator can pick an operation.',
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
116
124
|
play: async () => {
|
|
117
125
|
await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
|
|
118
126
|
},
|
|
@@ -122,6 +130,14 @@ export const DefaultBoolean: Story = {
|
|
|
122
130
|
args: {
|
|
123
131
|
returnType: ['boolean'],
|
|
124
132
|
},
|
|
133
|
+
parameters: {
|
|
134
|
+
docs: {
|
|
135
|
+
description: {
|
|
136
|
+
story:
|
|
137
|
+
'Renders the ExpressionBuilder with no value and a boolean return type — a single empty expression card is shown so the operator can pick a boolean-returning operation.',
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
125
141
|
play: async () => {
|
|
126
142
|
await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
|
|
127
143
|
},
|
|
@@ -142,6 +158,14 @@ export const WithSimpleValue: Story = {
|
|
|
142
158
|
},
|
|
143
159
|
},
|
|
144
160
|
},
|
|
161
|
+
parameters: {
|
|
162
|
+
docs: {
|
|
163
|
+
description: {
|
|
164
|
+
story:
|
|
165
|
+
'Renders the ExpressionBuilder holding a single "contains" expression with three arguments — the card shows the operation and each operand slot.',
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
145
169
|
play: async () => {
|
|
146
170
|
await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
|
|
147
171
|
},
|
|
@@ -234,6 +258,14 @@ export const WithComplexValue: Story = {
|
|
|
234
258
|
},
|
|
235
259
|
},
|
|
236
260
|
},
|
|
261
|
+
parameters: {
|
|
262
|
+
docs: {
|
|
263
|
+
description: {
|
|
264
|
+
story:
|
|
265
|
+
'Renders the ExpressionBuilder holding a nested &&/|| expression with six leaf expressions — the builder shows the full expression tree with the AND/OR group cards and their operand cards.',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
},
|
|
237
269
|
play: async () => {
|
|
238
270
|
await waitFor(() => expect(expressionCount()).toBe(6), { timeout: 10000 });
|
|
239
271
|
},
|
|
@@ -241,6 +273,15 @@ export const WithComplexValue: Story = {
|
|
|
241
273
|
|
|
242
274
|
export const ShowsExplanation: Story = {
|
|
243
275
|
...WithComplexValue,
|
|
276
|
+
parameters: {
|
|
277
|
+
...WithComplexValue.parameters,
|
|
278
|
+
docs: {
|
|
279
|
+
description: {
|
|
280
|
+
story:
|
|
281
|
+
'Renders the nested expression tree and clicks Explain — the plain-language explanation of the whole expression is shown alongside the builder.',
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
},
|
|
244
285
|
play: async (args) => {
|
|
245
286
|
await WithComplexValue.play!(args);
|
|
246
287
|
await clickButtonByLabel('Explain');
|
|
@@ -260,6 +301,15 @@ export const Readonly: Story = {
|
|
|
260
301
|
...WithComplexValue.args,
|
|
261
302
|
readOnly: true,
|
|
262
303
|
},
|
|
304
|
+
parameters: {
|
|
305
|
+
...WithComplexValue.parameters,
|
|
306
|
+
docs: {
|
|
307
|
+
description: {
|
|
308
|
+
story:
|
|
309
|
+
'Renders the nested expression tree with readOnly enabled — the tree is visible but the AND/OR add-group controls are hidden so the operator cannot mutate it.',
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
},
|
|
263
313
|
play: async (args) => {
|
|
264
314
|
await WithComplexValue.play!(args);
|
|
265
315
|
expect(document.querySelector('.expression-and')).toBeNull();
|
|
@@ -268,6 +318,15 @@ export const Readonly: Story = {
|
|
|
268
318
|
|
|
269
319
|
export const FocusedEditing: Story = {
|
|
270
320
|
...WithComplexValue,
|
|
321
|
+
parameters: {
|
|
322
|
+
...WithComplexValue.parameters,
|
|
323
|
+
docs: {
|
|
324
|
+
description: {
|
|
325
|
+
story:
|
|
326
|
+
'Renders the nested expression tree, hovers a card and clicks its fullscreen action — the focused-editing modal opens over that subtree.',
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
},
|
|
271
330
|
play: async (args) => {
|
|
272
331
|
await WithComplexValue.play!(args);
|
|
273
332
|
await userEvent.hover(document.querySelectorAll('.expression')[0]);
|
|
@@ -288,6 +347,14 @@ export const WithArgWithAllowedValues: Story = {
|
|
|
288
347
|
args: {
|
|
289
348
|
returnType: ['bool'],
|
|
290
349
|
},
|
|
350
|
+
parameters: {
|
|
351
|
+
docs: {
|
|
352
|
+
description: {
|
|
353
|
+
story:
|
|
354
|
+
'Renders an empty ExpressionBuilder and selects "Matches Regular Expression" — the third operand ("Regex Options") carries element_allowed_values and renders the "Select one or more" picker.',
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
291
358
|
play: async (args) => {
|
|
292
359
|
await Default.play!(args);
|
|
293
360
|
|
|
@@ -311,6 +378,14 @@ export const WithIntType: Story = {
|
|
|
311
378
|
},
|
|
312
379
|
},
|
|
313
380
|
},
|
|
381
|
+
parameters: {
|
|
382
|
+
docs: {
|
|
383
|
+
description: {
|
|
384
|
+
story:
|
|
385
|
+
'Renders the ExpressionBuilder with an int-typed >= expression comparing $local:input to 20 — the operands render as Number fields inside the expression card.',
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
},
|
|
314
389
|
play: async () => {
|
|
315
390
|
await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
|
|
316
391
|
},
|
|
@@ -326,6 +401,15 @@ export const WithIntType: Story = {
|
|
|
326
401
|
*/
|
|
327
402
|
export const ArgsChangeWhenOperatorChanges: Story = {
|
|
328
403
|
...WithSimpleValue,
|
|
404
|
+
parameters: {
|
|
405
|
+
...WithSimpleValue.parameters,
|
|
406
|
+
docs: {
|
|
407
|
+
description: {
|
|
408
|
+
story:
|
|
409
|
+
'Renders the seeded "String Contains" expression, then switches the operation to "Matches Regular Expression" — the string operands carry over and the new "Regex Options" allowed-values operand appears.',
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
},
|
|
329
413
|
play: async () => {
|
|
330
414
|
// Both string operands of the seeded `contains` render as textareas.
|
|
331
415
|
await waitFor(
|
|
@@ -344,6 +428,14 @@ export const NewGroupsCanBeCreated: Story = {
|
|
|
344
428
|
...WithSimpleValue.args,
|
|
345
429
|
returnType: ['bool'],
|
|
346
430
|
},
|
|
431
|
+
parameters: {
|
|
432
|
+
docs: {
|
|
433
|
+
description: {
|
|
434
|
+
story:
|
|
435
|
+
'Renders the seeded "String Contains" expression, then clicks the AND and OR add-group actions — the tree grows from 1 to 3 expression cards as new grouping levels are added.',
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
},
|
|
347
439
|
play: async () => {
|
|
348
440
|
await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
|
|
349
441
|
|
|
@@ -357,6 +449,15 @@ export const NewGroupsCanBeCreated: Story = {
|
|
|
357
449
|
|
|
358
450
|
export const GroupsCanBeDeleted: Story = {
|
|
359
451
|
...WithComplexValue,
|
|
452
|
+
parameters: {
|
|
453
|
+
...WithComplexValue.parameters,
|
|
454
|
+
docs: {
|
|
455
|
+
description: {
|
|
456
|
+
story:
|
|
457
|
+
'Renders the nested expression tree (6 cards) and removes one group — the tree shrinks to 5 cards after the delete.',
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
},
|
|
360
461
|
play: async () => {
|
|
361
462
|
await waitFor(() => expect(expressionCount()).toBe(6), { timeout: 10000 });
|
|
362
463
|
|
|
@@ -377,6 +478,14 @@ export const GroupsCanBeDeleted: Story = {
|
|
|
377
478
|
* inline `AiAssistanceAction({ context: selectedExpression })` captured.
|
|
378
479
|
*/
|
|
379
480
|
export const WithInjectedExtraActions: Story = {
|
|
481
|
+
parameters: {
|
|
482
|
+
docs: {
|
|
483
|
+
description: {
|
|
484
|
+
story:
|
|
485
|
+
'Renders the nested expression tree with an extraActions factory that injects an AI-assist button per card. Hovering an expression reveals the injected action alongside the built-in ones.',
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
},
|
|
380
489
|
args: {
|
|
381
490
|
...WithComplexValue.args,
|
|
382
491
|
extraActions: ({ selectedExpression }) => [
|
|
@@ -428,6 +537,14 @@ export const ExpressionWithIntReturnType: Story = {
|
|
|
428
537
|
is_expression: true,
|
|
429
538
|
},
|
|
430
539
|
},
|
|
540
|
+
parameters: {
|
|
541
|
+
docs: {
|
|
542
|
+
description: {
|
|
543
|
+
story:
|
|
544
|
+
'Renders the ExpressionBuilder with a "+" (Addition) varargs expression holding four int operands — the three "rest" args each expose a remove-argument button.',
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
},
|
|
431
548
|
play: async () => {
|
|
432
549
|
await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
|
|
433
550
|
// Three "rest" args → three remove-argument buttons.
|
|
@@ -438,6 +555,15 @@ export const ExpressionWithIntReturnType: Story = {
|
|
|
438
555
|
/** Remove one variable argument — the remove-arg count drops from 3 to 2. */
|
|
439
556
|
export const VariableArgumentsCanBeRemoved: Story = {
|
|
440
557
|
...ExpressionWithIntReturnType,
|
|
558
|
+
parameters: {
|
|
559
|
+
...ExpressionWithIntReturnType.parameters,
|
|
560
|
+
docs: {
|
|
561
|
+
description: {
|
|
562
|
+
story:
|
|
563
|
+
'Renders the "+" varargs expression and clicks one remove-argument button — one operand disappears and the remove-arg count drops from 3 to 2.',
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
},
|
|
441
567
|
play: async (args) => {
|
|
442
568
|
await ExpressionWithIntReturnType.play!(args);
|
|
443
569
|
|
|
@@ -450,6 +576,15 @@ export const VariableArgumentsCanBeRemoved: Story = {
|
|
|
450
576
|
/** Remove one then add one back — the count returns to 3. */
|
|
451
577
|
export const VariableArgumentsCanBeAdded: Story = {
|
|
452
578
|
...ExpressionWithIntReturnType,
|
|
579
|
+
parameters: {
|
|
580
|
+
...ExpressionWithIntReturnType.parameters,
|
|
581
|
+
docs: {
|
|
582
|
+
description: {
|
|
583
|
+
story:
|
|
584
|
+
'Renders the "+" varargs expression, removes one operand and then adds one back — the remove-arg count moves 3 → 2 → 3.',
|
|
585
|
+
},
|
|
586
|
+
},
|
|
587
|
+
},
|
|
453
588
|
play: async (args) => {
|
|
454
589
|
await ExpressionWithIntReturnType.play!(args);
|
|
455
590
|
|
|
@@ -487,6 +622,14 @@ export const ExpressionCanBeWrapped: Story = {
|
|
|
487
622
|
returnType: ['string', 'int'],
|
|
488
623
|
value: seededConvert,
|
|
489
624
|
},
|
|
625
|
+
parameters: {
|
|
626
|
+
docs: {
|
|
627
|
+
description: {
|
|
628
|
+
story:
|
|
629
|
+
'Renders a seeded "Convert to Boolean" expression, hovers the card and picks "Join List Elements" from the Wrap picker — the outer op mounts and the original expression becomes its first operand.',
|
|
630
|
+
},
|
|
631
|
+
},
|
|
632
|
+
},
|
|
490
633
|
play: async () => {
|
|
491
634
|
// Seeded base op + its operand render.
|
|
492
635
|
await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
|
|
@@ -506,6 +649,15 @@ export const ExpressionCanBeWrapped: Story = {
|
|
|
506
649
|
/** Wrap, then unwrap — back to a single expression card. */
|
|
507
650
|
export const ExpressionCanBeUnwrapped: Story = {
|
|
508
651
|
...ExpressionCanBeWrapped,
|
|
652
|
+
parameters: {
|
|
653
|
+
...ExpressionCanBeWrapped.parameters,
|
|
654
|
+
docs: {
|
|
655
|
+
description: {
|
|
656
|
+
story:
|
|
657
|
+
'Renders the wrapped expression from ExpressionCanBeWrapped, then hovers and unwraps the outer op — the inner "Convert to Boolean" survives and the outer wrapper is removed.',
|
|
658
|
+
},
|
|
659
|
+
},
|
|
660
|
+
},
|
|
509
661
|
play: async (args) => {
|
|
510
662
|
await ExpressionCanBeWrapped.play!(args);
|
|
511
663
|
|
|
@@ -579,6 +731,14 @@ const SeededMismatchBase: Story = {
|
|
|
579
731
|
* exact, so the builder flags it and the confirmation modal mounts.
|
|
580
732
|
*/
|
|
581
733
|
export const FunctionArgsArePassedToNewFunctionAndNeedConfirmation: Story = {
|
|
734
|
+
parameters: {
|
|
735
|
+
docs: {
|
|
736
|
+
description: {
|
|
737
|
+
story:
|
|
738
|
+
'Renders a valued "Format Date" expression and switches the operation to "Matches Regular Expression" — the carried date arg is accepted-but-not-exact for the new richtext operand and the mismatched-arguments confirmation modal mounts.',
|
|
739
|
+
},
|
|
740
|
+
},
|
|
741
|
+
},
|
|
582
742
|
args: {
|
|
583
743
|
returnType: 'string',
|
|
584
744
|
value: {
|
|
@@ -616,6 +776,15 @@ export const FunctionArgsArePassedToNewFunctionAndNeedConfirmation: Story = {
|
|
|
616
776
|
/** "Confirm selection" keeps the (still-selected) mismatched arg, transformed. */
|
|
617
777
|
export const AcceptIncompatibleFunctionArgsSelection: Story = {
|
|
618
778
|
...SeededMismatchBase,
|
|
779
|
+
parameters: {
|
|
780
|
+
...SeededMismatchBase.parameters,
|
|
781
|
+
docs: {
|
|
782
|
+
description: {
|
|
783
|
+
story:
|
|
784
|
+
'Renders the seeded mismatch-flagged expression, then clicks "Confirm selection" on the mismatched-arguments modal — the (still-selected) argument is kept and transformed to the new expected type.',
|
|
785
|
+
},
|
|
786
|
+
},
|
|
787
|
+
},
|
|
619
788
|
play: async (args) => {
|
|
620
789
|
await SeededMismatchBase.play!(args);
|
|
621
790
|
|
|
@@ -636,6 +805,15 @@ export const AcceptIncompatibleFunctionArgsSelection: Story = {
|
|
|
636
805
|
/** "Accept all" — every mismatched arg is transformed and kept. */
|
|
637
806
|
export const AcceptAllIncompatibleFunctionArgs: Story = {
|
|
638
807
|
...SeededMismatchBase,
|
|
808
|
+
parameters: {
|
|
809
|
+
...SeededMismatchBase.parameters,
|
|
810
|
+
docs: {
|
|
811
|
+
description: {
|
|
812
|
+
story:
|
|
813
|
+
'Renders the seeded mismatch-flagged expression, then clicks "Accept all" on the mismatched-arguments modal — every flagged argument is transformed and kept.',
|
|
814
|
+
},
|
|
815
|
+
},
|
|
816
|
+
},
|
|
639
817
|
play: async (args) => {
|
|
640
818
|
await SeededMismatchBase.play!(args);
|
|
641
819
|
|
|
@@ -655,6 +833,15 @@ export const AcceptAllIncompatibleFunctionArgs: Story = {
|
|
|
655
833
|
/** "Discard all" — every mismatched arg is cleared. */
|
|
656
834
|
export const DiscardAllIncompatibleFunctionArgs: Story = {
|
|
657
835
|
...SeededMismatchBase,
|
|
836
|
+
parameters: {
|
|
837
|
+
...SeededMismatchBase.parameters,
|
|
838
|
+
docs: {
|
|
839
|
+
description: {
|
|
840
|
+
story:
|
|
841
|
+
'Renders the seeded mismatch-flagged expression, then clicks "Discard all" on the mismatched-arguments modal — every flagged argument is cleared.',
|
|
842
|
+
},
|
|
843
|
+
},
|
|
844
|
+
},
|
|
658
845
|
play: async (args) => {
|
|
659
846
|
await SeededMismatchBase.play!(args);
|
|
660
847
|
|