@jsenv/navi 0.6.2 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,7 @@ import { FormActionContext } from "../action_execution/form_context.js";
14
14
  import { renderActionableComponent } from "../action_execution/render_actionable_component.jsx";
15
15
  import { useAction } from "../action_execution/use_action.js";
16
16
  import { useExecuteAction } from "../action_execution/use_execute_action.js";
17
+ import { useConsumAlignProps } from "../layout/flex.jsx";
17
18
  import { consumeSpacingProps } from "../layout/spacing.jsx";
18
19
  import { LoaderBackground } from "../loader/loader_background.jsx";
19
20
  import { withPropsClassName } from "../props_composition/with_props_class_name.js";
@@ -211,7 +212,8 @@ const ButtonBasic = forwardRef((props, ref) => {
211
212
 
212
213
  // visual
213
214
  appearance = "navi",
214
- alignX = "start",
215
+ alignX,
216
+ alignY,
215
217
  discrete,
216
218
  className,
217
219
  style,
@@ -243,18 +245,7 @@ const ButtonBasic = forwardRef((props, ref) => {
243
245
  const innerStyle = withPropsStyle(
244
246
  {
245
247
  ...consumeSpacingProps(rest),
246
- ...(alignX === "start"
247
- ? {}
248
- : alignX === "center"
249
- ? {
250
- alignSelf: "center",
251
- marginLeft: "auto",
252
- marginRight: "auto",
253
- }
254
- : {
255
- alignSelf: "end",
256
- marginLeft: "auto",
257
- }),
248
+ ...useConsumAlignProps({ alignX, alignY }),
258
249
  },
259
250
  style,
260
251
  );
@@ -121,6 +121,7 @@ const FormWithAction = forwardRef((props, ref) => {
121
121
  action,
122
122
  method,
123
123
  actionErrorEffect = "show_validation_message", // "show_validation_message" or "throw"
124
+ errorMapping,
124
125
  onActionPrevented,
125
126
  onActionStart,
126
127
  onActionAbort,
@@ -135,6 +136,7 @@ const FormWithAction = forwardRef((props, ref) => {
135
136
  const [actionBoundToUIState] = useActionBoundToOneParam(action, uiState);
136
137
  const executeAction = useExecuteAction(innerRef, {
137
138
  errorEffect: actionErrorEffect,
139
+ errorMapping,
138
140
  });
139
141
  const { actionPending, actionRequester: formActionRequester } =
140
142
  useRequestedActionStatus(innerRef);
@@ -0,0 +1,506 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Flex Layout Demo</title>
6
+ <style>
7
+ .demo-box {
8
+ min-width: 60px;
9
+ padding: 10px;
10
+ text-align: center;
11
+ background: #e3f2fd;
12
+ border: 1px solid #90caf9;
13
+ border-radius: 4px;
14
+ }
15
+ .demo-section {
16
+ margin-bottom: 30px;
17
+ padding: 20px;
18
+ background: #f8f9fa;
19
+ border-radius: 8px;
20
+ }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <div id="app"></div>
25
+ <script type="module" jsenv-type="module/jsx">
26
+ /* eslint-disable no-unused-vars */
27
+ import { render } from "preact";
28
+ import { FlexRow, FlexColumn, FlexItem, Button } from "@jsenv/navi";
29
+
30
+ const DemoBox = ({ children, ...props }) => (
31
+ <div className="demo-box" {...props}>
32
+ {children}
33
+ </div>
34
+ );
35
+
36
+ const Demo = () => {
37
+ return (
38
+ <div style={{ padding: "20px", fontFamily: "system-ui, sans-serif" }}>
39
+ <h1>Flex Layout Demo</h1>
40
+
41
+ <h2>FlexRow</h2>
42
+
43
+ <section className="demo-section">
44
+ <h3>1. Basic FlexRow</h3>
45
+ <FlexRow>
46
+ <DemoBox>Item 1</DemoBox>
47
+ <DemoBox>Item 2</DemoBox>
48
+ <DemoBox>Item 3</DemoBox>
49
+ </FlexRow>
50
+ </section>
51
+
52
+ <section className="demo-section">
53
+ <h3>2. FlexRow with Gap</h3>
54
+ <FlexRow gap="15px">
55
+ <DemoBox>Item 1</DemoBox>
56
+ <DemoBox>Item 2</DemoBox>
57
+ <DemoBox>Item 3</DemoBox>
58
+ </FlexRow>
59
+ </section>
60
+
61
+ <section className="demo-section">
62
+ <h3>3. FlexRow with Vertical Alignment</h3>
63
+
64
+ <h4>alignY="start"</h4>
65
+ <FlexRow
66
+ alignY="start"
67
+ gap="10px"
68
+ style={{
69
+ height: "80px",
70
+ background: "#fff3e0",
71
+ padding: "10px",
72
+ }}
73
+ >
74
+ <DemoBox>Short</DemoBox>
75
+ <DemoBox style={{ height: "60px", lineHeight: "60px" }}>
76
+ Tall Item
77
+ </DemoBox>
78
+ <DemoBox>Short</DemoBox>
79
+ </FlexRow>
80
+
81
+ <h4>alignY="center" (default)</h4>
82
+ <FlexRow
83
+ alignY="center"
84
+ gap="10px"
85
+ style={{
86
+ height: "80px",
87
+ background: "#e8f5e8",
88
+ padding: "10px",
89
+ }}
90
+ >
91
+ <DemoBox>Short</DemoBox>
92
+ <DemoBox style={{ height: "60px", lineHeight: "60px" }}>
93
+ Tall Item
94
+ </DemoBox>
95
+ <DemoBox>Short</DemoBox>
96
+ </FlexRow>
97
+
98
+ <h4>alignY="end"</h4>
99
+ <FlexRow
100
+ alignY="end"
101
+ gap="10px"
102
+ style={{
103
+ height: "80px",
104
+ background: "#ffebee",
105
+ padding: "10px",
106
+ }}
107
+ >
108
+ <DemoBox>Short</DemoBox>
109
+ <DemoBox style={{ height: "60px", lineHeight: "60px" }}>
110
+ Tall Item
111
+ </DemoBox>
112
+ <DemoBox>Short</DemoBox>
113
+ </FlexRow>
114
+ </section>
115
+
116
+ <h2>FlexRow + FlexItem</h2>
117
+
118
+ <section className="demo-section">
119
+ <h3>4. FlexItem Basic Usage</h3>
120
+
121
+ <FlexRow gap="10px">
122
+ <FlexItem>
123
+ <DemoBox>FlexItem 1</DemoBox>
124
+ </FlexItem>
125
+ <FlexItem>
126
+ <DemoBox>FlexItem 2</DemoBox>
127
+ </FlexItem>
128
+ <FlexItem>
129
+ <DemoBox>FlexItem 3</DemoBox>
130
+ </FlexItem>
131
+ </FlexRow>
132
+ </section>
133
+
134
+ <section className="demo-section">
135
+ <h3>5. FlexItem with Growth</h3>
136
+
137
+ <FlexRow gap="10px">
138
+ <FlexItem>
139
+ <DemoBox>Fixed</DemoBox>
140
+ </FlexItem>
141
+ <FlexItem grow>
142
+ <DemoBox>Grows to fill</DemoBox>
143
+ </FlexItem>
144
+ <FlexItem>
145
+ <DemoBox>Fixed</DemoBox>
146
+ </FlexItem>
147
+ </FlexRow>
148
+ </section>
149
+
150
+ <section className="demo-section">
151
+ <h3>6. FlexItem with alignY</h3>
152
+
153
+ <FlexRow
154
+ gap="10px"
155
+ style={{
156
+ height: "100px",
157
+ background: "#e1f5fe",
158
+ padding: "10px",
159
+ }}
160
+ >
161
+ <FlexItem>
162
+ <DemoBox>Default (center)</DemoBox>
163
+ </FlexItem>
164
+ <FlexItem alignY="start">
165
+ <DemoBox>alignY="start"</DemoBox>
166
+ </FlexItem>
167
+ <FlexItem alignY="end">
168
+ <DemoBox>alignY="end"</DemoBox>
169
+ </FlexItem>
170
+ <FlexItem alignY="stretch">
171
+ <DemoBox style={{ height: "100%" }}>alignY="stretch"</DemoBox>
172
+ </FlexItem>
173
+ </FlexRow>
174
+ </section>
175
+
176
+ <section className="demo-section">
177
+ <h3>7. FlexItem with alignX</h3>
178
+
179
+ <FlexRow
180
+ gap="10px"
181
+ style={{
182
+ background: "#f3e5f5",
183
+ padding: "10px",
184
+ }}
185
+ >
186
+ <FlexItem>
187
+ <DemoBox>Default</DemoBox>
188
+ </FlexItem>
189
+ <FlexItem alignX="start">
190
+ <DemoBox>alignX="start"</DemoBox>
191
+ </FlexItem>
192
+ <FlexItem alignX="center">
193
+ <DemoBox>alignX="center"</DemoBox>
194
+ </FlexItem>
195
+ <FlexItem alignX="end">
196
+ <DemoBox>alignX="end"</DemoBox>
197
+ </FlexItem>
198
+ </FlexRow>
199
+ </section>
200
+
201
+ <section className="demo-section">
202
+ <h3>8. Auto Margin Examples</h3>
203
+
204
+ <h4>Single item pushed to end</h4>
205
+ <FlexRow
206
+ gap="10px"
207
+ style={{ background: "#fff3e0", padding: "10px" }}
208
+ >
209
+ <DemoBox>Item 1</DemoBox>
210
+ <DemoBox>Item 2</DemoBox>
211
+ <FlexItem alignX="end">
212
+ <DemoBox>Pushed to end</DemoBox>
213
+ </FlexItem>
214
+ </FlexRow>
215
+
216
+ <h4>Single item centered</h4>
217
+ <FlexRow
218
+ gap="10px"
219
+ style={{ background: "#e8f5e8", padding: "10px" }}
220
+ >
221
+ <DemoBox>Item 1</DemoBox>
222
+ <FlexItem alignX="center">
223
+ <DemoBox>Centered</DemoBox>
224
+ </FlexItem>
225
+ <DemoBox>Item 3</DemoBox>
226
+ </FlexRow>
227
+
228
+ <h4>Multiple items pushed to end</h4>
229
+ <FlexRow
230
+ gap="10px"
231
+ style={{ background: "#f0f4ff", padding: "10px" }}
232
+ >
233
+ <DemoBox>Item 1</DemoBox>
234
+ <FlexItem alignX="end">
235
+ <DemoBox>Pushed A</DemoBox>
236
+ </FlexItem>
237
+ <FlexItem alignX="end">
238
+ <DemoBox>Pushed B</DemoBox>
239
+ </FlexItem>
240
+ <FlexItem alignX="end">
241
+ <DemoBox>Pushed C</DemoBox>
242
+ </FlexItem>
243
+ </FlexRow>
244
+
245
+ <h4>Multiple items with different alignments</h4>
246
+ <FlexRow
247
+ gap="10px"
248
+ style={{ background: "#ffebee", padding: "10px" }}
249
+ >
250
+ <FlexItem alignX="start">
251
+ <DemoBox>Start</DemoBox>
252
+ </FlexItem>
253
+ <DemoBox>Normal</DemoBox>
254
+ <FlexItem alignX="center">
255
+ <DemoBox>Center</DemoBox>
256
+ </FlexItem>
257
+ <DemoBox>Normal</DemoBox>
258
+ <FlexItem alignX="end">
259
+ <DemoBox>End</DemoBox>
260
+ </FlexItem>
261
+ </FlexRow>
262
+ </section>
263
+
264
+ <section className="demo-section">
265
+ <h3>9. Combined Growth and Alignment</h3>
266
+
267
+ <FlexRow
268
+ gap="10px"
269
+ style={{ background: "#e1f5fe", padding: "10px" }}
270
+ >
271
+ <DemoBox>Fixed</DemoBox>
272
+ <FlexItem grow>
273
+ <DemoBox>Grows</DemoBox>
274
+ </FlexItem>
275
+ <FlexItem alignX="end">
276
+ <DemoBox>Pushed to end</DemoBox>
277
+ </FlexItem>
278
+ </FlexRow>
279
+ </section>
280
+
281
+ <section className="demo-section">
282
+ <h3>10. Real-World Example: Button with alignX</h3>
283
+
284
+ <FlexRow
285
+ gap="10px"
286
+ style={{ background: "#f5f5f5", padding: "10px" }}
287
+ >
288
+ <DemoBox>Content</DemoBox>
289
+ <DemoBox>More content</DemoBox>
290
+ <Button alignX="end">Action Button</Button>
291
+ </FlexRow>
292
+ </section>
293
+
294
+ <h2>FlexColumn</h2>
295
+
296
+ <section className="demo-section">
297
+ <h3>10. Basic FlexColumn</h3>
298
+ <FlexColumn style={{ height: "200px" }}>
299
+ <DemoBox>Item 1</DemoBox>
300
+ <DemoBox>Item 2</DemoBox>
301
+ <DemoBox>Item 3</DemoBox>
302
+ </FlexColumn>
303
+ </section>
304
+
305
+ <section className="demo-section">
306
+ <h3>11. FlexColumn with Gap</h3>
307
+ <FlexColumn gap="15px" style={{ height: "200px" }}>
308
+ <DemoBox>Item 1</DemoBox>
309
+ <DemoBox>Item 2</DemoBox>
310
+ <DemoBox>Item 3</DemoBox>
311
+ </FlexColumn>
312
+ </section>
313
+
314
+ <section className="demo-section">
315
+ <h3>12. FlexColumn with Horizontal Alignment</h3>
316
+
317
+ <h4>alignX="start"</h4>
318
+ <FlexColumn
319
+ alignX="start"
320
+ gap="10px"
321
+ style={{
322
+ height: "150px",
323
+ width: "300px",
324
+ background: "#fff3e0",
325
+ padding: "10px",
326
+ }}
327
+ >
328
+ <DemoBox>Short</DemoBox>
329
+ <DemoBox style={{ width: "200px" }}>Wide Item</DemoBox>
330
+ <DemoBox>Short</DemoBox>
331
+ </FlexColumn>
332
+
333
+ <h4>alignX="center" (default)</h4>
334
+ <FlexColumn
335
+ alignX="center"
336
+ gap="10px"
337
+ style={{
338
+ height: "150px",
339
+ width: "300px",
340
+ background: "#e8f5e8",
341
+ padding: "10px",
342
+ }}
343
+ >
344
+ <DemoBox>Short</DemoBox>
345
+ <DemoBox style={{ width: "200px" }}>Wide Item</DemoBox>
346
+ <DemoBox>Short</DemoBox>
347
+ </FlexColumn>
348
+
349
+ <h4>alignX="end"</h4>
350
+ <FlexColumn
351
+ alignX="end"
352
+ gap="10px"
353
+ style={{
354
+ height: "150px",
355
+ width: "300px",
356
+ background: "#ffebee",
357
+ padding: "10px",
358
+ }}
359
+ >
360
+ <DemoBox>Short</DemoBox>
361
+ <DemoBox style={{ width: "200px" }}>Wide Item</DemoBox>
362
+ <DemoBox>Short</DemoBox>
363
+ </FlexColumn>
364
+ </section>
365
+
366
+ <section className="demo-section">
367
+ <h3>13. FlexItem with alignX in Column</h3>
368
+
369
+ <FlexColumn
370
+ gap="10px"
371
+ style={{
372
+ height: "200px",
373
+ width: "300px",
374
+ background: "#f3e5f5",
375
+ padding: "10px",
376
+ }}
377
+ >
378
+ <FlexItem>
379
+ <DemoBox>Default</DemoBox>
380
+ </FlexItem>
381
+ <FlexItem alignX="start">
382
+ <DemoBox>alignX="start"</DemoBox>
383
+ </FlexItem>
384
+ <FlexItem alignX="center">
385
+ <DemoBox>alignX="center"</DemoBox>
386
+ </FlexItem>
387
+ <FlexItem alignX="end">
388
+ <DemoBox>alignX="end"</DemoBox>
389
+ </FlexItem>
390
+ </FlexColumn>
391
+ </section>
392
+
393
+ <section className="demo-section">
394
+ <h3>14. FlexItem with alignY in Column</h3>
395
+
396
+ <FlexColumn
397
+ gap="10px"
398
+ style={{
399
+ height: "300px",
400
+ width: "200px",
401
+ background: "#e1f5fe",
402
+ padding: "10px",
403
+ }}
404
+ >
405
+ <FlexItem>
406
+ <DemoBox>Default</DemoBox>
407
+ </FlexItem>
408
+ <FlexItem alignY="start">
409
+ <DemoBox>alignY="start"</DemoBox>
410
+ </FlexItem>
411
+ <FlexItem alignY="center">
412
+ <DemoBox>alignY="center"</DemoBox>
413
+ </FlexItem>
414
+ <FlexItem alignY="end">
415
+ <DemoBox>alignY="end"</DemoBox>
416
+ </FlexItem>
417
+ </FlexColumn>
418
+ </section>
419
+
420
+ <section className="demo-section">
421
+ <h3>15. Column Auto Margin Examples</h3>
422
+
423
+ <h4>Single item pushed to bottom</h4>
424
+ <FlexColumn
425
+ gap="10px"
426
+ style={{
427
+ height: "200px",
428
+ background: "#fff3e0",
429
+ padding: "10px",
430
+ }}
431
+ >
432
+ <DemoBox>Item 1</DemoBox>
433
+ <DemoBox>Item 2</DemoBox>
434
+ <FlexItem alignY="end">
435
+ <DemoBox>Pushed to bottom</DemoBox>
436
+ </FlexItem>
437
+ </FlexColumn>
438
+
439
+ <h4>Multiple items pushed to bottom</h4>
440
+ <FlexColumn
441
+ gap="10px"
442
+ style={{
443
+ height: "250px",
444
+ background: "#f0f4ff",
445
+ padding: "10px",
446
+ }}
447
+ >
448
+ <DemoBox>Item 1</DemoBox>
449
+ <FlexItem alignY="end">
450
+ <DemoBox>Pushed A</DemoBox>
451
+ </FlexItem>
452
+ <FlexItem alignY="end">
453
+ <DemoBox>Pushed B</DemoBox>
454
+ </FlexItem>
455
+ <FlexItem alignY="end">
456
+ <DemoBox>Pushed C</DemoBox>
457
+ </FlexItem>
458
+ </FlexColumn>
459
+
460
+ <h4>Item centered vertically</h4>
461
+ <FlexColumn
462
+ gap="10px"
463
+ style={{
464
+ height: "200px",
465
+ background: "#e8f5e8",
466
+ padding: "10px",
467
+ }}
468
+ >
469
+ <DemoBox>Item 1</DemoBox>
470
+ <FlexItem alignY="center">
471
+ <DemoBox>Centered</DemoBox>
472
+ </FlexItem>
473
+ <DemoBox>Item 3</DemoBox>
474
+ </FlexColumn>
475
+ </section>
476
+
477
+ <section className="demo-section">
478
+ <h3>16. Combined Growth and Alignment in Column</h3>
479
+
480
+ <FlexColumn
481
+ gap="10px"
482
+ style={{
483
+ height: "250px",
484
+ background: "#e1f5fe",
485
+ padding: "10px",
486
+ }}
487
+ >
488
+ <DemoBox>Fixed</DemoBox>
489
+ <FlexItem grow>
490
+ <DemoBox style="height: 100%; box-sizing: border-box;">
491
+ Grows
492
+ </DemoBox>
493
+ </FlexItem>
494
+ <FlexItem alignY="end">
495
+ <DemoBox>Pushed to bottom</DemoBox>
496
+ </FlexItem>
497
+ </FlexColumn>
498
+ </section>
499
+ </div>
500
+ );
501
+ };
502
+
503
+ render(<Demo />, document.getElementById("app"));
504
+ </script>
505
+ </body>
506
+ </html>