@flowerforce/flower-react 3.0.1-beta.0 → 3.0.1-beta.2
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/README.md +191 -196
- package/dist/index.cjs.js +53 -31
- package/dist/index.esm.js +53 -31
- package/dist/src/components/types/FlowerField.d.ts +1 -1
- package/dist/src/components/types/FlowerHooks.d.ts +2 -1
- package/dist/src/components/types/FlowerNavigate.d.ts +9 -0
- package/dist/src/context.d.ts +1 -0
- package/dist/src/index.d.ts +13 -0
- package/package.json +5 -5
package/README.md
CHANGED
@@ -19,7 +19,6 @@ For more info [flower.stackhouse.dev/](https://flower.stackhouse.dev/)
|
|
19
19
|
- **Form Validation**: Built-in functionalities to validate form inputs within nodes, ensuring data integrity and correctness.
|
20
20
|
- **History Management**: Internal management of flow history, tracking node traversal and changes for debugging and visualization purposes.
|
21
21
|
|
22
|
-
|
23
22
|
### Installation
|
24
23
|
|
25
24
|
Flower React can be installed via npm or yarn for use in any JavaScript project.
|
@@ -49,38 +48,35 @@ yarn add @flowerforce/flower-core
|
|
49
48
|
The **FlowerProvider** component wraps the entire application, providing a global context for managing the application flow.
|
50
49
|
|
51
50
|
```jsx
|
52
|
-
import React from 'react'
|
53
|
-
import Flower,
|
51
|
+
import React from 'react'
|
52
|
+
import { Flower, FlowerProvider } from '@flowerforce/flower-react'
|
54
53
|
|
55
54
|
function Root() {
|
56
55
|
return (
|
57
56
|
<FlowerProvider>
|
58
57
|
<App />
|
59
58
|
</FlowerProvider>
|
60
|
-
)
|
59
|
+
)
|
61
60
|
}
|
62
61
|
```
|
63
62
|
|
64
|
-
|
65
63
|
## How to use
|
64
|
+
|
66
65
|
### Simple Example
|
67
66
|
|
68
67
|
The **Flower** component defines an application flow with a specific name, which serves as a unique identifier for the flow. It is the main component for defining the application flow, accepting a required "name" property and an initialData field for prepopulating values.
|
69
68
|
|
70
69
|
The **FlowerNode** component represents a UI state or a step within the application flow. Transitions between nodes can be specified using the **to** object.
|
71
70
|
|
72
|
-
|
73
71
|
```jsx
|
74
72
|
import React from 'react'
|
75
|
-
import Flower,
|
73
|
+
import { Flower, FlowerNavigate, FlowerNode } from '@flowerforce/flower-react'
|
76
74
|
|
77
75
|
export const Page = () => {
|
78
76
|
return (
|
79
77
|
<Flower name="demo">
|
80
|
-
<FlowerNode id="step1"
|
81
|
-
to={{ step2: null }}>
|
78
|
+
<FlowerNode id="step1" to={{ step2: null }}>
|
82
79
|
...
|
83
|
-
|
84
80
|
<FlowerNavigate action="next">
|
85
81
|
<button>click me to go next</button>
|
86
82
|
</FlowerNavigate>
|
@@ -88,7 +84,6 @@ export const Page = () => {
|
|
88
84
|
|
89
85
|
<FlowerNode id="step2" to={{ step3: null }}>
|
90
86
|
...
|
91
|
-
|
92
87
|
<FlowerNavigate action="back">
|
93
88
|
<button>click me to go back</button>
|
94
89
|
</FlowerNavigate>
|
@@ -106,10 +101,9 @@ export const Page = () => {
|
|
106
101
|
</Flower>
|
107
102
|
)
|
108
103
|
}
|
109
|
-
|
110
104
|
```
|
111
105
|
|
112
|
-
Edit on
|
106
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-9wsjv7)
|
113
107
|
|
114
108
|
### Navigate with routes
|
115
109
|
|
@@ -117,44 +111,45 @@ Additionally, it's possible to navigate between nodes by defining specific route
|
|
117
111
|
|
118
112
|
```jsx
|
119
113
|
import React from 'react'
|
120
|
-
import
|
114
|
+
import {
|
115
|
+
Flower,
|
116
|
+
FlowerRoute,
|
117
|
+
FlowerNavigate,
|
118
|
+
FlowerNode
|
119
|
+
} from '@flowerforce/flower-react'
|
121
120
|
|
122
121
|
export const Page = () => {
|
123
122
|
return (
|
124
123
|
<Flower name="demo">
|
125
124
|
<FlowerRoute id="start" to={{ step1: null }} /> {/* autonext */}
|
126
|
-
|
127
|
-
|
128
|
-
to={{
|
129
|
-
stepOK:
|
130
|
-
stepKO:
|
125
|
+
<FlowerNode
|
126
|
+
id="step1"
|
127
|
+
to={{
|
128
|
+
stepOK: 'onSuccess',
|
129
|
+
stepKO: 'onError',
|
131
130
|
default: null
|
132
|
-
|
131
|
+
}}
|
132
|
+
>
|
133
133
|
...
|
134
|
-
|
135
134
|
<FlowerNavigate action="next" route="onSuccess">
|
136
135
|
<button>click me to go on "stepOK"</button>
|
137
136
|
</FlowerNavigate>
|
138
|
-
|
139
137
|
<FlowerNavigate action="next" route="onError">
|
140
138
|
<button>click me to go on "stepKO"</button>
|
141
139
|
</FlowerNavigate>
|
142
|
-
|
143
140
|
<FlowerNavigate action="next">
|
144
141
|
<button>click me to go on "default" </button>
|
145
142
|
</FlowerNavigate>
|
146
143
|
</FlowerNode>
|
147
|
-
|
148
144
|
<FlowerNode id="stepOK">... </FlowerNode>
|
149
145
|
<FlowerNode id="stepKO">... </FlowerNode>
|
150
146
|
<FlowerNode id="default">... </FlowerNode>
|
151
|
-
|
152
147
|
</Flower>
|
153
148
|
)
|
154
149
|
}
|
155
|
-
|
156
150
|
```
|
157
|
-
|
151
|
+
|
152
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-9k4kfk)
|
158
153
|
|
159
154
|
### Navigation State Rules
|
160
155
|
|
@@ -166,24 +161,28 @@ The FlowerNode step1 connects to both step2 and step3. However, the rule states
|
|
166
161
|
|
167
162
|
```jsx
|
168
163
|
import React from 'react'
|
169
|
-
import
|
164
|
+
import {
|
165
|
+
Flower,
|
166
|
+
FlowerRoute,
|
167
|
+
FlowerNavigate,
|
168
|
+
FlowerNode
|
169
|
+
} from '@flowerforce/flower-react'
|
170
170
|
|
171
171
|
export const Page = () => {
|
172
172
|
return (
|
173
173
|
<Flower name="demo" initialData={{ skipStep2: true }}>
|
174
174
|
<FlowerRoute id="start" to={{ step1: null }} />
|
175
|
-
|
176
|
-
<FlowerNode
|
175
|
+
|
176
|
+
<FlowerNode
|
177
177
|
id="step1"
|
178
|
-
to={{
|
178
|
+
to={{
|
179
179
|
step3: {
|
180
|
-
|
181
|
-
|
180
|
+
rules: { $and: [{ skipStep2: { $eq: true } }] }
|
181
|
+
},
|
182
182
|
step2: null
|
183
|
-
|
184
|
-
|
183
|
+
}}
|
184
|
+
>
|
185
185
|
...
|
186
|
-
|
187
186
|
<FlowerNavigate action="next">
|
188
187
|
<button>click me to go next</button>
|
189
188
|
</FlowerNavigate>
|
@@ -192,34 +191,39 @@ export const Page = () => {
|
|
192
191
|
<FlowerNode id="step2">...</FlowerNode>
|
193
192
|
|
194
193
|
<FlowerNode id="step3">...</FlowerNode>
|
195
|
-
|
196
194
|
</Flower>
|
197
195
|
)
|
198
196
|
}
|
199
|
-
|
200
197
|
```
|
201
|
-
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-5c4rs4)
|
202
198
|
|
199
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-5c4rs4)
|
203
200
|
|
204
201
|
### Basic WRITE | READ State
|
205
202
|
|
206
|
-
To modify the internal state of Flower, besides passing initialData as a prop, we can always modify and read the state through the components **FlowerField** and **FlowerValue**.
|
203
|
+
To modify the internal state of Flower, besides passing initialData as a prop, we can always modify and read the state through the components **FlowerField** and **FlowerValue**.
|
207
204
|
|
208
|
-
|
209
|
-
|
205
|
+
_FlowerField_ pass two props, onChange and value, to properly modify and read the value from the state of Flower.
|
206
|
+
_FlowerValue_ pass value, to properly read the value from the state of Flower.
|
210
207
|
|
211
208
|
Here's an example of how it works:
|
212
209
|
|
213
210
|
```jsx
|
214
211
|
import React from 'react'
|
215
|
-
import
|
212
|
+
import {
|
213
|
+
Flower,
|
214
|
+
FlowerRoute,
|
215
|
+
FlowerNavigate,
|
216
|
+
FlowerNode,
|
217
|
+
FlowerField,
|
218
|
+
FlowerValue
|
219
|
+
} from '@flowerforce/flower-react'
|
216
220
|
|
217
221
|
export const Page = () => {
|
218
222
|
return (
|
219
223
|
<Flower name="demo">
|
220
|
-
<FlowerNode
|
221
|
-
id="step1"
|
222
|
-
to={{
|
224
|
+
<FlowerNode
|
225
|
+
id="step1"
|
226
|
+
to={{
|
223
227
|
step3: {
|
224
228
|
rules={{ $and: [{ skipStep2: { $eq: true } }] }}
|
225
229
|
},
|
@@ -227,7 +231,7 @@ export const Page = () => {
|
|
227
231
|
}}
|
228
232
|
>
|
229
233
|
...
|
230
|
-
|
234
|
+
|
231
235
|
<FlowerField id="skipStep2">
|
232
236
|
{({ onChange, value }) => <input type="checkbox" checked={value} onChange={e => onChange(e.target.checked)} />}
|
233
237
|
</FlowerField>
|
@@ -239,7 +243,7 @@ export const Page = () => {
|
|
239
243
|
|
240
244
|
<FlowerNode id="step2">...</FlowerNode>
|
241
245
|
|
242
|
-
<FlowerNode id="step3">
|
246
|
+
<FlowerNode id="step3">
|
243
247
|
<FlowerValue id="enableFinal">
|
244
248
|
{({ value }) => <span>skipStep2: {String(!!value)}</span>}
|
245
249
|
</FlowerValue>
|
@@ -251,41 +255,36 @@ export const Page = () => {
|
|
251
255
|
|
252
256
|
```
|
253
257
|
|
254
|
-
Edit on
|
255
|
-
|
256
|
-
|
258
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-3-forked-r3hgnj)
|
257
259
|
|
258
260
|
### Action Node
|
259
261
|
|
260
|
-
|
261
262
|
The **FlowerAction** component serves as an action entity within the application flow, enabling the definition of specific actions to execute during the progression of the flow.
|
262
263
|
|
263
|
-
The distinction between **FlowerNode** and **FlowerAction** lies in how they behave within the flow.
|
264
|
+
The distinction between **FlowerNode** and **FlowerAction** lies in how they behave within the flow.
|
264
265
|
In the context of a **FlowerNode**, if a "back" action is taken but the preceding step is a **FlowerAction**, that particular step is skipped.
|
265
266
|
|
266
|
-
|
267
267
|
```jsx
|
268
|
-
import
|
268
|
+
import {
|
269
|
+
Flower,
|
269
270
|
FlowerAction,
|
270
271
|
FlowerNavigate,
|
271
272
|
FlowerNode,
|
272
|
-
useFlower
|
273
|
-
} from
|
274
|
-
import { memo, useEffect } from
|
273
|
+
useFlower
|
274
|
+
} from '@flowerforce/flower-react'
|
275
|
+
import { memo, useEffect } from 'react'
|
275
276
|
|
276
|
-
const ComponentAction = memo(
|
277
|
-
()
|
278
|
-
const { next } = useFlower();
|
277
|
+
const ComponentAction = memo(() => {
|
278
|
+
const { next } = useFlower()
|
279
279
|
|
280
|
-
|
281
|
-
|
280
|
+
useEffect(() => {
|
281
|
+
// * do your staff here - api call etc **
|
282
282
|
|
283
|
-
|
284
|
-
|
283
|
+
next()
|
284
|
+
}, [next])
|
285
285
|
|
286
|
-
|
287
|
-
|
288
|
-
);
|
286
|
+
return <span className="loader"></span>
|
287
|
+
})
|
289
288
|
|
290
289
|
export default function App() {
|
291
290
|
return (
|
@@ -294,7 +293,7 @@ export default function App() {
|
|
294
293
|
<FlowerNode id="step1" to={{ step2: null }}>
|
295
294
|
...
|
296
295
|
<FlowerNavigate action="next">
|
297
|
-
|
296
|
+
<button>click me to go next</button>
|
298
297
|
</FlowerNavigate>
|
299
298
|
</FlowerNode>
|
300
299
|
|
@@ -308,42 +307,39 @@ export default function App() {
|
|
308
307
|
<FlowerNode id="success">
|
309
308
|
...
|
310
309
|
<FlowerNavigate action="back">
|
311
|
-
|
310
|
+
<button>click me to go back</button>
|
312
311
|
</FlowerNavigate>
|
313
312
|
</FlowerNode>
|
314
313
|
</Flower>
|
315
|
-
)
|
314
|
+
)
|
316
315
|
}
|
317
|
-
|
318
316
|
```
|
319
317
|
|
320
|
-
Edit on
|
318
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-actionnode-766vhj)
|
321
319
|
|
322
320
|
Another difference between **FlowerNode** and **FlowerAction** is that upon mounting a FlowerAction, if the preceding node of type **FlowerNode** has the **retain** property, this node will not be unmounted.
|
323
321
|
|
324
|
-
|
325
322
|
```jsx
|
326
|
-
import
|
323
|
+
import {
|
324
|
+
Flower,
|
327
325
|
FlowerAction,
|
328
326
|
FlowerNavigate,
|
329
327
|
FlowerNode,
|
330
|
-
useFlower
|
331
|
-
} from
|
332
|
-
import { memo, useEffect } from
|
328
|
+
useFlower
|
329
|
+
} from '@flowerforce/flower-react'
|
330
|
+
import { memo, useEffect } from 'react'
|
333
331
|
|
334
|
-
const ComponentAction = memo(
|
335
|
-
()
|
336
|
-
const { next } = useFlower();
|
332
|
+
const ComponentAction = memo(() => {
|
333
|
+
const { next } = useFlower()
|
337
334
|
|
338
|
-
|
339
|
-
|
335
|
+
useEffect(() => {
|
336
|
+
// * do your staff here - api call etc **
|
340
337
|
|
341
|
-
|
342
|
-
|
338
|
+
next()
|
339
|
+
}, [next])
|
343
340
|
|
344
|
-
|
345
|
-
|
346
|
-
);
|
341
|
+
return <span className="loader"></span>
|
342
|
+
})
|
347
343
|
|
348
344
|
export default function App() {
|
349
345
|
return (
|
@@ -352,7 +348,7 @@ export default function App() {
|
|
352
348
|
<FlowerNode id="step1" to={{ step2: null }} retain>
|
353
349
|
...
|
354
350
|
<FlowerNavigate action="next">
|
355
|
-
|
351
|
+
<button>click me to go next</button>
|
356
352
|
</FlowerNavigate>
|
357
353
|
</FlowerNode>
|
358
354
|
|
@@ -366,16 +362,15 @@ export default function App() {
|
|
366
362
|
<FlowerNode id="success">
|
367
363
|
...
|
368
364
|
<FlowerNavigate action="back">
|
369
|
-
|
365
|
+
<button>click me to go back</button>
|
370
366
|
</FlowerNavigate>
|
371
367
|
</FlowerNode>
|
372
368
|
</Flower>
|
373
|
-
)
|
369
|
+
)
|
374
370
|
}
|
375
|
-
|
376
371
|
```
|
377
|
-
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-actionnode-forked-7cd68s)
|
378
372
|
|
373
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-actionnode-forked-7cd68s)
|
379
374
|
|
380
375
|
### Hook - useFlower
|
381
376
|
|
@@ -385,61 +380,65 @@ Here, we are using the useFlower hook to obtain some essential functions for nav
|
|
385
380
|
|
386
381
|
```jsx
|
387
382
|
import React from 'react'
|
388
|
-
import
|
383
|
+
import {
|
384
|
+
Flower,
|
385
|
+
FlowerRoute,
|
386
|
+
FlowerNavigate,
|
387
|
+
FlowerNode,
|
388
|
+
useFlower
|
389
|
+
} from '@flowerforce/flower-react'
|
389
390
|
|
390
391
|
const ButtonNext = () => {
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
<button onClick={() => next()}>click me to go next</button>
|
395
|
-
)
|
392
|
+
// useFlower get the context of the parent Flower
|
393
|
+
const { next, back, jump } = useFlower()
|
394
|
+
return <button onClick={() => next()}>click me to go next</button>
|
396
395
|
}
|
397
396
|
|
398
397
|
export const Page = () => {
|
399
398
|
return (
|
400
399
|
<Flower name="demo">
|
401
400
|
<FlowerRoute id="start" to={{ step1: null }} />
|
402
|
-
|
403
|
-
<FlowerNode id="step1"
|
404
|
-
to={{ step2: null }}>
|
405
|
-
...
|
406
401
|
|
402
|
+
<FlowerNode id="step1" to={{ step2: null }}>
|
403
|
+
...
|
407
404
|
<ButtonNext />
|
408
405
|
</FlowerNode>
|
409
406
|
|
410
|
-
<FlowerNode id="step2">
|
411
|
-
...
|
412
|
-
</FlowerNode>
|
407
|
+
<FlowerNode id="step2">...</FlowerNode>
|
413
408
|
</Flower>
|
414
409
|
)
|
415
410
|
}
|
416
|
-
|
417
411
|
```
|
418
|
-
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-6wj3l9)
|
419
412
|
|
413
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-6wj3l9)
|
420
414
|
|
421
415
|
#### External use
|
416
|
+
|
422
417
|
```jsx
|
423
418
|
import React from 'react'
|
424
|
-
import
|
419
|
+
import {
|
420
|
+
Flower,
|
421
|
+
FlowerRoute,
|
422
|
+
FlowerNavigate,
|
423
|
+
FlowerNode,
|
424
|
+
useFlower
|
425
|
+
} from '@flowerforce/flower-react'
|
425
426
|
|
426
427
|
export const Page = () => {
|
427
|
-
// useFlower in external usage need to know context passing flowName
|
428
|
-
const { next, back, jump } = useFlower({ flowName:
|
428
|
+
// useFlower in external usage need to know context passing flowName
|
429
|
+
const { next, back, jump } = useFlower({ flowName: 'demo' })
|
429
430
|
|
430
431
|
return (
|
431
432
|
<>
|
432
433
|
<button onClick={() => next()}>click me and go next</button>
|
433
434
|
|
434
|
-
<Flower name="demo">
|
435
|
-
...
|
436
|
-
</Flower>
|
435
|
+
<Flower name="demo">...</Flower>
|
437
436
|
</>
|
438
437
|
)
|
439
438
|
}
|
440
|
-
|
441
439
|
```
|
442
|
-
|
440
|
+
|
441
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-jk86mh)
|
443
442
|
|
444
443
|
### Utils Callback onEnter - onExit
|
445
444
|
|
@@ -449,39 +448,40 @@ onExit (function): A callback function that is executed when exiting the node st
|
|
449
448
|
|
450
449
|
```jsx
|
451
450
|
import React from 'react'
|
452
|
-
import
|
451
|
+
import {
|
452
|
+
Flower,
|
453
|
+
FlowerRoute,
|
454
|
+
FlowerNavigate,
|
455
|
+
FlowerNode
|
456
|
+
} from '@flowerforce/flower-react'
|
453
457
|
|
454
458
|
export const Page = () => {
|
455
459
|
return (
|
456
460
|
<Flower name="demo">
|
457
461
|
<FlowerRoute id="start" to={{ step1: null }} />
|
458
|
-
|
459
|
-
<FlowerNode id="step1"
|
460
|
-
to={{ step2: null }}
|
461
462
|
|
463
|
+
<FlowerNode
|
464
|
+
id="step1"
|
465
|
+
to={{ step2: null }}
|
462
466
|
// On mount component
|
463
|
-
onEnter={() => console.log(
|
464
|
-
|
467
|
+
onEnter={() => console.log('enter on step1')}
|
465
468
|
// On unmount component
|
466
|
-
onExit={() => console.log(
|
467
|
-
|
469
|
+
onExit={() => console.log('exit from step1')}
|
470
|
+
>
|
468
471
|
...
|
469
|
-
|
470
472
|
<FlowerNavigate action="next">
|
471
473
|
<button>click me to go next</button>
|
472
474
|
</FlowerNavigate>
|
473
475
|
</FlowerNode>
|
474
476
|
|
475
|
-
<FlowerNode id="step2">
|
476
|
-
...
|
477
|
-
</FlowerNode>
|
477
|
+
<FlowerNode id="step2">...</FlowerNode>
|
478
478
|
</Flower>
|
479
479
|
)
|
480
480
|
}
|
481
|
-
|
482
481
|
```
|
483
482
|
|
484
483
|
## Form
|
484
|
+
|
485
485
|
Flower enables the quick creation of forms.
|
486
486
|
|
487
487
|
It keeps track of the form's validity status. This status not only facilitates displaying error messages to the user but can also be leveraged for implementing flow rules.
|
@@ -489,40 +489,41 @@ It keeps track of the form's validity status. This status not only facilitates d
|
|
489
489
|
### Basic Usage
|
490
490
|
|
491
491
|
```jsx
|
492
|
-
import
|
492
|
+
import {
|
493
|
+
Flower,
|
493
494
|
FlowerNavigate,
|
494
495
|
FlowerNode,
|
495
496
|
FlowerField,
|
496
497
|
FlowerAction,
|
497
498
|
useFlower,
|
498
|
-
useFlowerForm
|
499
|
-
} from
|
500
|
-
import { useEffect } from
|
501
|
-
import
|
499
|
+
useFlowerForm
|
500
|
+
} from '@flowerforce/flower-react'
|
501
|
+
import { useEffect } from 'react'
|
502
|
+
import './styles.css'
|
502
503
|
|
503
504
|
const ComponentAction = () => {
|
504
|
-
const { next } = useFlower()
|
505
|
-
const { getData } = useFlowerForm()
|
505
|
+
const { next } = useFlower()
|
506
|
+
const { getData } = useFlowerForm()
|
506
507
|
|
507
508
|
useEffect(() => {
|
508
509
|
// get form data
|
509
|
-
const formData = getData()
|
510
|
+
const formData = getData()
|
510
511
|
|
511
512
|
try {
|
512
513
|
// * do your staff here - api call etc **
|
513
514
|
// example setTimout to simulate delay api call
|
514
515
|
setTimeout(() => {
|
515
516
|
// navigate to success step
|
516
|
-
next(
|
517
|
-
}, 500)
|
517
|
+
next('onSuccess')
|
518
|
+
}, 500)
|
518
519
|
} catch (error) {
|
519
520
|
// navigate to error step
|
520
|
-
next(
|
521
|
+
next('onError')
|
521
522
|
}
|
522
|
-
}, [next, getData])
|
523
|
+
}, [next, getData])
|
523
524
|
|
524
|
-
return <span className="loader"></span
|
525
|
-
}
|
525
|
+
return <span className="loader"></span>
|
526
|
+
}
|
526
527
|
|
527
528
|
export default function App() {
|
528
529
|
return (
|
@@ -539,12 +540,12 @@ export default function App() {
|
|
539
540
|
validate={[
|
540
541
|
{
|
541
542
|
rules: { $and: [{ username: { $exists: true } }] },
|
542
|
-
message:
|
543
|
+
message: 'Field is required'
|
543
544
|
},
|
544
545
|
{
|
545
|
-
rules: { $and: [{ username: { $strGte:
|
546
|
-
message:
|
547
|
-
}
|
546
|
+
rules: { $and: [{ username: { $strGte: '6' } }] },
|
547
|
+
message: 'Field length must be greater than or equal to 6.'
|
548
|
+
}
|
548
549
|
]}
|
549
550
|
>
|
550
551
|
{({ onChange, value, errors }) => (
|
@@ -556,7 +557,7 @@ export default function App() {
|
|
556
557
|
placeholder="Username"
|
557
558
|
onChange={(e) => onChange(e.target.value)}
|
558
559
|
/>
|
559
|
-
{errors && <div className="error">{errors.join(
|
560
|
+
{errors && <div className="error">{errors.join(', ')}</div>}
|
560
561
|
</div>
|
561
562
|
)}
|
562
563
|
</FlowerField>
|
@@ -569,8 +570,8 @@ export default function App() {
|
|
569
570
|
validate={[
|
570
571
|
{
|
571
572
|
rules: { $and: [{ password: { $exists: true } }] },
|
572
|
-
message:
|
573
|
-
}
|
573
|
+
message: 'Field is required'
|
574
|
+
}
|
574
575
|
]}
|
575
576
|
>
|
576
577
|
{({ onChange, value, errors }) => (
|
@@ -582,7 +583,7 @@ export default function App() {
|
|
582
583
|
placeholder="Password"
|
583
584
|
onChange={(e) => onChange(e.target.value)}
|
584
585
|
/>
|
585
|
-
{errors && <div className="error">{errors.join(
|
586
|
+
{errors && <div className="error">{errors.join(', ')}</div>}
|
586
587
|
</>
|
587
588
|
)}
|
588
589
|
</FlowerField>
|
@@ -590,7 +591,7 @@ export default function App() {
|
|
590
591
|
|
591
592
|
<FlowerNavigate
|
592
593
|
action="next"
|
593
|
-
rules={{ $and: [{
|
594
|
+
rules={{ $and: [{ '$form.isValid': { $eq: true } }] }}
|
594
595
|
alwaysDisplay
|
595
596
|
>
|
596
597
|
{({ onClick, hidden }) => (
|
@@ -603,7 +604,7 @@ export default function App() {
|
|
603
604
|
</FlowerNode>
|
604
605
|
|
605
606
|
{/* step 2 */}
|
606
|
-
<FlowerAction id="step2" to={{ success:
|
607
|
+
<FlowerAction id="step2" to={{ success: 'onSuccess', error: 'onError' }}>
|
607
608
|
<div className="page step2">
|
608
609
|
<ComponentAction />
|
609
610
|
</div>
|
@@ -630,9 +631,8 @@ export default function App() {
|
|
630
631
|
</div>
|
631
632
|
</FlowerNode>
|
632
633
|
</Flower>
|
633
|
-
)
|
634
|
+
)
|
634
635
|
}
|
635
|
-
|
636
636
|
```
|
637
637
|
|
638
638
|
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-2f43gh)
|
@@ -664,8 +664,8 @@ The rules schema follows the MongoDB style, below is the list of available opera
|
|
664
664
|
Rules in $and | $or
|
665
665
|
|
666
666
|
```jsx
|
667
|
-
<FlowerNode id="node"
|
668
|
-
to={{
|
667
|
+
<FlowerNode id="node"
|
668
|
+
to={{
|
669
669
|
node2: {
|
670
670
|
rules: { $and: [
|
671
671
|
{ myValue: { $exists: true } },
|
@@ -677,8 +677,8 @@ Rules in $and | $or
|
|
677
677
|
...
|
678
678
|
</Flower>
|
679
679
|
|
680
|
-
<FlowerNode id="node"
|
681
|
-
to={{
|
680
|
+
<FlowerNode id="node"
|
681
|
+
to={{
|
682
682
|
node2: {
|
683
683
|
rules: { $or: [
|
684
684
|
{ myValue: { $exists: false } },
|
@@ -696,8 +696,8 @@ Compare state value, use '$ref:'
|
|
696
696
|
|
697
697
|
```jsx
|
698
698
|
<Flower name="demo" initialData={{ myValue1: 'test', myValue2: 'test2' }}>
|
699
|
-
<FlowerNode id="node"
|
700
|
-
to={{
|
699
|
+
<FlowerNode id="node"
|
700
|
+
to={{
|
701
701
|
node2: {
|
702
702
|
rules: [
|
703
703
|
{ myValue1: { $eq: '$ref:myValue2' } }
|
@@ -707,7 +707,6 @@ Compare state value, use '$ref:'
|
|
707
707
|
</Flower>
|
708
708
|
```
|
709
709
|
|
710
|
-
|
711
710
|
## Display Rules
|
712
711
|
|
713
712
|
Showing or Hiding Fields: You can use rules to show or hide specific fields based on user choices. For example, hiding a "Buttons" unless the user selects a certain option.
|
@@ -716,55 +715,51 @@ We can use the FlowerRule component to hide a part of the UI according to certai
|
|
716
715
|
|
717
716
|
If the "alwaysDisplay" property is passed, however, the component will not be automatically hidden, but a "hidden" property will be provided when the rules are not met.
|
718
717
|
|
719
|
-
### Example
|
718
|
+
### Example
|
720
719
|
|
721
720
|
```jsx
|
722
721
|
import React from 'react'
|
723
|
-
import
|
724
|
-
|
722
|
+
import {
|
723
|
+
Flower,
|
724
|
+
FlowerRoute,
|
725
|
+
FlowerNode,
|
726
|
+
FlowerRule,
|
727
|
+
FlowerNavigate
|
728
|
+
} from '@flowerforce/flower-react'
|
725
729
|
|
726
730
|
export const Page = () => {
|
727
731
|
return (
|
728
732
|
<Flower name="demo" initialData={{ enableNav: true }}>
|
729
|
-
<FlowerNode id="step1"
|
730
|
-
to={{ step2: null }}>
|
733
|
+
<FlowerNode id="step1" to={{ step2: null }}>
|
731
734
|
...
|
732
|
-
|
733
|
-
|
734
|
-
<
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
>
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
<FlowerNavigate
|
753
|
-
action="reset"
|
754
|
-
rules={{ enableNav: { $eq: true } }}
|
755
|
-
>
|
756
|
-
<button>Reset</button>
|
757
|
-
</FlowerNavigate>
|
735
|
+
{/* show / hidden based on rule */}
|
736
|
+
<FlowerRule rules={{ enableNav: { $eq: true } }}>
|
737
|
+
<p>Buttons nav are enabled</p>
|
738
|
+
</FlowerRule>
|
739
|
+
{/* always visible component, hidden prop is true when rule is not matched */}
|
740
|
+
<FlowerNavigate
|
741
|
+
action="next"
|
742
|
+
rules={{ enableNav: { $eq: true } }}
|
743
|
+
alwaysDisplay
|
744
|
+
>
|
745
|
+
{({ onClick, hidden }) => (
|
746
|
+
<button disabled={hidden} onClick={onClick}>
|
747
|
+
Next →
|
748
|
+
</button>
|
749
|
+
)}
|
750
|
+
</FlowerNavigate>
|
751
|
+
{/* visible only when rule is matched */}
|
752
|
+
<FlowerNavigate action="reset" rules={{ enableNav: { $eq: true } }}>
|
753
|
+
<button>Reset</button>
|
754
|
+
</FlowerNavigate>
|
758
755
|
</FlowerNode>
|
759
|
-
|
760
756
|
...
|
761
757
|
</Flower>
|
762
758
|
)
|
763
759
|
}
|
764
|
-
|
765
760
|
```
|
766
|
-
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-sfn6ml)
|
767
761
|
|
762
|
+
Edit on [codesandbox/](https://codesandbox.io/p/sandbox/flower-react-example-1-forked-sfn6ml)
|
768
763
|
|
769
764
|
# Documentation
|
770
765
|
|
package/dist/index.cjs.js
CHANGED
@@ -227,8 +227,9 @@ const FlowerClient = ({
|
|
227
227
|
}, [dispatch, flowName, current, isDisabled, store, wsDevtools, isInitialized]);
|
228
228
|
const contextValues = React.useMemo(() => ({
|
229
229
|
flowName,
|
230
|
+
initialData: _initialData,
|
230
231
|
currentNode: current
|
231
|
-
}), [flowName, current]);
|
232
|
+
}), [flowName, _initialData, current]);
|
232
233
|
return isInitialized ? ( /*#__PURE__*/React.createElement(Provider, {
|
233
234
|
value: contextValues
|
234
235
|
}, prevFlowerNodeId !== current && typeof prevFlowerNodeId === 'string' && nodeById[prevFlowerNodeId], !isDisabled && nodeById[current])) : null;
|
@@ -351,29 +352,22 @@ const component$6 = /*#__PURE__*/React.memo(FlowerRoute);
|
|
351
352
|
component$6.displayName = 'FlowerRoute';
|
352
353
|
|
353
354
|
function _extends() {
|
354
|
-
_extends = Object.assign ? Object.assign.bind() : function (
|
355
|
-
for (var
|
356
|
-
var
|
357
|
-
for (var
|
358
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
359
|
-
target[key] = source[key];
|
360
|
-
}
|
361
|
-
}
|
355
|
+
return _extends = Object.assign ? Object.assign.bind() : function (n) {
|
356
|
+
for (var e = 1; e < arguments.length; e++) {
|
357
|
+
var t = arguments[e];
|
358
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
362
359
|
}
|
363
|
-
return
|
364
|
-
};
|
365
|
-
return _extends.apply(this, arguments);
|
360
|
+
return n;
|
361
|
+
}, _extends.apply(null, arguments);
|
366
362
|
}
|
367
|
-
function _objectWithoutPropertiesLoose(
|
368
|
-
if (
|
369
|
-
var
|
370
|
-
for (var
|
371
|
-
if (
|
372
|
-
|
373
|
-
target[key] = source[key];
|
374
|
-
}
|
363
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
364
|
+
if (null == r) return {};
|
365
|
+
var t = {};
|
366
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
367
|
+
if (e.indexOf(n) >= 0) continue;
|
368
|
+
t[n] = r[n];
|
375
369
|
}
|
376
|
-
return
|
370
|
+
return t;
|
377
371
|
}
|
378
372
|
|
379
373
|
const FlowerRule = ({
|
@@ -789,15 +783,17 @@ component$3.displayName = 'FlowerValue';
|
|
789
783
|
|
790
784
|
const ACTION_TYPES = {
|
791
785
|
back: ['prev', 'prevToNode'],
|
792
|
-
reset: ['reset', 'initializeFromNode'],
|
793
786
|
jump: ['node', 'node'],
|
794
|
-
next: ['next', 'next']
|
787
|
+
next: ['next', 'next'],
|
788
|
+
restart: ['restart', 'restart'],
|
789
|
+
reset: ['reset', 'initializeFromNode']
|
795
790
|
};
|
796
791
|
const PAYLAOAD_KEYS_NEEDED = {
|
797
792
|
back: ['node'],
|
798
|
-
reset: ['node'],
|
799
793
|
jump: ['node', 'history'],
|
800
|
-
next: ['node', 'route', 'data']
|
794
|
+
next: ['node', 'route', 'data'],
|
795
|
+
restart: ['node'],
|
796
|
+
reset: ['node', 'initialData']
|
801
797
|
};
|
802
798
|
const makeActionPayload = (actions, keys) => (flowName, params) => {
|
803
799
|
const rest = typeof params === 'string' ? {
|
@@ -816,13 +812,15 @@ const makeActionPayloadOnPrev = makeActionPayload(ACTION_TYPES.back, PAYLAOAD_KE
|
|
816
812
|
const makeActionPayloadOnReset = makeActionPayload(ACTION_TYPES.reset, PAYLAOAD_KEYS_NEEDED.reset);
|
817
813
|
const makeActionPayloadOnNode = makeActionPayload(ACTION_TYPES.jump, PAYLAOAD_KEYS_NEEDED.jump);
|
818
814
|
const makeActionPayloadOnNext = makeActionPayload(ACTION_TYPES.next, PAYLAOAD_KEYS_NEEDED.next);
|
815
|
+
const makeActionPayloadOnRestart = makeActionPayload(ACTION_TYPES.restart, PAYLAOAD_KEYS_NEEDED.restart);
|
819
816
|
const useFlower = ({
|
820
817
|
flowName: customFlowName,
|
821
818
|
name
|
822
819
|
} = {}) => {
|
823
820
|
const dispatch = useDispatch();
|
824
821
|
const {
|
825
|
-
flowName: flowNameDefault
|
822
|
+
flowName: flowNameDefault,
|
823
|
+
initialData
|
826
824
|
} = React.useContext(context);
|
827
825
|
const flowName = customFlowName || name || flowNameDefault;
|
828
826
|
const nodeId = useSelector(makeSelectCurrentNodeId(flowName != null ? flowName : ''));
|
@@ -860,11 +858,11 @@ const useFlower = ({
|
|
860
858
|
payload
|
861
859
|
});
|
862
860
|
}, [dispatch, emitNavigateEvent, flowName]);
|
863
|
-
const
|
861
|
+
const restart = React.useCallback(param => {
|
864
862
|
const {
|
865
863
|
type,
|
866
864
|
payload
|
867
|
-
} =
|
865
|
+
} = makeActionPayloadOnRestart(flowName, param);
|
868
866
|
dispatch({
|
869
867
|
type: `flower/${type}`,
|
870
868
|
payload
|
@@ -874,6 +872,25 @@ const useFlower = ({
|
|
874
872
|
payload
|
875
873
|
});
|
876
874
|
}, [dispatch, emitNavigateEvent, flowName]);
|
875
|
+
const reset = React.useCallback(param => {
|
876
|
+
const {
|
877
|
+
type,
|
878
|
+
payload
|
879
|
+
} = makeActionPayloadOnReset(flowName, typeof param === 'string' ? {
|
880
|
+
node: param,
|
881
|
+
initialData
|
882
|
+
} : _extends({}, param, {
|
883
|
+
initialData
|
884
|
+
}));
|
885
|
+
dispatch({
|
886
|
+
type: `flower/${type}`,
|
887
|
+
payload
|
888
|
+
});
|
889
|
+
emitNavigateEvent({
|
890
|
+
type,
|
891
|
+
payload
|
892
|
+
});
|
893
|
+
}, [dispatch, emitNavigateEvent, flowName, initialData]);
|
877
894
|
const jump = React.useCallback(param => {
|
878
895
|
const {
|
879
896
|
type,
|
@@ -894,7 +911,8 @@ const useFlower = ({
|
|
894
911
|
next,
|
895
912
|
jump,
|
896
913
|
back,
|
897
|
-
reset
|
914
|
+
reset,
|
915
|
+
restart
|
898
916
|
};
|
899
917
|
};
|
900
918
|
|
@@ -912,7 +930,8 @@ const useFlowerNavigate = ({
|
|
912
930
|
next,
|
913
931
|
jump,
|
914
932
|
back,
|
915
|
-
reset
|
933
|
+
reset,
|
934
|
+
restart
|
916
935
|
} = useFlower({
|
917
936
|
flowName: name
|
918
937
|
});
|
@@ -930,11 +949,14 @@ const useFlowerNavigate = ({
|
|
930
949
|
case 'reset':
|
931
950
|
reset(node);
|
932
951
|
return;
|
952
|
+
case 'restart':
|
953
|
+
restart(node);
|
954
|
+
return;
|
933
955
|
default:
|
934
956
|
next();
|
935
957
|
return;
|
936
958
|
}
|
937
|
-
}, [next, jump, back, reset, node, route]);
|
959
|
+
}, [next, jump, back, reset, restart, node, route]);
|
938
960
|
return {
|
939
961
|
onNavigate,
|
940
962
|
flowName
|
package/dist/index.esm.js
CHANGED
@@ -225,8 +225,9 @@ const FlowerClient = ({
|
|
225
225
|
}, [dispatch, flowName, current, isDisabled, store, wsDevtools, isInitialized]);
|
226
226
|
const contextValues = useMemo(() => ({
|
227
227
|
flowName,
|
228
|
+
initialData: _initialData,
|
228
229
|
currentNode: current
|
229
|
-
}), [flowName, current]);
|
230
|
+
}), [flowName, _initialData, current]);
|
230
231
|
return isInitialized ? ( /*#__PURE__*/React.createElement(Provider, {
|
231
232
|
value: contextValues
|
232
233
|
}, prevFlowerNodeId !== current && typeof prevFlowerNodeId === 'string' && nodeById[prevFlowerNodeId], !isDisabled && nodeById[current])) : null;
|
@@ -349,29 +350,22 @@ const component$6 = /*#__PURE__*/React.memo(FlowerRoute);
|
|
349
350
|
component$6.displayName = 'FlowerRoute';
|
350
351
|
|
351
352
|
function _extends() {
|
352
|
-
_extends = Object.assign ? Object.assign.bind() : function (
|
353
|
-
for (var
|
354
|
-
var
|
355
|
-
for (var
|
356
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
357
|
-
target[key] = source[key];
|
358
|
-
}
|
359
|
-
}
|
353
|
+
return _extends = Object.assign ? Object.assign.bind() : function (n) {
|
354
|
+
for (var e = 1; e < arguments.length; e++) {
|
355
|
+
var t = arguments[e];
|
356
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
360
357
|
}
|
361
|
-
return
|
362
|
-
};
|
363
|
-
return _extends.apply(this, arguments);
|
358
|
+
return n;
|
359
|
+
}, _extends.apply(null, arguments);
|
364
360
|
}
|
365
|
-
function _objectWithoutPropertiesLoose(
|
366
|
-
if (
|
367
|
-
var
|
368
|
-
for (var
|
369
|
-
if (
|
370
|
-
|
371
|
-
target[key] = source[key];
|
372
|
-
}
|
361
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
362
|
+
if (null == r) return {};
|
363
|
+
var t = {};
|
364
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
365
|
+
if (e.indexOf(n) >= 0) continue;
|
366
|
+
t[n] = r[n];
|
373
367
|
}
|
374
|
-
return
|
368
|
+
return t;
|
375
369
|
}
|
376
370
|
|
377
371
|
const FlowerRule = ({
|
@@ -787,15 +781,17 @@ component$3.displayName = 'FlowerValue';
|
|
787
781
|
|
788
782
|
const ACTION_TYPES = {
|
789
783
|
back: ['prev', 'prevToNode'],
|
790
|
-
reset: ['reset', 'initializeFromNode'],
|
791
784
|
jump: ['node', 'node'],
|
792
|
-
next: ['next', 'next']
|
785
|
+
next: ['next', 'next'],
|
786
|
+
restart: ['restart', 'restart'],
|
787
|
+
reset: ['reset', 'initializeFromNode']
|
793
788
|
};
|
794
789
|
const PAYLAOAD_KEYS_NEEDED = {
|
795
790
|
back: ['node'],
|
796
|
-
reset: ['node'],
|
797
791
|
jump: ['node', 'history'],
|
798
|
-
next: ['node', 'route', 'data']
|
792
|
+
next: ['node', 'route', 'data'],
|
793
|
+
restart: ['node'],
|
794
|
+
reset: ['node', 'initialData']
|
799
795
|
};
|
800
796
|
const makeActionPayload = (actions, keys) => (flowName, params) => {
|
801
797
|
const rest = typeof params === 'string' ? {
|
@@ -814,13 +810,15 @@ const makeActionPayloadOnPrev = makeActionPayload(ACTION_TYPES.back, PAYLAOAD_KE
|
|
814
810
|
const makeActionPayloadOnReset = makeActionPayload(ACTION_TYPES.reset, PAYLAOAD_KEYS_NEEDED.reset);
|
815
811
|
const makeActionPayloadOnNode = makeActionPayload(ACTION_TYPES.jump, PAYLAOAD_KEYS_NEEDED.jump);
|
816
812
|
const makeActionPayloadOnNext = makeActionPayload(ACTION_TYPES.next, PAYLAOAD_KEYS_NEEDED.next);
|
813
|
+
const makeActionPayloadOnRestart = makeActionPayload(ACTION_TYPES.restart, PAYLAOAD_KEYS_NEEDED.restart);
|
817
814
|
const useFlower = ({
|
818
815
|
flowName: customFlowName,
|
819
816
|
name
|
820
817
|
} = {}) => {
|
821
818
|
const dispatch = useDispatch();
|
822
819
|
const {
|
823
|
-
flowName: flowNameDefault
|
820
|
+
flowName: flowNameDefault,
|
821
|
+
initialData
|
824
822
|
} = useContext(context);
|
825
823
|
const flowName = customFlowName || name || flowNameDefault;
|
826
824
|
const nodeId = useSelector(makeSelectCurrentNodeId(flowName != null ? flowName : ''));
|
@@ -858,11 +856,11 @@ const useFlower = ({
|
|
858
856
|
payload
|
859
857
|
});
|
860
858
|
}, [dispatch, emitNavigateEvent, flowName]);
|
861
|
-
const
|
859
|
+
const restart = useCallback(param => {
|
862
860
|
const {
|
863
861
|
type,
|
864
862
|
payload
|
865
|
-
} =
|
863
|
+
} = makeActionPayloadOnRestart(flowName, param);
|
866
864
|
dispatch({
|
867
865
|
type: `flower/${type}`,
|
868
866
|
payload
|
@@ -872,6 +870,25 @@ const useFlower = ({
|
|
872
870
|
payload
|
873
871
|
});
|
874
872
|
}, [dispatch, emitNavigateEvent, flowName]);
|
873
|
+
const reset = useCallback(param => {
|
874
|
+
const {
|
875
|
+
type,
|
876
|
+
payload
|
877
|
+
} = makeActionPayloadOnReset(flowName, typeof param === 'string' ? {
|
878
|
+
node: param,
|
879
|
+
initialData
|
880
|
+
} : _extends({}, param, {
|
881
|
+
initialData
|
882
|
+
}));
|
883
|
+
dispatch({
|
884
|
+
type: `flower/${type}`,
|
885
|
+
payload
|
886
|
+
});
|
887
|
+
emitNavigateEvent({
|
888
|
+
type,
|
889
|
+
payload
|
890
|
+
});
|
891
|
+
}, [dispatch, emitNavigateEvent, flowName, initialData]);
|
875
892
|
const jump = useCallback(param => {
|
876
893
|
const {
|
877
894
|
type,
|
@@ -892,7 +909,8 @@ const useFlower = ({
|
|
892
909
|
next,
|
893
910
|
jump,
|
894
911
|
back,
|
895
|
-
reset
|
912
|
+
reset,
|
913
|
+
restart
|
896
914
|
};
|
897
915
|
};
|
898
916
|
|
@@ -910,7 +928,8 @@ const useFlowerNavigate = ({
|
|
910
928
|
next,
|
911
929
|
jump,
|
912
930
|
back,
|
913
|
-
reset
|
931
|
+
reset,
|
932
|
+
restart
|
914
933
|
} = useFlower({
|
915
934
|
flowName: name
|
916
935
|
});
|
@@ -928,11 +947,14 @@ const useFlowerNavigate = ({
|
|
928
947
|
case 'reset':
|
929
948
|
reset(node);
|
930
949
|
return;
|
950
|
+
case 'restart':
|
951
|
+
restart(node);
|
952
|
+
return;
|
931
953
|
default:
|
932
954
|
next();
|
933
955
|
return;
|
934
956
|
}
|
935
|
-
}, [next, jump, back, reset, node, route]);
|
957
|
+
}, [next, jump, back, reset, restart, node, route]);
|
936
958
|
return {
|
937
959
|
onNavigate,
|
938
960
|
flowName
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { RulesObject } from '@flowerforce/flower-core';
|
2
|
-
export type FlowerFieldProps<T extends Record<string, any>> = {
|
2
|
+
export type FlowerFieldProps<T extends Record<string, any> = Record<string, any>> = {
|
3
3
|
id?: string;
|
4
4
|
children: React.ReactNode | ((props: {
|
5
5
|
id: string;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Route, RouteNode, RoutePrev, RouteReset } from './FlowerNavigate';
|
1
|
+
import { Route, RouteNode, RoutePrev, RouteReset, RouteRestart } from './FlowerNavigate';
|
2
2
|
export type UseFlowerProps = {
|
3
3
|
[x in 'name' | 'flowName']?: string;
|
4
4
|
};
|
@@ -17,6 +17,7 @@ type useFlowerActions = {
|
|
17
17
|
back: (payload?: RoutePrev) => void;
|
18
18
|
reset: (payload?: RouteReset) => void;
|
19
19
|
jump: (payload: RouteNode) => void;
|
20
|
+
restart: (payload?: RouteRestart) => void;
|
20
21
|
};
|
21
22
|
export type UseFlower = (options?: UseFlowerProps) => useFlowerActions & {
|
22
23
|
flowName?: string;
|
@@ -5,9 +5,14 @@ export type RouteNode = string | {
|
|
5
5
|
flowName?: string;
|
6
6
|
history?: string[];
|
7
7
|
};
|
8
|
+
export type RouteRestart = string | {
|
9
|
+
node: string;
|
10
|
+
flowName?: string;
|
11
|
+
};
|
8
12
|
export type RouteReset = string | {
|
9
13
|
node: string;
|
10
14
|
flowName?: string;
|
15
|
+
initialData?: Record<string, any>;
|
11
16
|
};
|
12
17
|
export type RoutePrev = string | {
|
13
18
|
node: string;
|
@@ -34,4 +39,8 @@ export type FlowerNavigateProps = {
|
|
34
39
|
action?: 'jump';
|
35
40
|
node?: RouteNode;
|
36
41
|
route?: undefined;
|
42
|
+
} | {
|
43
|
+
action?: 'restart';
|
44
|
+
node?: RouteRestart;
|
45
|
+
route?: undefined;
|
37
46
|
});
|
package/dist/src/context.d.ts
CHANGED
@@ -3,6 +3,7 @@ export type FlowerContext = {
|
|
3
3
|
flowName?: string | undefined;
|
4
4
|
currentNode?: string | undefined;
|
5
5
|
autostart?: boolean | undefined;
|
6
|
+
initialData?: Record<string, any>;
|
6
7
|
};
|
7
8
|
export declare const context: React.Context<FlowerContext>;
|
8
9
|
export declare const Provider: React.Provider<FlowerContext>;
|
package/dist/src/index.d.ts
CHANGED
@@ -18,3 +18,16 @@ export { default as useFlowerForm } from './components/useFlowerForm';
|
|
18
18
|
export { default as FlowerProvider } from './provider';
|
19
19
|
export { getDataByFlow } from './selectors';
|
20
20
|
export { useSelector } from './provider';
|
21
|
+
export type { FlowerContext as FlowerContextProps } from './context';
|
22
|
+
export type { FlowerNodeDefaultProps } from './components/types/DefaultNode';
|
23
|
+
export type { FlowerComponentProps } from './components/types/FlowerComponent';
|
24
|
+
export type { FlowerFieldProps } from './components/types/FlowerField';
|
25
|
+
export type { FlowerFlowProps } from './components/types/FlowerFlow';
|
26
|
+
export type { UseFlower, UseFlowerForm, UseFlowerProps, NavigateFunctionParams } from './components/types/FlowerHooks';
|
27
|
+
export type { RouteReset, RoutePrev, RouteNode, Route, FlowerNavigateProps } from './components/types/FlowerNavigate';
|
28
|
+
export type { FlowerNodeProps } from './components/types/FlowerNode';
|
29
|
+
export type { FlowerProviderProps } from './components/types/FlowerProvider';
|
30
|
+
export type { FlowerRouteProps } from './components/types/FlowerRoute';
|
31
|
+
export type { FlowerRuleProps } from './components/types/FlowerRule';
|
32
|
+
export type { FlowerServerProps } from './components/types/FlowerServer';
|
33
|
+
export type { FlowerValueProps } from './components/types/FlowerValue';
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@flowerforce/flower-react",
|
3
|
-
"version": "3.0.1-beta.
|
3
|
+
"version": "3.0.1-beta.2",
|
4
4
|
"description": "FlowerJS components, hooks and utils for React.",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -22,8 +22,7 @@
|
|
22
22
|
},
|
23
23
|
"license": "ISC",
|
24
24
|
"peerDependencies": {
|
25
|
-
"react": ">=18"
|
26
|
-
"react-dom": ">=18"
|
25
|
+
"react": ">=18"
|
27
26
|
},
|
28
27
|
"devDependencies": {
|
29
28
|
"@testing-library/jest-dom": "^6.4.5",
|
@@ -35,7 +34,7 @@
|
|
35
34
|
"typescript": "^5.4.5"
|
36
35
|
},
|
37
36
|
"dependencies": {
|
38
|
-
"@flowerforce/flower-core": "3.0.
|
37
|
+
"@flowerforce/flower-core": "3.0.0",
|
39
38
|
"@reduxjs/toolkit": "^2.2.4",
|
40
39
|
"lodash": "^4.17.21",
|
41
40
|
"react-redux": "^9.1.2",
|
@@ -50,5 +49,6 @@
|
|
50
49
|
}
|
51
50
|
},
|
52
51
|
"module": "./dist/index.esm.js",
|
53
|
-
"main": "./dist/index.cjs.js"
|
52
|
+
"main": "./dist/index.cjs.js",
|
53
|
+
"types": "./dist/src/index.d.ts"
|
54
54
|
}
|