@almadar/std 1.0.0

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 (78) hide show
  1. package/LICENSE +72 -0
  2. package/dist/behaviors/action-affinity.d.ts +88 -0
  3. package/dist/behaviors/action-affinity.js +290 -0
  4. package/dist/behaviors/action-affinity.js.map +1 -0
  5. package/dist/behaviors/async.d.ts +20 -0
  6. package/dist/behaviors/async.js +542 -0
  7. package/dist/behaviors/async.js.map +1 -0
  8. package/dist/behaviors/data-management.d.ts +40 -0
  9. package/dist/behaviors/data-management.js +495 -0
  10. package/dist/behaviors/data-management.js.map +1 -0
  11. package/dist/behaviors/feedback.d.ts +18 -0
  12. package/dist/behaviors/feedback.js +307 -0
  13. package/dist/behaviors/feedback.js.map +1 -0
  14. package/dist/behaviors/game-core.d.ts +40 -0
  15. package/dist/behaviors/game-core.js +443 -0
  16. package/dist/behaviors/game-core.js.map +1 -0
  17. package/dist/behaviors/game-entity.d.ts +39 -0
  18. package/dist/behaviors/game-entity.js +643 -0
  19. package/dist/behaviors/game-entity.js.map +1 -0
  20. package/dist/behaviors/game-ui.d.ts +29 -0
  21. package/dist/behaviors/game-ui.js +493 -0
  22. package/dist/behaviors/game-ui.js.map +1 -0
  23. package/dist/behaviors/index.d.ts +11 -0
  24. package/dist/behaviors/index.js +4539 -0
  25. package/dist/behaviors/index.js.map +1 -0
  26. package/dist/behaviors/registry.d.ts +103 -0
  27. package/dist/behaviors/registry.js +4166 -0
  28. package/dist/behaviors/registry.js.map +1 -0
  29. package/dist/behaviors/types.d.ts +179 -0
  30. package/dist/behaviors/types.js +111 -0
  31. package/dist/behaviors/types.js.map +1 -0
  32. package/dist/behaviors/ui-interaction.d.ts +36 -0
  33. package/dist/behaviors/ui-interaction.js +1104 -0
  34. package/dist/behaviors/ui-interaction.js.map +1 -0
  35. package/dist/index.d.ts +195 -0
  36. package/dist/index.js +8209 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/modules/array.d.ts +28 -0
  39. package/dist/modules/array.js +556 -0
  40. package/dist/modules/array.js.map +1 -0
  41. package/dist/modules/async.d.ts +22 -0
  42. package/dist/modules/async.js +112 -0
  43. package/dist/modules/async.js.map +1 -0
  44. package/dist/modules/format.d.ts +21 -0
  45. package/dist/modules/format.js +129 -0
  46. package/dist/modules/format.js.map +1 -0
  47. package/dist/modules/index.d.ts +12 -0
  48. package/dist/modules/index.js +3131 -0
  49. package/dist/modules/index.js.map +1 -0
  50. package/dist/modules/math.d.ts +22 -0
  51. package/dist/modules/math.js +215 -0
  52. package/dist/modules/math.js.map +1 -0
  53. package/dist/modules/nn.d.ts +23 -0
  54. package/dist/modules/nn.js +189 -0
  55. package/dist/modules/nn.js.map +1 -0
  56. package/dist/modules/object.d.ts +22 -0
  57. package/dist/modules/object.js +257 -0
  58. package/dist/modules/object.js.map +1 -0
  59. package/dist/modules/str.d.ts +21 -0
  60. package/dist/modules/str.js +344 -0
  61. package/dist/modules/str.js.map +1 -0
  62. package/dist/modules/tensor.d.ts +23 -0
  63. package/dist/modules/tensor.js +427 -0
  64. package/dist/modules/tensor.js.map +1 -0
  65. package/dist/modules/time.d.ts +24 -0
  66. package/dist/modules/time.js +323 -0
  67. package/dist/modules/time.js.map +1 -0
  68. package/dist/modules/train.d.ts +23 -0
  69. package/dist/modules/train.js +308 -0
  70. package/dist/modules/train.js.map +1 -0
  71. package/dist/modules/validate.d.ts +23 -0
  72. package/dist/modules/validate.js +301 -0
  73. package/dist/modules/validate.js.map +1 -0
  74. package/dist/registry.d.ts +140 -0
  75. package/dist/registry.js +3240 -0
  76. package/dist/registry.js.map +1 -0
  77. package/dist/types-I95R8_FN.d.ts +91 -0
  78. package/package.json +59 -0
@@ -0,0 +1,4166 @@
1
+ // behaviors/types.ts
2
+ function getBehaviorMetadata(behavior) {
3
+ const sm = behavior.stateMachine;
4
+ const states = (sm?.states || []).map(
5
+ (s) => typeof s === "string" ? s : s.name
6
+ );
7
+ const events = (sm?.events || []).map(
8
+ (e) => typeof e === "string" ? e : e.key
9
+ );
10
+ return {
11
+ name: behavior.name,
12
+ category: behavior.category,
13
+ description: behavior.description || "",
14
+ suggestedFor: behavior.suggestedFor || [],
15
+ states,
16
+ events,
17
+ tickCount: behavior.ticks?.length || 0,
18
+ transitionCount: sm?.transitions?.length || 0,
19
+ hasDataEntities: (behavior.dataEntities?.length || 0) > 0
20
+ };
21
+ }
22
+
23
+ // behaviors/ui-interaction.ts
24
+ var LIST_BEHAVIOR = {
25
+ name: "std/List",
26
+ category: "ui-interaction",
27
+ description: "Entity list management with CRUD operations",
28
+ suggestedFor: [
29
+ "Entity listing pages",
30
+ "Admin panels",
31
+ "Data management screens",
32
+ "Table views with inline actions"
33
+ ],
34
+ dataEntities: [
35
+ {
36
+ name: "ListState",
37
+ runtime: true,
38
+ singleton: true,
39
+ fields: [
40
+ { name: "selectedId", type: "string", default: null }
41
+ ]
42
+ }
43
+ ],
44
+ stateMachine: {
45
+ initial: "Browsing",
46
+ states: [
47
+ { name: "Browsing", isInitial: true },
48
+ { name: "Creating" },
49
+ { name: "Viewing" },
50
+ { name: "Editing" },
51
+ { name: "Deleting" }
52
+ ],
53
+ events: [
54
+ { key: "INIT" },
55
+ { key: "CREATE" },
56
+ { key: "VIEW" },
57
+ { key: "EDIT" },
58
+ { key: "DELETE" },
59
+ { key: "CONFIRM_DELETE" },
60
+ { key: "CANCEL" },
61
+ { key: "SAVE" }
62
+ ],
63
+ transitions: [
64
+ // INIT: Self-loop on Browsing that renders the list UI
65
+ {
66
+ from: "Browsing",
67
+ to: "Browsing",
68
+ event: "INIT",
69
+ effects: [
70
+ ["render-ui", "main", {
71
+ type: "page-header",
72
+ title: "@config.title",
73
+ actions: [{ label: "Create", event: "CREATE", variant: "primary" }]
74
+ }],
75
+ ["render-ui", "main", {
76
+ type: "entity-table",
77
+ entity: "@config.entity",
78
+ columns: "@config.columns",
79
+ itemActions: [
80
+ { label: "View", event: "VIEW", placement: "row" },
81
+ { label: "Edit", event: "EDIT", placement: "row" },
82
+ { label: "Delete", event: "DELETE", variant: "danger", placement: "row" }
83
+ ]
84
+ }]
85
+ ]
86
+ },
87
+ {
88
+ from: "Browsing",
89
+ to: "Creating",
90
+ event: "CREATE",
91
+ effects: [
92
+ ["render-ui", "modal", {
93
+ type: "form-section",
94
+ entity: "@config.entity",
95
+ mode: "create",
96
+ submitEvent: "SAVE",
97
+ cancelEvent: "CANCEL"
98
+ }]
99
+ ]
100
+ },
101
+ {
102
+ from: "Browsing",
103
+ to: "Viewing",
104
+ event: "VIEW",
105
+ effects: [
106
+ ["set", "@entity.selectedId", "@payload.id"],
107
+ ["render-ui", "drawer", {
108
+ type: "entity-detail",
109
+ entity: "@config.entity",
110
+ id: "@payload.id",
111
+ actions: [
112
+ { label: "Edit", event: "EDIT" },
113
+ { label: "Close", event: "CANCEL" }
114
+ ]
115
+ }]
116
+ ]
117
+ },
118
+ {
119
+ from: "Browsing",
120
+ to: "Editing",
121
+ event: "EDIT",
122
+ effects: [
123
+ ["set", "@entity.selectedId", "@payload.id"],
124
+ ["render-ui", "drawer", {
125
+ type: "form-section",
126
+ entity: "@config.entity",
127
+ id: "@payload.id",
128
+ mode: "edit",
129
+ submitEvent: "SAVE",
130
+ cancelEvent: "CANCEL"
131
+ }]
132
+ ]
133
+ },
134
+ {
135
+ from: "Viewing",
136
+ to: "Editing",
137
+ event: "EDIT",
138
+ effects: [
139
+ ["render-ui", "drawer", {
140
+ type: "form-section",
141
+ entity: "@config.entity",
142
+ id: "@entity.selectedId",
143
+ mode: "edit",
144
+ submitEvent: "SAVE",
145
+ cancelEvent: "CANCEL"
146
+ }]
147
+ ]
148
+ },
149
+ {
150
+ from: "Browsing",
151
+ to: "Deleting",
152
+ event: "DELETE",
153
+ effects: [
154
+ ["set", "@entity.selectedId", "@payload.id"],
155
+ ["render-ui", "modal", {
156
+ type: "confirmation",
157
+ title: "Delete Confirmation",
158
+ message: "Are you sure you want to delete this item?",
159
+ confirmLabel: "Delete",
160
+ confirmVariant: "danger"
161
+ }]
162
+ ]
163
+ },
164
+ {
165
+ from: "Creating",
166
+ to: "Browsing",
167
+ event: "SAVE",
168
+ effects: [
169
+ ["persist", "create", "@config.entity", "@payload.data"],
170
+ ["render-ui", "modal", null],
171
+ ["notify", { type: "success", message: "Created successfully" }],
172
+ ["emit", "INIT"]
173
+ ]
174
+ },
175
+ {
176
+ from: "Editing",
177
+ to: "Browsing",
178
+ event: "SAVE",
179
+ effects: [
180
+ ["persist", "update", "@config.entity", "@payload.data"],
181
+ ["render-ui", "drawer", null],
182
+ ["notify", { type: "success", message: "Updated successfully" }],
183
+ ["emit", "INIT"]
184
+ ]
185
+ },
186
+ {
187
+ from: "Deleting",
188
+ to: "Browsing",
189
+ event: "CONFIRM_DELETE",
190
+ effects: [
191
+ ["persist", "delete", "@config.entity", "@entity.selectedId"],
192
+ ["render-ui", "modal", null],
193
+ ["notify", { type: "success", message: "Deleted successfully" }],
194
+ ["emit", "INIT"]
195
+ ]
196
+ },
197
+ {
198
+ from: "Creating",
199
+ to: "Browsing",
200
+ event: "CANCEL",
201
+ effects: [
202
+ ["render-ui", "modal", null]
203
+ ]
204
+ },
205
+ {
206
+ from: "Viewing",
207
+ to: "Browsing",
208
+ event: "CANCEL",
209
+ effects: [
210
+ ["render-ui", "drawer", null]
211
+ ]
212
+ },
213
+ {
214
+ from: "Editing",
215
+ to: "Browsing",
216
+ event: "CANCEL",
217
+ effects: [
218
+ ["render-ui", "drawer", null]
219
+ ]
220
+ },
221
+ {
222
+ from: "Deleting",
223
+ to: "Browsing",
224
+ event: "CANCEL",
225
+ effects: [
226
+ ["render-ui", "modal", null]
227
+ ]
228
+ }
229
+ ]
230
+ },
231
+ configSchema: {
232
+ required: [
233
+ { name: "entity", type: "entity", description: "Entity type to list" },
234
+ { name: "columns", type: "array", description: "Fields to display as columns" }
235
+ ],
236
+ optional: [
237
+ { name: "title", type: "string", description: "Page title", default: "" },
238
+ { name: "display", type: "string", description: "Display mode", default: "table", enum: ["table", "cards", "list"] },
239
+ { name: "actions", type: "action[]", description: "Available actions", default: ["view", "edit", "delete"] },
240
+ { name: "createInModal", type: "boolean", description: "Show create form in modal", default: true },
241
+ { name: "editInDrawer", type: "boolean", description: "Show edit form in drawer", default: true }
242
+ ]
243
+ }
244
+ };
245
+ var DETAIL_BEHAVIOR = {
246
+ name: "std/Detail",
247
+ category: "ui-interaction",
248
+ description: "Single entity view with edit/delete capabilities",
249
+ suggestedFor: [
250
+ "Entity detail pages",
251
+ "Profile views",
252
+ "Settings pages",
253
+ "Single record screens"
254
+ ],
255
+ dataEntities: [
256
+ {
257
+ name: "DetailState",
258
+ runtime: true,
259
+ fields: [
260
+ { name: "entityId", type: "string", default: null },
261
+ { name: "isLoading", type: "boolean", default: false },
262
+ { name: "hasChanges", type: "boolean", default: false }
263
+ ]
264
+ }
265
+ ],
266
+ stateMachine: {
267
+ initial: "Viewing",
268
+ states: [
269
+ { name: "Viewing", isInitial: true },
270
+ { name: "Editing" },
271
+ { name: "Deleting" }
272
+ ],
273
+ events: [
274
+ { key: "INIT" },
275
+ { key: "EDIT" },
276
+ { key: "SAVE" },
277
+ { key: "CANCEL" },
278
+ { key: "DELETE" },
279
+ { key: "CONFIRM_DELETE" }
280
+ ],
281
+ transitions: [
282
+ // INIT: Self-loop on Viewing
283
+ {
284
+ from: "Viewing",
285
+ to: "Viewing",
286
+ event: "INIT",
287
+ effects: [
288
+ ["render-ui", "main", {
289
+ type: "page-header",
290
+ title: "@entity.name",
291
+ actions: [
292
+ { label: "Edit", event: "EDIT" },
293
+ { label: "Delete", event: "DELETE", variant: "danger" }
294
+ ]
295
+ }],
296
+ ["render-ui", "main", {
297
+ type: "entity-detail",
298
+ entity: "@config.entity",
299
+ fieldNames: "@config.fields"
300
+ }]
301
+ ]
302
+ },
303
+ {
304
+ from: "Viewing",
305
+ to: "Editing",
306
+ event: "EDIT",
307
+ effects: [
308
+ ["render-ui", "main", {
309
+ type: "form-section",
310
+ entity: "@config.entity",
311
+ mode: "edit",
312
+ fields: "@config.fields",
313
+ submitEvent: "SAVE",
314
+ cancelEvent: "CANCEL"
315
+ }]
316
+ ]
317
+ },
318
+ {
319
+ from: "Editing",
320
+ to: "Viewing",
321
+ event: "SAVE",
322
+ effects: [
323
+ ["persist", "update", "@config.entity", "@payload.data"],
324
+ ["notify", { type: "success", message: "Updated successfully" }],
325
+ ["emit", "INIT"]
326
+ ]
327
+ },
328
+ {
329
+ from: "Editing",
330
+ to: "Viewing",
331
+ event: "CANCEL",
332
+ effects: [
333
+ ["emit", "INIT"]
334
+ ]
335
+ },
336
+ {
337
+ from: "Viewing",
338
+ to: "Deleting",
339
+ event: "DELETE",
340
+ effects: [
341
+ ["render-ui", "modal", {
342
+ type: "confirmation",
343
+ title: "Delete Confirmation",
344
+ message: "Are you sure you want to delete this item?"
345
+ }]
346
+ ]
347
+ },
348
+ {
349
+ from: "Deleting",
350
+ to: "Viewing",
351
+ event: "CONFIRM_DELETE",
352
+ effects: [
353
+ ["persist", "delete", "@config.entity", "@entity.id"],
354
+ ["navigate", "@config.returnUrl"]
355
+ ]
356
+ },
357
+ {
358
+ from: "Deleting",
359
+ to: "Viewing",
360
+ event: "CANCEL",
361
+ effects: [
362
+ ["render-ui", "modal", null]
363
+ ]
364
+ }
365
+ ]
366
+ },
367
+ configSchema: {
368
+ required: [
369
+ { name: "entity", type: "entity", description: "Entity type" },
370
+ { name: "fields", type: "array", description: "Fields to display" }
371
+ ],
372
+ optional: [
373
+ { name: "layout", type: "string", description: "Layout mode", default: "two-column", enum: ["single-column", "two-column", "grid"] },
374
+ { name: "allowEdit", type: "boolean", description: "Allow editing", default: true },
375
+ { name: "allowDelete", type: "boolean", description: "Allow deletion", default: true }
376
+ ]
377
+ }
378
+ };
379
+ var FORM_BEHAVIOR = {
380
+ name: "std/Form",
381
+ category: "ui-interaction",
382
+ description: "Form state management with validation and submission",
383
+ suggestedFor: [
384
+ "Create/edit forms",
385
+ "Settings forms",
386
+ "Multi-field input",
387
+ "Validated data entry"
388
+ ],
389
+ dataEntities: [
390
+ {
391
+ name: "FormState",
392
+ runtime: true,
393
+ fields: [
394
+ { name: "values", type: "object", default: {} },
395
+ { name: "errors", type: "object", default: {} },
396
+ { name: "touched", type: "object", default: {} },
397
+ { name: "isDirty", type: "boolean", default: false },
398
+ { name: "isSubmitting", type: "boolean", default: false }
399
+ ]
400
+ }
401
+ ],
402
+ stateMachine: {
403
+ initial: "Idle",
404
+ states: [
405
+ { name: "Idle", isInitial: true },
406
+ { name: "Editing" },
407
+ { name: "Validating" },
408
+ { name: "Submitting" },
409
+ { name: "Success" },
410
+ { name: "Error" }
411
+ ],
412
+ events: [
413
+ { key: "INIT" },
414
+ { key: "FIELD_CHANGE" },
415
+ { key: "FIELD_BLUR" },
416
+ { key: "SUBMIT" },
417
+ { key: "VALIDATION_PASSED" },
418
+ { key: "VALIDATION_FAILED" },
419
+ { key: "SUBMIT_SUCCESS" },
420
+ { key: "SUBMIT_ERROR" },
421
+ { key: "RESET" }
422
+ ],
423
+ transitions: [
424
+ // INIT: Self-loop on Idle → Editing
425
+ {
426
+ from: "Idle",
427
+ to: "Editing",
428
+ event: "INIT",
429
+ effects: [
430
+ ["render-ui", "main", {
431
+ type: "form-section",
432
+ entity: "@config.entity",
433
+ fields: "@config.fields",
434
+ values: "@entity.values",
435
+ errors: "@entity.errors",
436
+ submitEvent: "SUBMIT",
437
+ cancelEvent: "@config.cancelEvent"
438
+ }]
439
+ ]
440
+ },
441
+ {
442
+ from: "Editing",
443
+ to: "Editing",
444
+ event: "FIELD_CHANGE",
445
+ effects: [
446
+ ["set", "@entity.values", ["object/set", "@entity.values", "@payload.field", "@payload.value"]],
447
+ ["set", "@entity.isDirty", true]
448
+ ]
449
+ },
450
+ {
451
+ from: "Editing",
452
+ to: "Editing",
453
+ event: "FIELD_BLUR",
454
+ effects: [
455
+ ["set", "@entity.touched", ["object/set", "@entity.touched", "@payload.field", true]]
456
+ ]
457
+ },
458
+ {
459
+ from: "Editing",
460
+ to: "Validating",
461
+ event: "SUBMIT",
462
+ effects: [
463
+ [
464
+ "let",
465
+ [["result", ["validate/check", "@entity.values", "@config.validation"]]],
466
+ [
467
+ "if",
468
+ "@result.valid",
469
+ ["emit", "VALIDATION_PASSED"],
470
+ [
471
+ "do",
472
+ ["set", "@entity.errors", "@result.errors"],
473
+ ["emit", "VALIDATION_FAILED"]
474
+ ]
475
+ ]
476
+ ]
477
+ ]
478
+ },
479
+ {
480
+ from: "Validating",
481
+ to: "Submitting",
482
+ event: "VALIDATION_PASSED",
483
+ effects: [
484
+ ["set", "@entity.isSubmitting", true],
485
+ [
486
+ "if",
487
+ ["=", "@config.mode", "create"],
488
+ ["persist", "create", "@config.entity", "@entity.values"],
489
+ ["persist", "update", "@config.entity", "@entity.values"]
490
+ ]
491
+ ]
492
+ },
493
+ {
494
+ from: "Validating",
495
+ to: "Editing",
496
+ event: "VALIDATION_FAILED",
497
+ effects: [
498
+ ["notify", { type: "error", message: "Please fix the validation errors" }]
499
+ ]
500
+ },
501
+ {
502
+ from: "Submitting",
503
+ to: "Success",
504
+ event: "SUBMIT_SUCCESS",
505
+ effects: [
506
+ ["set", "@entity.isSubmitting", false],
507
+ ["notify", { type: "success", message: "Saved successfully" }],
508
+ ["emit", "@config.submitEvent", { data: "@entity.values" }]
509
+ ]
510
+ },
511
+ {
512
+ from: "Submitting",
513
+ to: "Error",
514
+ event: "SUBMIT_ERROR",
515
+ effects: [
516
+ ["set", "@entity.isSubmitting", false],
517
+ ["set", "@entity.errors", { _form: "@payload.error" }],
518
+ ["notify", { type: "error", message: "@payload.error" }]
519
+ ]
520
+ },
521
+ {
522
+ from: "Editing",
523
+ to: "Idle",
524
+ event: "RESET",
525
+ effects: [
526
+ ["set", "@entity.values", {}],
527
+ ["set", "@entity.errors", {}],
528
+ ["set", "@entity.touched", {}],
529
+ ["set", "@entity.isDirty", false]
530
+ ]
531
+ },
532
+ {
533
+ from: "Error",
534
+ to: "Idle",
535
+ event: "RESET",
536
+ effects: [
537
+ ["set", "@entity.values", {}],
538
+ ["set", "@entity.errors", {}],
539
+ ["set", "@entity.touched", {}],
540
+ ["set", "@entity.isDirty", false]
541
+ ]
542
+ }
543
+ ]
544
+ },
545
+ configSchema: {
546
+ required: [
547
+ { name: "entity", type: "entity", description: "Entity type" },
548
+ { name: "fields", type: "array", description: "Form fields" }
549
+ ],
550
+ optional: [
551
+ { name: "mode", type: "string", description: "Form mode", default: "create", enum: ["create", "edit"] },
552
+ { name: "validation", type: "object", description: "Validation rules", default: {} },
553
+ { name: "submitEvent", type: "event", description: "Event to emit on successful submit", default: "SAVE" },
554
+ { name: "cancelEvent", type: "event", description: "Event to emit on cancel", default: "CANCEL" }
555
+ ]
556
+ }
557
+ };
558
+ var MODAL_BEHAVIOR = {
559
+ name: "std/Modal",
560
+ category: "ui-interaction",
561
+ description: "Modal dialog with open/close state management",
562
+ suggestedFor: [
563
+ "Confirmation dialogs",
564
+ "Create forms",
565
+ "Detail views",
566
+ "Any overlay content"
567
+ ],
568
+ dataEntities: [
569
+ {
570
+ name: "ModalState",
571
+ runtime: true,
572
+ fields: [
573
+ { name: "content", type: "object", default: null }
574
+ ]
575
+ }
576
+ ],
577
+ stateMachine: {
578
+ initial: "Closed",
579
+ states: [
580
+ { name: "Closed", isInitial: true },
581
+ { name: "Open" }
582
+ ],
583
+ events: [
584
+ { key: "OPEN" },
585
+ { key: "CLOSE" },
586
+ { key: "CONFIRM" }
587
+ ],
588
+ transitions: [
589
+ {
590
+ from: "Closed",
591
+ to: "Open",
592
+ event: "OPEN",
593
+ effects: [
594
+ ["set", "@entity.content", "@payload.content"],
595
+ ["render-ui", "modal", {
596
+ type: "@payload.type",
597
+ onClose: "CLOSE"
598
+ }]
599
+ ]
600
+ },
601
+ {
602
+ from: "Open",
603
+ to: "Closed",
604
+ event: "CLOSE",
605
+ effects: [
606
+ ["render-ui", "modal", null]
607
+ ]
608
+ },
609
+ {
610
+ from: "Open",
611
+ to: "Closed",
612
+ event: "CONFIRM",
613
+ effects: [
614
+ ["render-ui", "modal", null]
615
+ ]
616
+ }
617
+ ]
618
+ },
619
+ configSchema: {
620
+ required: [],
621
+ optional: [
622
+ { name: "size", type: "string", description: "Modal size", default: "md", enum: ["sm", "md", "lg", "xl", "full"] },
623
+ { name: "closeOnOverlay", type: "boolean", description: "Close on overlay click", default: true },
624
+ { name: "closeOnEscape", type: "boolean", description: "Close on escape key", default: true }
625
+ ]
626
+ }
627
+ };
628
+ var DRAWER_BEHAVIOR = {
629
+ name: "std/Drawer",
630
+ category: "ui-interaction",
631
+ description: "Side drawer panel for detail views and forms",
632
+ suggestedFor: [
633
+ "Detail panels",
634
+ "Edit forms",
635
+ "Property panels",
636
+ "Side navigation"
637
+ ],
638
+ dataEntities: [
639
+ {
640
+ name: "DrawerState",
641
+ runtime: true,
642
+ fields: [
643
+ { name: "content", type: "object", default: null }
644
+ ]
645
+ }
646
+ ],
647
+ stateMachine: {
648
+ initial: "Closed",
649
+ states: [
650
+ { name: "Closed", isInitial: true },
651
+ { name: "Open" }
652
+ ],
653
+ events: [
654
+ { key: "OPEN" },
655
+ { key: "CLOSE" }
656
+ ],
657
+ transitions: [
658
+ {
659
+ from: "Closed",
660
+ to: "Open",
661
+ event: "OPEN",
662
+ effects: [
663
+ ["set", "@entity.content", "@payload.content"],
664
+ ["render-ui", "drawer", {
665
+ type: "@payload.type",
666
+ onClose: "CLOSE"
667
+ }]
668
+ ]
669
+ },
670
+ {
671
+ from: "Open",
672
+ to: "Closed",
673
+ event: "CLOSE",
674
+ effects: [
675
+ ["render-ui", "drawer", null]
676
+ ]
677
+ }
678
+ ]
679
+ },
680
+ configSchema: {
681
+ required: [],
682
+ optional: [
683
+ { name: "position", type: "string", description: "Drawer position", default: "right", enum: ["left", "right"] },
684
+ { name: "size", type: "string", description: "Drawer size", default: "md", enum: ["sm", "md", "lg"] },
685
+ { name: "overlay", type: "boolean", description: "Show overlay", default: true }
686
+ ]
687
+ }
688
+ };
689
+ var TABS_BEHAVIOR = {
690
+ name: "std/Tabs",
691
+ category: "ui-interaction",
692
+ description: "Tabbed navigation within a page",
693
+ suggestedFor: [
694
+ "Multi-view pages",
695
+ "Settings with sections",
696
+ "Dashboard tabs",
697
+ "Profile sections"
698
+ ],
699
+ dataEntities: [
700
+ {
701
+ name: "TabsState",
702
+ runtime: true,
703
+ singleton: true,
704
+ fields: [
705
+ { name: "activeTab", type: "string", default: null }
706
+ ]
707
+ }
708
+ ],
709
+ stateMachine: {
710
+ initial: "Active",
711
+ states: [
712
+ { name: "Active", isInitial: true }
713
+ ],
714
+ events: [
715
+ { key: "INIT" },
716
+ { key: "SELECT_TAB" }
717
+ ],
718
+ transitions: [
719
+ // INIT: Self-loop on Active
720
+ {
721
+ from: "Active",
722
+ to: "Active",
723
+ event: "INIT",
724
+ effects: [
725
+ ["set", "@entity.activeTab", "@config.defaultTab"],
726
+ ["render-ui", "main", {
727
+ type: "filter-group",
728
+ filterType: "tabs",
729
+ tabs: "@config.tabs",
730
+ active: "@entity.activeTab",
731
+ onSelect: "SELECT_TAB"
732
+ }]
733
+ ]
734
+ },
735
+ {
736
+ from: "Active",
737
+ to: "Active",
738
+ event: "SELECT_TAB",
739
+ effects: [
740
+ ["set", "@entity.activeTab", "@payload.tabId"]
741
+ ]
742
+ }
743
+ ]
744
+ },
745
+ configSchema: {
746
+ required: [
747
+ { name: "tabs", type: "array", description: "Tab definitions with id, label, content" }
748
+ ],
749
+ optional: [
750
+ { name: "defaultTab", type: "string", description: "Default active tab ID" }
751
+ ]
752
+ }
753
+ };
754
+ var WIZARD_BEHAVIOR = {
755
+ name: "std/Wizard",
756
+ category: "ui-interaction",
757
+ description: "Multi-step wizard flow - each step is a state",
758
+ suggestedFor: [
759
+ "Onboarding flows",
760
+ "Multi-step forms",
761
+ "Setup wizards",
762
+ "Checkout flows"
763
+ ],
764
+ dataEntities: [
765
+ {
766
+ name: "WizardState",
767
+ runtime: true,
768
+ singleton: true,
769
+ fields: [
770
+ { name: "stepData", type: "object", default: {} }
771
+ ]
772
+ }
773
+ ],
774
+ // IMPORTANT: Each wizard step is a STATE, not a number index
775
+ // This is the correct pattern for wizards
776
+ stateMachine: {
777
+ initial: "Step1",
778
+ states: [
779
+ { name: "Step1", isInitial: true },
780
+ { name: "Step2" },
781
+ { name: "Step3" },
782
+ { name: "Complete" }
783
+ ],
784
+ events: [
785
+ { key: "INIT" },
786
+ { key: "NEXT" },
787
+ { key: "PREV" },
788
+ { key: "COMPLETE" }
789
+ ],
790
+ transitions: [
791
+ // INIT on Step1: Self-loop that renders step 1
792
+ {
793
+ from: "Step1",
794
+ to: "Step1",
795
+ event: "INIT",
796
+ effects: [
797
+ ["render-ui", "main", {
798
+ type: "wizard-progress",
799
+ steps: ["Step 1", "Step 2", "Step 3"],
800
+ current: 0
801
+ }],
802
+ ["render-ui", "main", {
803
+ type: "form-section",
804
+ entity: "@config.entity",
805
+ fields: "@config.step1Fields",
806
+ submitEvent: "NEXT"
807
+ }]
808
+ ]
809
+ },
810
+ // Step1 → Step2
811
+ {
812
+ from: "Step1",
813
+ to: "Step2",
814
+ event: "NEXT",
815
+ effects: [
816
+ ["set", "@entity.stepData.step1", "@payload"],
817
+ ["render-ui", "main", {
818
+ type: "wizard-progress",
819
+ steps: ["Step 1", "Step 2", "Step 3"],
820
+ current: 1
821
+ }],
822
+ ["render-ui", "main", {
823
+ type: "form-section",
824
+ entity: "@config.entity",
825
+ fields: "@config.step2Fields",
826
+ submitEvent: "NEXT",
827
+ cancelEvent: "PREV"
828
+ }]
829
+ ]
830
+ },
831
+ // Step2 → Step1 (back)
832
+ {
833
+ from: "Step2",
834
+ to: "Step1",
835
+ event: "PREV",
836
+ effects: [
837
+ ["emit", "INIT"]
838
+ ]
839
+ },
840
+ // Step2 → Step3
841
+ {
842
+ from: "Step2",
843
+ to: "Step3",
844
+ event: "NEXT",
845
+ effects: [
846
+ ["set", "@entity.stepData.step2", "@payload"],
847
+ ["render-ui", "main", {
848
+ type: "wizard-progress",
849
+ steps: ["Step 1", "Step 2", "Step 3"],
850
+ current: 2
851
+ }],
852
+ ["render-ui", "main", {
853
+ type: "entity-detail",
854
+ entity: "@config.entity",
855
+ fieldNames: ["step1", "step2"],
856
+ title: "Review"
857
+ }],
858
+ ["render-ui", "main", {
859
+ type: "form-section",
860
+ submitLabel: "Complete",
861
+ cancelLabel: "Back",
862
+ submitEvent: "COMPLETE",
863
+ cancelEvent: "PREV"
864
+ }]
865
+ ]
866
+ },
867
+ // Step3 → Step2 (back)
868
+ {
869
+ from: "Step3",
870
+ to: "Step2",
871
+ event: "PREV",
872
+ effects: [
873
+ ["render-ui", "main", {
874
+ type: "wizard-progress",
875
+ steps: ["Step 1", "Step 2", "Step 3"],
876
+ current: 1
877
+ }],
878
+ ["render-ui", "main", {
879
+ type: "form-section",
880
+ entity: "@config.entity",
881
+ fields: "@config.step2Fields",
882
+ submitEvent: "NEXT",
883
+ cancelEvent: "PREV"
884
+ }]
885
+ ]
886
+ },
887
+ // Step3 → Complete
888
+ {
889
+ from: "Step3",
890
+ to: "Complete",
891
+ event: "COMPLETE",
892
+ effects: [
893
+ ["persist", "create", "@config.entity", "@entity.stepData"],
894
+ ["notify", { type: "success", message: "Wizard completed!" }],
895
+ ["navigate", "@config.completionUrl"]
896
+ ]
897
+ }
898
+ ]
899
+ },
900
+ configSchema: {
901
+ required: [
902
+ { name: "entity", type: "entity", description: "Entity to create" },
903
+ { name: "step1Fields", type: "array", description: "Fields for step 1" },
904
+ { name: "step2Fields", type: "array", description: "Fields for step 2" }
905
+ ],
906
+ optional: [
907
+ { name: "completionUrl", type: "string", description: "URL to navigate on completion", default: "/" }
908
+ ]
909
+ }
910
+ };
911
+ var MASTER_DETAIL_BEHAVIOR = {
912
+ name: "std/MasterDetail",
913
+ category: "ui-interaction",
914
+ description: "Master-detail layout with synchronized list and detail views",
915
+ suggestedFor: [
916
+ "Email clients",
917
+ "File managers",
918
+ "Two-panel layouts",
919
+ "List-detail views"
920
+ ],
921
+ dataEntities: [
922
+ {
923
+ name: "MasterDetailState",
924
+ runtime: true,
925
+ singleton: true,
926
+ fields: [
927
+ { name: "selectedId", type: "string", default: null }
928
+ ]
929
+ }
930
+ ],
931
+ stateMachine: {
932
+ initial: "NoSelection",
933
+ states: [
934
+ { name: "NoSelection", isInitial: true },
935
+ { name: "Selected" }
936
+ ],
937
+ events: [
938
+ { key: "INIT" },
939
+ { key: "SELECT" },
940
+ { key: "DESELECT" }
941
+ ],
942
+ transitions: [
943
+ // INIT: Self-loop on NoSelection
944
+ {
945
+ from: "NoSelection",
946
+ to: "NoSelection",
947
+ event: "INIT",
948
+ effects: [
949
+ ["render-ui", "main", {
950
+ type: "master-detail",
951
+ entity: "@config.entity",
952
+ masterColumns: "@config.masterColumns",
953
+ onSelect: "SELECT",
954
+ selected: "@entity.selectedId"
955
+ }],
956
+ ["render-ui", "main", {
957
+ type: "empty-state",
958
+ message: "Select an item to view details"
959
+ }]
960
+ ]
961
+ },
962
+ {
963
+ from: "NoSelection",
964
+ to: "Selected",
965
+ event: "SELECT",
966
+ effects: [
967
+ ["set", "@entity.selectedId", "@payload.id"],
968
+ ["render-ui", "main", {
969
+ type: "entity-detail",
970
+ entity: "@config.entity",
971
+ id: "@payload.id",
972
+ fieldNames: "@config.detailFields"
973
+ }]
974
+ ]
975
+ },
976
+ {
977
+ from: "Selected",
978
+ to: "Selected",
979
+ event: "SELECT",
980
+ effects: [
981
+ ["set", "@entity.selectedId", "@payload.id"],
982
+ ["render-ui", "main", {
983
+ type: "entity-detail",
984
+ entity: "@config.entity",
985
+ id: "@payload.id",
986
+ fieldNames: "@config.detailFields"
987
+ }]
988
+ ]
989
+ },
990
+ {
991
+ from: "Selected",
992
+ to: "NoSelection",
993
+ event: "DESELECT",
994
+ effects: [
995
+ ["set", "@entity.selectedId", null],
996
+ ["render-ui", "main", {
997
+ type: "empty-state",
998
+ message: "Select an item to view details"
999
+ }]
1000
+ ]
1001
+ }
1002
+ ]
1003
+ },
1004
+ configSchema: {
1005
+ required: [
1006
+ { name: "entity", type: "entity", description: "Entity type" },
1007
+ { name: "masterColumns", type: "array", description: "Columns for master list" },
1008
+ { name: "detailFields", type: "array", description: "Fields for detail panel" }
1009
+ ],
1010
+ optional: [
1011
+ { name: "masterWidth", type: "string", description: "Master panel width", default: "350px" }
1012
+ ]
1013
+ }
1014
+ };
1015
+ var FILTER_BEHAVIOR = {
1016
+ name: "std/Filter",
1017
+ category: "ui-interaction",
1018
+ description: "Filter and search management for lists",
1019
+ suggestedFor: [
1020
+ "Filtered lists",
1021
+ "Search interfaces",
1022
+ "Faceted navigation",
1023
+ "Advanced filtering"
1024
+ ],
1025
+ dataEntities: [
1026
+ {
1027
+ name: "FilterState",
1028
+ runtime: true,
1029
+ singleton: true,
1030
+ fields: [
1031
+ { name: "filters", type: "object", default: {} },
1032
+ { name: "searchTerm", type: "string", default: "" }
1033
+ ]
1034
+ }
1035
+ ],
1036
+ stateMachine: {
1037
+ initial: "Idle",
1038
+ states: [
1039
+ { name: "Idle", isInitial: true },
1040
+ { name: "Filtering" }
1041
+ ],
1042
+ events: [
1043
+ { key: "INIT" },
1044
+ { key: "SET_FILTER" },
1045
+ { key: "CLEAR_FILTERS" },
1046
+ { key: "SEARCH" }
1047
+ ],
1048
+ transitions: [
1049
+ // INIT: Self-loop
1050
+ {
1051
+ from: "Idle",
1052
+ to: "Idle",
1053
+ event: "INIT",
1054
+ effects: [
1055
+ ["render-ui", "main", {
1056
+ type: "filter-group",
1057
+ filters: "@config.filters",
1058
+ values: "@entity.filters",
1059
+ onFilterChange: "SET_FILTER",
1060
+ onClear: "CLEAR_FILTERS"
1061
+ }]
1062
+ ]
1063
+ },
1064
+ {
1065
+ from: "Idle",
1066
+ to: "Filtering",
1067
+ event: "SET_FILTER",
1068
+ effects: [
1069
+ ["set", "@entity.filters", ["object/set", "@entity.filters", "@payload.field", "@payload.value"]],
1070
+ ["emit", "FILTER_CHANGED", "@entity.filters"]
1071
+ ]
1072
+ },
1073
+ {
1074
+ from: "Filtering",
1075
+ to: "Idle",
1076
+ event: "SET_FILTER",
1077
+ effects: [
1078
+ ["set", "@entity.filters", ["object/set", "@entity.filters", "@payload.field", "@payload.value"]],
1079
+ ["emit", "FILTER_CHANGED", "@entity.filters"]
1080
+ ]
1081
+ },
1082
+ {
1083
+ from: "Filtering",
1084
+ to: "Idle",
1085
+ event: "CLEAR_FILTERS",
1086
+ effects: [
1087
+ ["set", "@entity.filters", {}],
1088
+ ["set", "@entity.searchTerm", ""],
1089
+ ["emit", "FILTER_CHANGED", {}]
1090
+ ]
1091
+ },
1092
+ {
1093
+ from: "Idle",
1094
+ to: "Filtering",
1095
+ event: "SEARCH",
1096
+ effects: [
1097
+ ["set", "@entity.searchTerm", "@payload.term"],
1098
+ ["emit", "SEARCH_CHANGED", "@payload.term"]
1099
+ ]
1100
+ }
1101
+ ]
1102
+ },
1103
+ configSchema: {
1104
+ required: [
1105
+ { name: "filters", type: "array", description: "Filter definitions" }
1106
+ ],
1107
+ optional: [
1108
+ { name: "searchable", type: "boolean", description: "Enable search", default: true }
1109
+ ]
1110
+ }
1111
+ };
1112
+ var UI_INTERACTION_BEHAVIORS = [
1113
+ LIST_BEHAVIOR,
1114
+ DETAIL_BEHAVIOR,
1115
+ FORM_BEHAVIOR,
1116
+ MODAL_BEHAVIOR,
1117
+ DRAWER_BEHAVIOR,
1118
+ TABS_BEHAVIOR,
1119
+ WIZARD_BEHAVIOR,
1120
+ MASTER_DETAIL_BEHAVIOR,
1121
+ FILTER_BEHAVIOR
1122
+ ];
1123
+
1124
+ // behaviors/data-management.ts
1125
+ var PAGINATION_BEHAVIOR = {
1126
+ name: "std/Pagination",
1127
+ category: "data-management",
1128
+ description: "Page-based navigation for large data sets",
1129
+ suggestedFor: [
1130
+ "Large lists",
1131
+ "Table pagination",
1132
+ "Infinite scroll alternative",
1133
+ "Data-heavy views"
1134
+ ],
1135
+ dataEntities: [
1136
+ {
1137
+ name: "PaginationState",
1138
+ runtime: true,
1139
+ singleton: true,
1140
+ fields: [
1141
+ { name: "page", type: "number", default: 1 },
1142
+ { name: "pageSize", type: "number", default: 20 },
1143
+ { name: "totalItems", type: "number", default: 0 }
1144
+ ]
1145
+ }
1146
+ ],
1147
+ stateMachine: {
1148
+ initial: "Active",
1149
+ states: [
1150
+ { name: "Active", isInitial: true }
1151
+ ],
1152
+ events: [
1153
+ { key: "INIT" },
1154
+ { key: "NEXT_PAGE" },
1155
+ { key: "PREV_PAGE" },
1156
+ { key: "GO_TO_PAGE" },
1157
+ { key: "SET_PAGE_SIZE" }
1158
+ ],
1159
+ transitions: [
1160
+ {
1161
+ from: "*",
1162
+ event: "INIT",
1163
+ effects: [
1164
+ ["set", "@entity.page", 1],
1165
+ ["set", "@entity.pageSize", "@config.defaultPageSize"]
1166
+ ]
1167
+ },
1168
+ {
1169
+ event: "NEXT_PAGE",
1170
+ guard: ["<", "@entity.page", ["math/ceil", ["/", "@entity.totalItems", "@entity.pageSize"]]],
1171
+ effects: [
1172
+ ["set", "@entity.page", ["+", "@entity.page", 1]]
1173
+ ]
1174
+ },
1175
+ {
1176
+ event: "PREV_PAGE",
1177
+ guard: [">", "@entity.page", 1],
1178
+ effects: [
1179
+ ["set", "@entity.page", ["-", "@entity.page", 1]]
1180
+ ]
1181
+ },
1182
+ {
1183
+ event: "GO_TO_PAGE",
1184
+ guard: [
1185
+ "and",
1186
+ [">=", "@payload.page", 1],
1187
+ ["<=", "@payload.page", ["math/ceil", ["/", "@entity.totalItems", "@entity.pageSize"]]]
1188
+ ],
1189
+ effects: [
1190
+ ["set", "@entity.page", "@payload.page"]
1191
+ ]
1192
+ },
1193
+ {
1194
+ event: "SET_PAGE_SIZE",
1195
+ effects: [
1196
+ ["set", "@entity.pageSize", "@payload.size"],
1197
+ ["set", "@entity.page", 1]
1198
+ ]
1199
+ }
1200
+ ]
1201
+ },
1202
+ configSchema: {
1203
+ required: [],
1204
+ optional: [
1205
+ { name: "defaultPageSize", type: "number", description: "Default items per page", default: 20 },
1206
+ { name: "pageSizeOptions", type: "array", description: "Available page sizes", default: [10, 20, 50, 100] }
1207
+ ]
1208
+ }
1209
+ };
1210
+ var SELECTION_BEHAVIOR = {
1211
+ name: "std/Selection",
1212
+ category: "data-management",
1213
+ description: "Single or multi-selection management",
1214
+ suggestedFor: [
1215
+ "Multi-select lists",
1216
+ "Bulk operations",
1217
+ "Item picking",
1218
+ "Checkboxes in tables"
1219
+ ],
1220
+ dataEntities: [
1221
+ {
1222
+ name: "SelectionState",
1223
+ runtime: true,
1224
+ singleton: true,
1225
+ fields: [
1226
+ { name: "selected", type: "array", default: [] },
1227
+ { name: "lastSelected", type: "string", default: null }
1228
+ ]
1229
+ }
1230
+ ],
1231
+ stateMachine: {
1232
+ initial: "Active",
1233
+ states: [
1234
+ { name: "Active", isInitial: true }
1235
+ ],
1236
+ events: [
1237
+ { key: "INIT" },
1238
+ { key: "SELECT" },
1239
+ { key: "DESELECT" },
1240
+ { key: "TOGGLE" },
1241
+ { key: "SELECT_ALL" },
1242
+ { key: "CLEAR" }
1243
+ ],
1244
+ transitions: [
1245
+ {
1246
+ from: "*",
1247
+ event: "INIT",
1248
+ effects: [
1249
+ ["set", "@entity.selected", []],
1250
+ ["set", "@entity.lastSelected", null]
1251
+ ]
1252
+ },
1253
+ {
1254
+ event: "SELECT",
1255
+ effects: [
1256
+ [
1257
+ "if",
1258
+ ["=", "@config.mode", "single"],
1259
+ [
1260
+ "do",
1261
+ ["set", "@entity.selected", ["@payload.id"]],
1262
+ ["set", "@entity.lastSelected", "@payload.id"]
1263
+ ],
1264
+ [
1265
+ "if",
1266
+ [
1267
+ "or",
1268
+ ["not", "@config.maxSelection"],
1269
+ ["<", ["array/len", "@entity.selected"], "@config.maxSelection"]
1270
+ ],
1271
+ [
1272
+ "do",
1273
+ ["set", "@entity.selected", ["array/append", "@entity.selected", "@payload.id"]],
1274
+ ["set", "@entity.lastSelected", "@payload.id"]
1275
+ ],
1276
+ ["notify", { type: "warning", message: "Maximum selection reached" }]
1277
+ ]
1278
+ ]
1279
+ ]
1280
+ },
1281
+ {
1282
+ event: "DESELECT",
1283
+ effects: [
1284
+ ["set", "@entity.selected", ["array/filter", "@entity.selected", ["fn", "id", ["!=", "@id", "@payload.id"]]]]
1285
+ ]
1286
+ },
1287
+ {
1288
+ event: "TOGGLE",
1289
+ effects: [
1290
+ [
1291
+ "if",
1292
+ ["array/includes", "@entity.selected", "@payload.id"],
1293
+ ["set", "@entity.selected", ["array/filter", "@entity.selected", ["fn", "id", ["!=", "@id", "@payload.id"]]]],
1294
+ [
1295
+ "if",
1296
+ ["or", ["=", "@config.mode", "single"], [
1297
+ "or",
1298
+ ["not", "@config.maxSelection"],
1299
+ ["<", ["array/len", "@entity.selected"], "@config.maxSelection"]
1300
+ ]],
1301
+ [
1302
+ "set",
1303
+ "@entity.selected",
1304
+ [
1305
+ "if",
1306
+ ["=", "@config.mode", "single"],
1307
+ ["@payload.id"],
1308
+ ["array/append", "@entity.selected", "@payload.id"]
1309
+ ]
1310
+ ],
1311
+ ["notify", { type: "warning", message: "Maximum selection reached" }]
1312
+ ]
1313
+ ]
1314
+ ]
1315
+ },
1316
+ {
1317
+ event: "SELECT_ALL",
1318
+ guard: ["=", "@config.mode", "multi"],
1319
+ effects: [
1320
+ ["set", "@entity.selected", "@payload.ids"]
1321
+ ]
1322
+ },
1323
+ {
1324
+ event: "CLEAR",
1325
+ effects: [
1326
+ ["set", "@entity.selected", []],
1327
+ ["set", "@entity.lastSelected", null]
1328
+ ]
1329
+ }
1330
+ ]
1331
+ },
1332
+ configSchema: {
1333
+ required: [],
1334
+ optional: [
1335
+ { name: "mode", type: "string", description: "Selection mode", default: "single", enum: ["single", "multi"] },
1336
+ { name: "maxSelection", type: "number", description: "Maximum selections (multi mode)", default: null }
1337
+ ]
1338
+ }
1339
+ };
1340
+ var SORT_BEHAVIOR = {
1341
+ name: "std/Sort",
1342
+ category: "data-management",
1343
+ description: "Sorting by field with direction toggle",
1344
+ suggestedFor: [
1345
+ "Sortable tables",
1346
+ "List ordering",
1347
+ "Column headers"
1348
+ ],
1349
+ dataEntities: [
1350
+ {
1351
+ name: "SortState",
1352
+ runtime: true,
1353
+ singleton: true,
1354
+ fields: [
1355
+ { name: "sortField", type: "string", default: null },
1356
+ { name: "sortDirection", type: "string", default: "asc" }
1357
+ ]
1358
+ }
1359
+ ],
1360
+ stateMachine: {
1361
+ initial: "Active",
1362
+ states: [
1363
+ { name: "Active", isInitial: true }
1364
+ ],
1365
+ events: [
1366
+ { key: "INIT" },
1367
+ { key: "SORT" },
1368
+ { key: "TOGGLE_DIRECTION" },
1369
+ { key: "CLEAR_SORT" }
1370
+ ],
1371
+ transitions: [
1372
+ {
1373
+ from: "*",
1374
+ event: "INIT",
1375
+ effects: [
1376
+ ["set", "@entity.sortField", "@config.defaultField"],
1377
+ ["set", "@entity.sortDirection", "@config.defaultDirection"]
1378
+ ]
1379
+ },
1380
+ {
1381
+ event: "SORT",
1382
+ effects: [
1383
+ [
1384
+ "if",
1385
+ ["=", "@entity.sortField", "@payload.field"],
1386
+ ["set", "@entity.sortDirection", ["if", ["=", "@entity.sortDirection", "asc"], "desc", "asc"]],
1387
+ [
1388
+ "do",
1389
+ ["set", "@entity.sortField", "@payload.field"],
1390
+ ["set", "@entity.sortDirection", "asc"]
1391
+ ]
1392
+ ]
1393
+ ]
1394
+ },
1395
+ {
1396
+ event: "TOGGLE_DIRECTION",
1397
+ guard: ["!=", "@entity.sortField", null],
1398
+ effects: [
1399
+ ["set", "@entity.sortDirection", ["if", ["=", "@entity.sortDirection", "asc"], "desc", "asc"]]
1400
+ ]
1401
+ },
1402
+ {
1403
+ event: "CLEAR_SORT",
1404
+ effects: [
1405
+ ["set", "@entity.sortField", null],
1406
+ ["set", "@entity.sortDirection", "asc"]
1407
+ ]
1408
+ }
1409
+ ]
1410
+ },
1411
+ configSchema: {
1412
+ required: [],
1413
+ optional: [
1414
+ { name: "defaultField", type: "string", description: "Default sort field" },
1415
+ { name: "defaultDirection", type: "string", description: "Default direction", default: "asc", enum: ["asc", "desc"] }
1416
+ ]
1417
+ }
1418
+ };
1419
+ var FILTER_BEHAVIOR2 = {
1420
+ name: "std/Filter",
1421
+ category: "data-management",
1422
+ description: "Query Singleton pattern for explicit filtering - use with entity-table query prop",
1423
+ suggestedFor: [
1424
+ "Filterable lists",
1425
+ "Advanced search",
1426
+ "Filter panels",
1427
+ "Faceted search",
1428
+ "Entity tables with filters"
1429
+ ],
1430
+ dataEntities: [
1431
+ {
1432
+ name: "QueryState",
1433
+ runtime: true,
1434
+ singleton: true,
1435
+ fields: [
1436
+ { name: "status", type: "string", default: null, description: "Filter by status field" },
1437
+ { name: "priority", type: "string", default: null, description: "Filter by priority field" },
1438
+ { name: "search", type: "string", default: "", description: "Search term" },
1439
+ { name: "sortBy", type: "string", default: "createdAt", description: "Sort field" },
1440
+ { name: "sortOrder", type: "string", default: "desc", description: "Sort direction: asc or desc" }
1441
+ ]
1442
+ }
1443
+ ],
1444
+ stateMachine: {
1445
+ initial: "Active",
1446
+ states: [
1447
+ { name: "Active", isInitial: true }
1448
+ ],
1449
+ events: [
1450
+ { key: "INIT" },
1451
+ { key: "FILTER" },
1452
+ { key: "SEARCH" },
1453
+ { key: "SORT" },
1454
+ { key: "CLEAR_FILTERS" }
1455
+ ],
1456
+ transitions: [
1457
+ {
1458
+ from: "*",
1459
+ event: "INIT",
1460
+ effects: [
1461
+ // Render filter UI with query reference
1462
+ ["render-ui", "sidebar", {
1463
+ type: "filter-group",
1464
+ query: "@QueryState",
1465
+ filters: "@config.filters"
1466
+ }],
1467
+ // Render entity table with query reference
1468
+ ["render-ui", "main", {
1469
+ type: "entity-table",
1470
+ entity: "@config.entity",
1471
+ query: "@QueryState",
1472
+ columns: "@config.columns"
1473
+ }]
1474
+ ]
1475
+ },
1476
+ {
1477
+ event: "FILTER",
1478
+ effects: [
1479
+ ["set", "@QueryState.status", "@payload.status"],
1480
+ ["set", "@QueryState.priority", "@payload.priority"]
1481
+ ]
1482
+ },
1483
+ {
1484
+ event: "SEARCH",
1485
+ effects: [
1486
+ ["set", "@QueryState.search", "@payload.searchTerm"]
1487
+ ]
1488
+ },
1489
+ {
1490
+ event: "SORT",
1491
+ effects: [
1492
+ ["set", "@QueryState.sortBy", "@payload.field"],
1493
+ ["set", "@QueryState.sortOrder", "@payload.order"]
1494
+ ]
1495
+ },
1496
+ {
1497
+ event: "CLEAR_FILTERS",
1498
+ effects: [
1499
+ ["set", "@QueryState.status", null],
1500
+ ["set", "@QueryState.priority", null],
1501
+ ["set", "@QueryState.search", ""]
1502
+ ]
1503
+ }
1504
+ ]
1505
+ },
1506
+ configSchema: {
1507
+ required: [
1508
+ { name: "entity", type: "string", description: "Entity to filter" }
1509
+ ],
1510
+ optional: [
1511
+ { name: "filters", type: "array", description: "Filter field definitions", default: [] },
1512
+ { name: "columns", type: "array", description: "Table columns to display", default: [] }
1513
+ ]
1514
+ }
1515
+ };
1516
+ var SEARCH_BEHAVIOR = {
1517
+ name: "std/Search",
1518
+ category: "data-management",
1519
+ description: "Search with debounce - updates QueryState.search field",
1520
+ suggestedFor: [
1521
+ "Search inputs",
1522
+ "Quick filters",
1523
+ "Global search",
1524
+ "Type-ahead"
1525
+ ],
1526
+ dataEntities: [
1527
+ {
1528
+ name: "SearchState",
1529
+ runtime: true,
1530
+ singleton: true,
1531
+ fields: [
1532
+ { name: "search", type: "string", default: "" },
1533
+ { name: "isSearching", type: "boolean", default: false }
1534
+ ]
1535
+ }
1536
+ ],
1537
+ stateMachine: {
1538
+ initial: "Idle",
1539
+ states: [
1540
+ { name: "Idle", isInitial: true },
1541
+ { name: "Searching" }
1542
+ ],
1543
+ events: [
1544
+ { key: "INIT" },
1545
+ { key: "SEARCH" },
1546
+ { key: "CLEAR_SEARCH" },
1547
+ { key: "SEARCH_COMPLETE" }
1548
+ ],
1549
+ transitions: [
1550
+ {
1551
+ from: "*",
1552
+ event: "INIT",
1553
+ effects: [
1554
+ ["set", "@entity.search", ""],
1555
+ ["set", "@entity.isSearching", false],
1556
+ ["render-ui", "main", {
1557
+ type: "search-bar",
1558
+ query: "@SearchState",
1559
+ placeholder: "@config.placeholder"
1560
+ }]
1561
+ ]
1562
+ },
1563
+ {
1564
+ from: "Idle",
1565
+ to: "Searching",
1566
+ event: "SEARCH",
1567
+ guard: [">=", ["str/len", "@payload.term"], "@config.minLength"],
1568
+ effects: [
1569
+ ["set", "@entity.search", "@payload.term"],
1570
+ ["set", "@entity.isSearching", true],
1571
+ ["async/debounce", "@config.debounceMs", ["emit", "SEARCH_COMPLETE"]]
1572
+ ]
1573
+ },
1574
+ {
1575
+ from: "Idle",
1576
+ event: "SEARCH",
1577
+ guard: ["<", ["str/len", "@payload.term"], "@config.minLength"],
1578
+ effects: [
1579
+ ["set", "@entity.search", "@payload.term"]
1580
+ ]
1581
+ },
1582
+ {
1583
+ from: "Searching",
1584
+ to: "Idle",
1585
+ event: "SEARCH_COMPLETE",
1586
+ effects: [
1587
+ ["set", "@entity.isSearching", false]
1588
+ ]
1589
+ },
1590
+ {
1591
+ event: "CLEAR_SEARCH",
1592
+ effects: [
1593
+ ["set", "@entity.search", ""],
1594
+ ["set", "@entity.isSearching", false]
1595
+ ]
1596
+ }
1597
+ ]
1598
+ },
1599
+ configSchema: {
1600
+ required: [],
1601
+ optional: [
1602
+ { name: "debounceMs", type: "number", description: "Debounce delay in ms", default: 300 },
1603
+ { name: "minLength", type: "number", description: "Minimum search length", default: 1 },
1604
+ { name: "placeholder", type: "string", description: "Input placeholder", default: "Search..." }
1605
+ ]
1606
+ }
1607
+ };
1608
+ var DATA_MANAGEMENT_BEHAVIORS = [
1609
+ PAGINATION_BEHAVIOR,
1610
+ SELECTION_BEHAVIOR,
1611
+ SORT_BEHAVIOR,
1612
+ FILTER_BEHAVIOR2,
1613
+ SEARCH_BEHAVIOR
1614
+ ];
1615
+
1616
+ // behaviors/async.ts
1617
+ var LOADING_BEHAVIOR = {
1618
+ name: "std/Loading",
1619
+ category: "async",
1620
+ description: "Loading state management with success/error handling",
1621
+ suggestedFor: [
1622
+ "Async data loading",
1623
+ "API calls",
1624
+ "Resource fetching",
1625
+ "Initial page load"
1626
+ ],
1627
+ dataEntities: [
1628
+ {
1629
+ name: "LoadingState",
1630
+ runtime: true,
1631
+ singleton: true,
1632
+ fields: [
1633
+ { name: "isLoading", type: "boolean", default: false },
1634
+ { name: "error", type: "object", default: null },
1635
+ { name: "data", type: "object", default: null },
1636
+ { name: "startTime", type: "number", default: null }
1637
+ ]
1638
+ }
1639
+ ],
1640
+ stateMachine: {
1641
+ initial: "Idle",
1642
+ states: [
1643
+ { name: "Idle", isInitial: true },
1644
+ { name: "Loading" },
1645
+ { name: "Success" },
1646
+ { name: "Error" }
1647
+ ],
1648
+ events: [
1649
+ { key: "START" },
1650
+ { key: "SUCCESS" },
1651
+ { key: "ERROR" },
1652
+ { key: "RETRY" },
1653
+ { key: "RESET" }
1654
+ ],
1655
+ transitions: [
1656
+ {
1657
+ from: "Idle",
1658
+ to: "Loading",
1659
+ event: "START",
1660
+ effects: [
1661
+ ["set", "@entity.isLoading", true],
1662
+ ["set", "@entity.error", null],
1663
+ ["set", "@entity.startTime", ["time/now"]],
1664
+ ["render", "content", "loading-state", {}]
1665
+ ]
1666
+ },
1667
+ {
1668
+ from: "Loading",
1669
+ to: "Success",
1670
+ event: "SUCCESS",
1671
+ effects: [
1672
+ ["set", "@entity.isLoading", false],
1673
+ ["set", "@entity.data", "@payload.data"]
1674
+ ]
1675
+ },
1676
+ {
1677
+ from: "Loading",
1678
+ to: "Error",
1679
+ event: "ERROR",
1680
+ effects: [
1681
+ ["set", "@entity.isLoading", false],
1682
+ ["set", "@entity.error", "@payload.error"],
1683
+ ["render", "content", "error-state", {
1684
+ error: "@entity.error",
1685
+ onRetry: "RETRY"
1686
+ }]
1687
+ ]
1688
+ },
1689
+ {
1690
+ from: "Error",
1691
+ to: "Loading",
1692
+ event: "RETRY",
1693
+ effects: [
1694
+ ["set", "@entity.isLoading", true],
1695
+ ["set", "@entity.error", null],
1696
+ ["set", "@entity.startTime", ["time/now"]],
1697
+ ["render", "content", "loading-state", {}]
1698
+ ]
1699
+ },
1700
+ {
1701
+ from: ["Success", "Error"],
1702
+ to: "Idle",
1703
+ event: "RESET",
1704
+ effects: [
1705
+ ["set", "@entity.isLoading", false],
1706
+ ["set", "@entity.error", null],
1707
+ ["set", "@entity.data", null]
1708
+ ]
1709
+ }
1710
+ ]
1711
+ },
1712
+ configSchema: {
1713
+ required: [],
1714
+ optional: [
1715
+ { name: "showLoadingAfterMs", type: "number", description: "Delay before showing loading", default: 200 },
1716
+ { name: "minLoadingMs", type: "number", description: "Minimum loading display time", default: 500 }
1717
+ ]
1718
+ }
1719
+ };
1720
+ var FETCH_BEHAVIOR = {
1721
+ name: "std/Fetch",
1722
+ category: "async",
1723
+ description: "Data fetching with caching and refresh capabilities",
1724
+ suggestedFor: [
1725
+ "API data fetching",
1726
+ "Entity loading",
1727
+ "Remote data",
1728
+ "Cached queries"
1729
+ ],
1730
+ dataEntities: [
1731
+ {
1732
+ name: "FetchState",
1733
+ runtime: true,
1734
+ singleton: true,
1735
+ fields: [
1736
+ { name: "data", type: "object", default: null },
1737
+ { name: "error", type: "object", default: null },
1738
+ { name: "isFetching", type: "boolean", default: false },
1739
+ { name: "lastFetchedAt", type: "number", default: null }
1740
+ ]
1741
+ }
1742
+ ],
1743
+ stateMachine: {
1744
+ initial: "Idle",
1745
+ states: [
1746
+ { name: "Idle", isInitial: true },
1747
+ { name: "Fetching" },
1748
+ { name: "Stale" },
1749
+ { name: "Fresh" },
1750
+ { name: "Error" }
1751
+ ],
1752
+ events: [
1753
+ { key: "FETCH" },
1754
+ { key: "FETCH_SUCCESS" },
1755
+ { key: "FETCH_ERROR" },
1756
+ { key: "REFRESH" },
1757
+ { key: "INVALIDATE" }
1758
+ ],
1759
+ transitions: [
1760
+ {
1761
+ from: ["Idle", "Stale"],
1762
+ to: "Fetching",
1763
+ event: "FETCH",
1764
+ effects: [
1765
+ ["set", "@entity.isFetching", true],
1766
+ ["set", "@entity.error", null]
1767
+ ]
1768
+ },
1769
+ {
1770
+ from: "Fetching",
1771
+ to: "Fresh",
1772
+ event: "FETCH_SUCCESS",
1773
+ effects: [
1774
+ ["set", "@entity.isFetching", false],
1775
+ ["set", "@entity.data", "@payload.data"],
1776
+ ["set", "@entity.lastFetchedAt", ["time/now"]]
1777
+ ]
1778
+ },
1779
+ {
1780
+ from: "Fetching",
1781
+ to: "Error",
1782
+ event: "FETCH_ERROR",
1783
+ effects: [
1784
+ ["set", "@entity.isFetching", false],
1785
+ ["set", "@entity.error", "@payload.error"]
1786
+ ]
1787
+ },
1788
+ {
1789
+ from: "Fresh",
1790
+ to: "Stale",
1791
+ event: "INVALIDATE",
1792
+ effects: [
1793
+ ["set", "@entity.lastFetchedAt", null]
1794
+ ]
1795
+ },
1796
+ {
1797
+ from: ["Fresh", "Stale", "Error"],
1798
+ to: "Fetching",
1799
+ event: "REFRESH",
1800
+ effects: [
1801
+ ["set", "@entity.isFetching", true],
1802
+ ["set", "@entity.error", null]
1803
+ ]
1804
+ }
1805
+ ]
1806
+ },
1807
+ configSchema: {
1808
+ required: [
1809
+ { name: "entity", type: "entity", description: "Entity type to fetch" }
1810
+ ],
1811
+ optional: [
1812
+ { name: "staleTimeMs", type: "number", description: "Time until data is stale", default: 6e4 },
1813
+ { name: "cacheKey", type: "string", description: "Cache key for deduplication" }
1814
+ ]
1815
+ }
1816
+ };
1817
+ var SUBMIT_BEHAVIOR = {
1818
+ name: "std/Submit",
1819
+ category: "async",
1820
+ description: "Async submission with retry capabilities",
1821
+ suggestedFor: [
1822
+ "Form submission",
1823
+ "Data saving",
1824
+ "API mutations",
1825
+ "Actions with confirmation"
1826
+ ],
1827
+ dataEntities: [
1828
+ {
1829
+ name: "SubmitState",
1830
+ runtime: true,
1831
+ singleton: true,
1832
+ fields: [
1833
+ { name: "isSubmitting", type: "boolean", default: false },
1834
+ { name: "error", type: "object", default: null },
1835
+ { name: "lastSubmittedData", type: "object", default: null }
1836
+ ]
1837
+ }
1838
+ ],
1839
+ stateMachine: {
1840
+ initial: "Idle",
1841
+ states: [
1842
+ { name: "Idle", isInitial: true },
1843
+ { name: "Submitting" },
1844
+ { name: "Success" },
1845
+ { name: "Error" }
1846
+ ],
1847
+ events: [
1848
+ { key: "SUBMIT" },
1849
+ { key: "SUBMIT_SUCCESS" },
1850
+ { key: "SUBMIT_ERROR" },
1851
+ { key: "RETRY" },
1852
+ { key: "RESET" }
1853
+ ],
1854
+ transitions: [
1855
+ {
1856
+ from: "Idle",
1857
+ to: "Submitting",
1858
+ event: "SUBMIT",
1859
+ effects: [
1860
+ ["set", "@entity.isSubmitting", true],
1861
+ ["set", "@entity.error", null],
1862
+ ["set", "@entity.lastSubmittedData", "@payload.data"]
1863
+ ]
1864
+ },
1865
+ {
1866
+ from: "Submitting",
1867
+ to: "Success",
1868
+ event: "SUBMIT_SUCCESS",
1869
+ effects: [
1870
+ ["set", "@entity.isSubmitting", false],
1871
+ ["notify", { type: "success", message: "@config.successMessage" }],
1872
+ ["when", "@config.resetOnSuccess", ["emit", "RESET"]]
1873
+ ]
1874
+ },
1875
+ {
1876
+ from: "Submitting",
1877
+ to: "Error",
1878
+ event: "SUBMIT_ERROR",
1879
+ effects: [
1880
+ ["set", "@entity.isSubmitting", false],
1881
+ ["set", "@entity.error", "@payload.error"],
1882
+ ["notify", { type: "error", message: "@config.errorMessage" }]
1883
+ ]
1884
+ },
1885
+ {
1886
+ from: "Error",
1887
+ to: "Submitting",
1888
+ event: "RETRY",
1889
+ effects: [
1890
+ ["set", "@entity.isSubmitting", true],
1891
+ ["set", "@entity.error", null]
1892
+ ]
1893
+ },
1894
+ {
1895
+ from: ["Success", "Error"],
1896
+ to: "Idle",
1897
+ event: "RESET",
1898
+ effects: [
1899
+ ["set", "@entity.isSubmitting", false],
1900
+ ["set", "@entity.error", null],
1901
+ ["set", "@entity.lastSubmittedData", null]
1902
+ ]
1903
+ }
1904
+ ]
1905
+ },
1906
+ configSchema: {
1907
+ required: [],
1908
+ optional: [
1909
+ { name: "successMessage", type: "string", description: "Success notification", default: "Saved successfully" },
1910
+ { name: "errorMessage", type: "string", description: "Error notification", default: "Failed to save" },
1911
+ { name: "resetOnSuccess", type: "boolean", description: "Reset to idle on success", default: false }
1912
+ ]
1913
+ }
1914
+ };
1915
+ var RETRY_BEHAVIOR = {
1916
+ name: "std/Retry",
1917
+ category: "async",
1918
+ description: "Automatic retry with exponential backoff",
1919
+ suggestedFor: [
1920
+ "Network requests",
1921
+ "Unreliable operations",
1922
+ "Transient failures",
1923
+ "Recovery logic"
1924
+ ],
1925
+ dataEntities: [
1926
+ {
1927
+ name: "RetryState",
1928
+ runtime: true,
1929
+ singleton: true,
1930
+ fields: [
1931
+ { name: "attempt", type: "number", default: 0 },
1932
+ { name: "error", type: "object", default: null },
1933
+ { name: "nextRetryAt", type: "number", default: null }
1934
+ ]
1935
+ }
1936
+ ],
1937
+ stateMachine: {
1938
+ initial: "Idle",
1939
+ states: [
1940
+ { name: "Idle", isInitial: true },
1941
+ { name: "Attempting" },
1942
+ { name: "Waiting" },
1943
+ { name: "Success" },
1944
+ { name: "Failed" }
1945
+ ],
1946
+ events: [
1947
+ { key: "START" },
1948
+ { key: "ATTEMPT_SUCCESS" },
1949
+ { key: "ATTEMPT_ERROR" },
1950
+ { key: "RETRY_TICK" },
1951
+ { key: "GIVE_UP" },
1952
+ { key: "RESET" }
1953
+ ],
1954
+ transitions: [
1955
+ {
1956
+ from: "Idle",
1957
+ to: "Attempting",
1958
+ event: "START",
1959
+ effects: [
1960
+ ["set", "@entity.attempt", 1],
1961
+ ["set", "@entity.error", null]
1962
+ ]
1963
+ },
1964
+ {
1965
+ from: "Attempting",
1966
+ to: "Success",
1967
+ event: "ATTEMPT_SUCCESS",
1968
+ effects: []
1969
+ },
1970
+ {
1971
+ from: "Attempting",
1972
+ to: "Waiting",
1973
+ event: "ATTEMPT_ERROR",
1974
+ guard: ["<", "@entity.attempt", "@config.maxAttempts"],
1975
+ effects: [
1976
+ ["set", "@entity.error", "@payload.error"],
1977
+ [
1978
+ "let",
1979
+ [["delay", [
1980
+ "math/min",
1981
+ ["*", "@config.initialDelayMs", ["math/pow", "@config.backoffMultiplier", "@entity.attempt"]],
1982
+ "@config.maxDelayMs"
1983
+ ]]],
1984
+ ["set", "@entity.nextRetryAt", ["+", ["time/now"], "@delay"]],
1985
+ ["async/delay", "@delay", ["emit", "RETRY_TICK"]]
1986
+ ]
1987
+ ]
1988
+ },
1989
+ {
1990
+ from: "Attempting",
1991
+ to: "Failed",
1992
+ event: "ATTEMPT_ERROR",
1993
+ guard: [">=", "@entity.attempt", "@config.maxAttempts"],
1994
+ effects: [
1995
+ ["set", "@entity.error", "@payload.error"],
1996
+ ["notify", { type: "error", message: "All retry attempts failed" }]
1997
+ ]
1998
+ },
1999
+ {
2000
+ from: "Waiting",
2001
+ to: "Attempting",
2002
+ event: "RETRY_TICK",
2003
+ effects: [
2004
+ ["set", "@entity.attempt", ["+", "@entity.attempt", 1]]
2005
+ ]
2006
+ },
2007
+ {
2008
+ from: "Waiting",
2009
+ to: "Failed",
2010
+ event: "GIVE_UP",
2011
+ effects: [
2012
+ ["notify", { type: "warning", message: "Retry cancelled" }]
2013
+ ]
2014
+ },
2015
+ {
2016
+ from: ["Success", "Failed"],
2017
+ to: "Idle",
2018
+ event: "RESET",
2019
+ effects: [
2020
+ ["set", "@entity.attempt", 0],
2021
+ ["set", "@entity.error", null],
2022
+ ["set", "@entity.nextRetryAt", null]
2023
+ ]
2024
+ }
2025
+ ]
2026
+ },
2027
+ configSchema: {
2028
+ required: [],
2029
+ optional: [
2030
+ { name: "maxAttempts", type: "number", description: "Maximum retry attempts", default: 3 },
2031
+ { name: "initialDelayMs", type: "number", description: "Initial retry delay", default: 1e3 },
2032
+ { name: "maxDelayMs", type: "number", description: "Maximum retry delay", default: 3e4 },
2033
+ { name: "backoffMultiplier", type: "number", description: "Backoff multiplier", default: 2 }
2034
+ ]
2035
+ }
2036
+ };
2037
+ var POLL_BEHAVIOR = {
2038
+ name: "std/Poll",
2039
+ category: "async",
2040
+ description: "Periodic polling with start/stop control",
2041
+ suggestedFor: [
2042
+ "Real-time updates",
2043
+ "Status checking",
2044
+ "Live data",
2045
+ "Notification polling"
2046
+ ],
2047
+ dataEntities: [
2048
+ {
2049
+ name: "PollState",
2050
+ runtime: true,
2051
+ singleton: true,
2052
+ fields: [
2053
+ { name: "isPolling", type: "boolean", default: false },
2054
+ { name: "pollCount", type: "number", default: 0 },
2055
+ { name: "lastPollAt", type: "number", default: null },
2056
+ { name: "error", type: "object", default: null }
2057
+ ]
2058
+ }
2059
+ ],
2060
+ stateMachine: {
2061
+ initial: "Stopped",
2062
+ states: [
2063
+ { name: "Stopped", isInitial: true },
2064
+ { name: "Polling" },
2065
+ { name: "Paused" }
2066
+ ],
2067
+ events: [
2068
+ { key: "START" },
2069
+ { key: "STOP" },
2070
+ { key: "PAUSE" },
2071
+ { key: "RESUME" },
2072
+ { key: "POLL_TICK" },
2073
+ { key: "POLL_SUCCESS" },
2074
+ { key: "POLL_ERROR" }
2075
+ ],
2076
+ transitions: [
2077
+ {
2078
+ from: "Stopped",
2079
+ to: "Polling",
2080
+ event: "START",
2081
+ effects: [
2082
+ ["set", "@entity.isPolling", true],
2083
+ ["set", "@entity.pollCount", 0],
2084
+ ["async/interval", "@config.intervalMs", ["emit", "POLL_TICK"]]
2085
+ ]
2086
+ },
2087
+ {
2088
+ from: "Polling",
2089
+ event: "POLL_TICK",
2090
+ guard: ["or", ["=", "@config.maxPolls", null], ["<", "@entity.pollCount", "@config.maxPolls"]],
2091
+ effects: [
2092
+ ["set", "@entity.lastPollAt", ["time/now"]]
2093
+ ]
2094
+ },
2095
+ {
2096
+ from: "Polling",
2097
+ event: "POLL_SUCCESS",
2098
+ effects: [
2099
+ ["set", "@entity.pollCount", ["+", "@entity.pollCount", 1]],
2100
+ ["set", "@entity.error", null]
2101
+ ]
2102
+ },
2103
+ {
2104
+ from: "Polling",
2105
+ event: "POLL_ERROR",
2106
+ effects: [
2107
+ ["set", "@entity.error", "@payload.error"],
2108
+ ["when", "@config.stopOnError", ["emit", "STOP"]]
2109
+ ]
2110
+ },
2111
+ {
2112
+ from: "Polling",
2113
+ to: "Paused",
2114
+ event: "PAUSE",
2115
+ effects: [
2116
+ ["set", "@entity.isPolling", false]
2117
+ ]
2118
+ },
2119
+ {
2120
+ from: "Paused",
2121
+ to: "Polling",
2122
+ event: "RESUME",
2123
+ effects: [
2124
+ ["set", "@entity.isPolling", true],
2125
+ ["async/interval", "@config.intervalMs", ["emit", "POLL_TICK"]]
2126
+ ]
2127
+ },
2128
+ {
2129
+ from: ["Polling", "Paused"],
2130
+ to: "Stopped",
2131
+ event: "STOP",
2132
+ effects: [
2133
+ ["set", "@entity.isPolling", false]
2134
+ ]
2135
+ }
2136
+ ]
2137
+ },
2138
+ configSchema: {
2139
+ required: [],
2140
+ optional: [
2141
+ { name: "intervalMs", type: "number", description: "Poll interval in ms", default: 5e3 },
2142
+ { name: "stopOnError", type: "boolean", description: "Stop polling on error", default: false },
2143
+ { name: "maxPolls", type: "number", description: "Maximum poll count (null = infinite)", default: null }
2144
+ ]
2145
+ }
2146
+ };
2147
+ var ASYNC_BEHAVIORS = [
2148
+ LOADING_BEHAVIOR,
2149
+ FETCH_BEHAVIOR,
2150
+ SUBMIT_BEHAVIOR,
2151
+ RETRY_BEHAVIOR,
2152
+ POLL_BEHAVIOR
2153
+ ];
2154
+
2155
+ // behaviors/feedback.ts
2156
+ var NOTIFICATION_BEHAVIOR = {
2157
+ name: "std/Notification",
2158
+ category: "feedback",
2159
+ description: "Toast notification with auto-dismiss",
2160
+ suggestedFor: [
2161
+ "Success messages",
2162
+ "Error alerts",
2163
+ "Status updates",
2164
+ "User feedback"
2165
+ ],
2166
+ dataEntities: [
2167
+ {
2168
+ name: "NotificationState",
2169
+ runtime: true,
2170
+ singleton: true,
2171
+ fields: [
2172
+ { name: "notifications", type: "array", default: [] },
2173
+ { name: "currentId", type: "number", default: 0 }
2174
+ ]
2175
+ }
2176
+ ],
2177
+ stateMachine: {
2178
+ initial: "Hidden",
2179
+ states: [
2180
+ { name: "Hidden", isInitial: true },
2181
+ { name: "Visible" },
2182
+ { name: "Dismissing" }
2183
+ ],
2184
+ events: [
2185
+ { key: "SHOW" },
2186
+ { key: "HIDE" },
2187
+ { key: "DISMISS" },
2188
+ { key: "AUTO_DISMISS" }
2189
+ ],
2190
+ transitions: [
2191
+ {
2192
+ from: "*",
2193
+ event: "SHOW",
2194
+ effects: [
2195
+ [
2196
+ "let",
2197
+ [["id", ["+", "@entity.currentId", 1]]],
2198
+ [
2199
+ "do",
2200
+ ["set", "@entity.currentId", "@id"],
2201
+ [
2202
+ "set",
2203
+ "@entity.notifications",
2204
+ ["array/append", "@entity.notifications", {
2205
+ id: "@id",
2206
+ type: "@payload.type",
2207
+ message: "@payload.message",
2208
+ title: "@payload.title"
2209
+ }]
2210
+ ],
2211
+ [
2212
+ "when",
2213
+ [">", "@config.autoDismissMs", 0],
2214
+ ["async/delay", "@config.autoDismissMs", ["emit", "AUTO_DISMISS", { id: "@id" }]]
2215
+ ]
2216
+ ]
2217
+ ]
2218
+ ]
2219
+ },
2220
+ {
2221
+ event: "DISMISS",
2222
+ effects: [
2223
+ [
2224
+ "set",
2225
+ "@entity.notifications",
2226
+ ["array/filter", "@entity.notifications", ["fn", "n", ["!=", "@n.id", "@payload.id"]]]
2227
+ ]
2228
+ ]
2229
+ },
2230
+ {
2231
+ event: "AUTO_DISMISS",
2232
+ effects: [
2233
+ [
2234
+ "set",
2235
+ "@entity.notifications",
2236
+ ["array/filter", "@entity.notifications", ["fn", "n", ["!=", "@n.id", "@payload.id"]]]
2237
+ ]
2238
+ ]
2239
+ },
2240
+ {
2241
+ event: "HIDE",
2242
+ effects: [
2243
+ ["set", "@entity.notifications", []]
2244
+ ]
2245
+ }
2246
+ ]
2247
+ },
2248
+ configSchema: {
2249
+ required: [],
2250
+ optional: [
2251
+ { name: "autoDismissMs", type: "number", description: "Auto dismiss delay (0 = no auto)", default: 5e3 },
2252
+ { name: "position", type: "string", description: "Toast position", default: "top-right", enum: ["top-left", "top-center", "top-right", "bottom-left", "bottom-center", "bottom-right"] },
2253
+ { name: "maxVisible", type: "number", description: "Maximum visible notifications", default: 5 }
2254
+ ]
2255
+ }
2256
+ };
2257
+ var CONFIRMATION_BEHAVIOR = {
2258
+ name: "std/Confirmation",
2259
+ category: "feedback",
2260
+ description: "Confirmation dialog with confirm/cancel actions",
2261
+ suggestedFor: [
2262
+ "Delete confirmation",
2263
+ "Destructive actions",
2264
+ "Important decisions",
2265
+ "Exit warnings"
2266
+ ],
2267
+ dataEntities: [
2268
+ {
2269
+ name: "ConfirmationState",
2270
+ runtime: true,
2271
+ singleton: true,
2272
+ fields: [
2273
+ { name: "title", type: "string", default: "" },
2274
+ { name: "message", type: "string", default: "" },
2275
+ { name: "pendingAction", type: "object", default: null }
2276
+ ]
2277
+ }
2278
+ ],
2279
+ stateMachine: {
2280
+ initial: "Closed",
2281
+ states: [
2282
+ { name: "Closed", isInitial: true },
2283
+ { name: "Open" }
2284
+ ],
2285
+ events: [
2286
+ { key: "REQUEST" },
2287
+ { key: "CONFIRM" },
2288
+ { key: "CANCEL" }
2289
+ ],
2290
+ transitions: [
2291
+ {
2292
+ from: "Closed",
2293
+ to: "Open",
2294
+ event: "REQUEST",
2295
+ effects: [
2296
+ ["set", "@entity.title", "@payload.title"],
2297
+ ["set", "@entity.message", "@payload.message"],
2298
+ ["set", "@entity.pendingAction", "@payload.onConfirm"],
2299
+ ["render-ui", "modal", {
2300
+ type: "confirmation",
2301
+ title: "@entity.title",
2302
+ message: "@entity.message",
2303
+ confirmLabel: "@config.confirmLabel",
2304
+ cancelLabel: "@config.cancelLabel",
2305
+ confirmVariant: "@config.confirmVariant"
2306
+ }]
2307
+ ]
2308
+ },
2309
+ {
2310
+ from: "Open",
2311
+ to: "Closed",
2312
+ event: "CONFIRM",
2313
+ effects: [
2314
+ ["render-ui", "modal", null],
2315
+ ["when", "@entity.pendingAction", ["emit", "@entity.pendingAction.event", "@entity.pendingAction.payload"]],
2316
+ ["set", "@entity.pendingAction", null]
2317
+ ]
2318
+ },
2319
+ {
2320
+ from: "Open",
2321
+ to: "Closed",
2322
+ event: "CANCEL",
2323
+ effects: [
2324
+ ["render-ui", "modal", null],
2325
+ ["set", "@entity.pendingAction", null]
2326
+ ]
2327
+ }
2328
+ ]
2329
+ },
2330
+ configSchema: {
2331
+ required: [],
2332
+ optional: [
2333
+ { name: "confirmLabel", type: "string", description: "Confirm button label", default: "Confirm" },
2334
+ { name: "cancelLabel", type: "string", description: "Cancel button label", default: "Cancel" },
2335
+ { name: "confirmVariant", type: "string", description: "Confirm button variant", default: "primary", enum: ["primary", "danger", "warning"] }
2336
+ ]
2337
+ }
2338
+ };
2339
+ var UNDO_BEHAVIOR = {
2340
+ name: "std/Undo",
2341
+ category: "feedback",
2342
+ description: "Undo/redo stack for reversible actions",
2343
+ suggestedFor: [
2344
+ "Document editing",
2345
+ "Form changes",
2346
+ "Canvas operations",
2347
+ "Reversible actions"
2348
+ ],
2349
+ dataEntities: [
2350
+ {
2351
+ name: "UndoState",
2352
+ runtime: true,
2353
+ singleton: true,
2354
+ fields: [
2355
+ { name: "undoStack", type: "array", default: [] },
2356
+ { name: "redoStack", type: "array", default: [] }
2357
+ ]
2358
+ }
2359
+ ],
2360
+ stateMachine: {
2361
+ initial: "Ready",
2362
+ states: [
2363
+ { name: "Ready", isInitial: true }
2364
+ ],
2365
+ events: [
2366
+ { key: "PUSH" },
2367
+ { key: "UNDO" },
2368
+ { key: "REDO" },
2369
+ { key: "CLEAR" }
2370
+ ],
2371
+ transitions: [
2372
+ {
2373
+ event: "PUSH",
2374
+ effects: [
2375
+ [
2376
+ "set",
2377
+ "@entity.undoStack",
2378
+ [
2379
+ "array/slice",
2380
+ ["array/prepend", "@entity.undoStack", {
2381
+ action: "@payload.action",
2382
+ data: "@payload.data",
2383
+ reverseAction: "@payload.reverseAction",
2384
+ reverseData: "@payload.reverseData",
2385
+ description: "@payload.description"
2386
+ }],
2387
+ 0,
2388
+ "@config.maxHistory"
2389
+ ]
2390
+ ],
2391
+ ["set", "@entity.redoStack", []],
2392
+ [
2393
+ "when",
2394
+ "@config.showToast",
2395
+ ["emit", "NOTIFY", {
2396
+ type: "info",
2397
+ message: ["str/concat", "@payload.description", " - Click to undo"],
2398
+ action: { label: "Undo", event: "UNDO" }
2399
+ }]
2400
+ ]
2401
+ ]
2402
+ },
2403
+ {
2404
+ event: "UNDO",
2405
+ guard: [">", ["array/len", "@entity.undoStack"], 0],
2406
+ effects: [
2407
+ [
2408
+ "let",
2409
+ [["action", ["array/first", "@entity.undoStack"]]],
2410
+ [
2411
+ "do",
2412
+ ["set", "@entity.undoStack", ["array/slice", "@entity.undoStack", 1]],
2413
+ ["set", "@entity.redoStack", ["array/prepend", "@entity.redoStack", "@action"]],
2414
+ ["emit", "@action.reverseAction", "@action.reverseData"]
2415
+ ]
2416
+ ]
2417
+ ]
2418
+ },
2419
+ {
2420
+ event: "REDO",
2421
+ guard: [">", ["array/len", "@entity.redoStack"], 0],
2422
+ effects: [
2423
+ [
2424
+ "let",
2425
+ [["action", ["array/first", "@entity.redoStack"]]],
2426
+ [
2427
+ "do",
2428
+ ["set", "@entity.redoStack", ["array/slice", "@entity.redoStack", 1]],
2429
+ ["set", "@entity.undoStack", ["array/prepend", "@entity.undoStack", "@action"]],
2430
+ ["emit", "@action.action", "@action.data"]
2431
+ ]
2432
+ ]
2433
+ ]
2434
+ },
2435
+ {
2436
+ event: "CLEAR",
2437
+ effects: [
2438
+ ["set", "@entity.undoStack", []],
2439
+ ["set", "@entity.redoStack", []]
2440
+ ]
2441
+ }
2442
+ ]
2443
+ },
2444
+ configSchema: {
2445
+ required: [],
2446
+ optional: [
2447
+ { name: "maxHistory", type: "number", description: "Maximum undo history", default: 50 },
2448
+ { name: "showToast", type: "boolean", description: "Show undo toast", default: true },
2449
+ { name: "toastDurationMs", type: "number", description: "Toast display duration", default: 5e3 }
2450
+ ]
2451
+ }
2452
+ };
2453
+ var FEEDBACK_BEHAVIORS = [
2454
+ NOTIFICATION_BEHAVIOR,
2455
+ CONFIRMATION_BEHAVIOR,
2456
+ UNDO_BEHAVIOR
2457
+ ];
2458
+
2459
+ // behaviors/game-core.ts
2460
+ var GAME_LOOP_BEHAVIOR = {
2461
+ name: "std/GameLoop",
2462
+ category: "game-core",
2463
+ description: "Master game loop coordinator running at 60fps",
2464
+ suggestedFor: [
2465
+ "All real-time games",
2466
+ "Platformers",
2467
+ "Action games",
2468
+ "Endless runners"
2469
+ ],
2470
+ dataEntities: [
2471
+ {
2472
+ name: "GameLoopState",
2473
+ runtime: true,
2474
+ singleton: true,
2475
+ fields: [
2476
+ { name: "frameCount", type: "number", default: 0 },
2477
+ { name: "deltaTime", type: "number", default: 16 },
2478
+ { name: "elapsedTime", type: "number", default: 0 }
2479
+ ]
2480
+ }
2481
+ ],
2482
+ stateMachine: {
2483
+ initial: "Stopped",
2484
+ states: [
2485
+ { name: "Stopped", isInitial: true },
2486
+ { name: "Running" },
2487
+ { name: "Paused" }
2488
+ ],
2489
+ events: [
2490
+ { key: "START" },
2491
+ { key: "STOP" },
2492
+ { key: "PAUSE" },
2493
+ { key: "RESUME" },
2494
+ { key: "TICK" }
2495
+ ],
2496
+ transitions: [
2497
+ {
2498
+ from: "Stopped",
2499
+ to: "Running",
2500
+ event: "START",
2501
+ effects: [
2502
+ ["set", "@entity.frameCount", 0],
2503
+ ["set", "@entity.elapsedTime", 0]
2504
+ ]
2505
+ },
2506
+ {
2507
+ from: "Running",
2508
+ to: "Paused",
2509
+ event: "PAUSE",
2510
+ effects: []
2511
+ },
2512
+ {
2513
+ from: "Paused",
2514
+ to: "Running",
2515
+ event: "RESUME",
2516
+ effects: []
2517
+ },
2518
+ {
2519
+ from: ["Running", "Paused"],
2520
+ to: "Stopped",
2521
+ event: "STOP",
2522
+ effects: []
2523
+ }
2524
+ ]
2525
+ },
2526
+ ticks: [
2527
+ {
2528
+ name: "GameTick",
2529
+ interval: "frame",
2530
+ guard: ["=", "@state", "Running"],
2531
+ effects: [
2532
+ ["set", "@entity.frameCount", ["+", "@entity.frameCount", 1]],
2533
+ ["set", "@entity.elapsedTime", ["+", "@entity.elapsedTime", "@entity.deltaTime"]],
2534
+ ["emit", "GAME_TICK", { frame: "@entity.frameCount", delta: "@entity.deltaTime" }]
2535
+ ]
2536
+ }
2537
+ ],
2538
+ configSchema: {
2539
+ required: [],
2540
+ optional: [
2541
+ { name: "targetFps", type: "number", description: "Target frames per second", default: 60 },
2542
+ { name: "fixedTimestep", type: "boolean", description: "Use fixed timestep", default: true }
2543
+ ]
2544
+ }
2545
+ };
2546
+ var PHYSICS_2D_BEHAVIOR = {
2547
+ name: "std/Physics2D",
2548
+ category: "game-core",
2549
+ description: "2D physics with gravity, velocity, and friction",
2550
+ suggestedFor: [
2551
+ "Platformer characters",
2552
+ "Falling objects",
2553
+ "Projectiles",
2554
+ "Any entity affected by gravity"
2555
+ ],
2556
+ requiredFields: [
2557
+ { name: "x", type: "number", description: "Entity X position" },
2558
+ { name: "y", type: "number", description: "Entity Y position" }
2559
+ ],
2560
+ dataEntities: [
2561
+ {
2562
+ name: "Physics2DState",
2563
+ runtime: true,
2564
+ fields: [
2565
+ { name: "vx", type: "number", default: 0 },
2566
+ { name: "vy", type: "number", default: 0 },
2567
+ { name: "isGrounded", type: "boolean", default: false }
2568
+ ]
2569
+ }
2570
+ ],
2571
+ stateMachine: {
2572
+ initial: "Active",
2573
+ states: [
2574
+ { name: "Active", isInitial: true },
2575
+ { name: "Frozen" }
2576
+ ],
2577
+ events: [
2578
+ { key: "INIT" },
2579
+ { key: "APPLY_FORCE" },
2580
+ { key: "GROUND_HIT" },
2581
+ { key: "FREEZE" },
2582
+ { key: "UNFREEZE" }
2583
+ ],
2584
+ transitions: [
2585
+ {
2586
+ from: "*",
2587
+ event: "INIT",
2588
+ effects: [
2589
+ ["set", "@entity.vx", 0],
2590
+ ["set", "@entity.vy", 0],
2591
+ ["set", "@entity.isGrounded", false]
2592
+ ]
2593
+ },
2594
+ {
2595
+ from: "Active",
2596
+ event: "APPLY_FORCE",
2597
+ effects: [
2598
+ ["set", "@entity.vx", ["+", "@entity.vx", "@payload.fx"]],
2599
+ ["set", "@entity.vy", ["+", "@entity.vy", "@payload.fy"]]
2600
+ ]
2601
+ },
2602
+ {
2603
+ from: "Active",
2604
+ event: "GROUND_HIT",
2605
+ effects: [
2606
+ ["set", "@entity.isGrounded", true],
2607
+ ["set", "@entity.vy", 0],
2608
+ ["set", "@entity.vx", ["*", "@entity.vx", "@config.friction"]]
2609
+ ]
2610
+ },
2611
+ {
2612
+ from: "Active",
2613
+ to: "Frozen",
2614
+ event: "FREEZE",
2615
+ effects: []
2616
+ },
2617
+ {
2618
+ from: "Frozen",
2619
+ to: "Active",
2620
+ event: "UNFREEZE",
2621
+ effects: []
2622
+ }
2623
+ ]
2624
+ },
2625
+ ticks: [
2626
+ {
2627
+ name: "ApplyGravity",
2628
+ interval: "frame",
2629
+ guard: ["and", ["=", "@state", "Active"], ["not", "@entity.isGrounded"]],
2630
+ effects: [
2631
+ ["set", "@entity.vy", ["math/min", "@config.maxVelocityY", ["+", "@entity.vy", "@config.gravity"]]]
2632
+ ]
2633
+ },
2634
+ {
2635
+ name: "ApplyVelocity",
2636
+ interval: "frame",
2637
+ guard: ["=", "@state", "Active"],
2638
+ effects: [
2639
+ ["set", "@entity.vx", ["*", "@entity.vx", "@config.airResistance"]],
2640
+ ["set", "@entity.x", ["+", "@entity.x", "@entity.vx"]],
2641
+ ["set", "@entity.y", ["+", "@entity.y", "@entity.vy"]]
2642
+ ]
2643
+ }
2644
+ ],
2645
+ configSchema: {
2646
+ required: [],
2647
+ optional: [
2648
+ { name: "gravity", type: "number", description: "Gravity acceleration (pixels/frame\xB2)", default: 0.5 },
2649
+ { name: "maxVelocityY", type: "number", description: "Terminal velocity", default: 15 },
2650
+ { name: "friction", type: "number", description: "Ground friction (0-1)", default: 0.8 },
2651
+ { name: "airResistance", type: "number", description: "Air resistance (0-1)", default: 0.99 }
2652
+ ]
2653
+ }
2654
+ };
2655
+ var INPUT_BEHAVIOR = {
2656
+ name: "std/Input",
2657
+ category: "game-core",
2658
+ description: "Unified keyboard and touch input state management",
2659
+ suggestedFor: [
2660
+ "All interactive games",
2661
+ "Player controls",
2662
+ "Menu navigation"
2663
+ ],
2664
+ dataEntities: [
2665
+ {
2666
+ name: "InputState",
2667
+ runtime: true,
2668
+ singleton: true,
2669
+ fields: [
2670
+ { name: "left", type: "boolean", default: false },
2671
+ { name: "right", type: "boolean", default: false },
2672
+ { name: "up", type: "boolean", default: false },
2673
+ { name: "down", type: "boolean", default: false },
2674
+ { name: "jump", type: "boolean", default: false },
2675
+ { name: "action", type: "boolean", default: false },
2676
+ { name: "pause", type: "boolean", default: false }
2677
+ ]
2678
+ }
2679
+ ],
2680
+ stateMachine: {
2681
+ initial: "Ready",
2682
+ states: [
2683
+ { name: "Ready", isInitial: true }
2684
+ ],
2685
+ events: [
2686
+ { key: "KEY_DOWN" },
2687
+ { key: "KEY_UP" },
2688
+ { key: "TOUCH_START" },
2689
+ { key: "TOUCH_END" },
2690
+ { key: "RESET" }
2691
+ ],
2692
+ transitions: [
2693
+ {
2694
+ event: "KEY_DOWN",
2695
+ effects: [
2696
+ [
2697
+ "if",
2698
+ ["or", ["=", "@payload.key", "ArrowLeft"], ["=", "@payload.key", "a"]],
2699
+ ["set", "@entity.left", true]
2700
+ ],
2701
+ [
2702
+ "if",
2703
+ ["or", ["=", "@payload.key", "ArrowRight"], ["=", "@payload.key", "d"]],
2704
+ ["set", "@entity.right", true]
2705
+ ],
2706
+ [
2707
+ "if",
2708
+ ["or", ["=", "@payload.key", "ArrowUp"], ["=", "@payload.key", "w"]],
2709
+ ["set", "@entity.up", true]
2710
+ ],
2711
+ [
2712
+ "if",
2713
+ ["or", ["=", "@payload.key", "ArrowDown"], ["=", "@payload.key", "s"]],
2714
+ ["set", "@entity.down", true]
2715
+ ],
2716
+ [
2717
+ "if",
2718
+ ["=", "@payload.key", " "],
2719
+ ["set", "@entity.jump", true]
2720
+ ],
2721
+ [
2722
+ "if",
2723
+ ["or", ["=", "@payload.key", "Enter"], ["=", "@payload.key", "e"]],
2724
+ ["set", "@entity.action", true]
2725
+ ],
2726
+ [
2727
+ "if",
2728
+ ["or", ["=", "@payload.key", "Escape"], ["=", "@payload.key", "p"]],
2729
+ ["set", "@entity.pause", true]
2730
+ ]
2731
+ ]
2732
+ },
2733
+ {
2734
+ event: "KEY_UP",
2735
+ effects: [
2736
+ [
2737
+ "if",
2738
+ ["or", ["=", "@payload.key", "ArrowLeft"], ["=", "@payload.key", "a"]],
2739
+ ["set", "@entity.left", false]
2740
+ ],
2741
+ [
2742
+ "if",
2743
+ ["or", ["=", "@payload.key", "ArrowRight"], ["=", "@payload.key", "d"]],
2744
+ ["set", "@entity.right", false]
2745
+ ],
2746
+ [
2747
+ "if",
2748
+ ["or", ["=", "@payload.key", "ArrowUp"], ["=", "@payload.key", "w"]],
2749
+ ["set", "@entity.up", false]
2750
+ ],
2751
+ [
2752
+ "if",
2753
+ ["or", ["=", "@payload.key", "ArrowDown"], ["=", "@payload.key", "s"]],
2754
+ ["set", "@entity.down", false]
2755
+ ],
2756
+ [
2757
+ "if",
2758
+ ["=", "@payload.key", " "],
2759
+ ["set", "@entity.jump", false]
2760
+ ],
2761
+ [
2762
+ "if",
2763
+ ["or", ["=", "@payload.key", "Enter"], ["=", "@payload.key", "e"]],
2764
+ ["set", "@entity.action", false]
2765
+ ],
2766
+ [
2767
+ "if",
2768
+ ["or", ["=", "@payload.key", "Escape"], ["=", "@payload.key", "p"]],
2769
+ ["set", "@entity.pause", false]
2770
+ ]
2771
+ ]
2772
+ },
2773
+ {
2774
+ event: "RESET",
2775
+ effects: [
2776
+ ["set", "@entity.left", false],
2777
+ ["set", "@entity.right", false],
2778
+ ["set", "@entity.up", false],
2779
+ ["set", "@entity.down", false],
2780
+ ["set", "@entity.jump", false],
2781
+ ["set", "@entity.action", false],
2782
+ ["set", "@entity.pause", false]
2783
+ ]
2784
+ }
2785
+ ]
2786
+ },
2787
+ configSchema: {
2788
+ required: [],
2789
+ optional: [
2790
+ { name: "keyMap", type: "object", description: "Key to action mapping", default: {} }
2791
+ ]
2792
+ }
2793
+ };
2794
+ var COLLISION_BEHAVIOR = {
2795
+ name: "std/Collision",
2796
+ category: "game-core",
2797
+ description: "Collision detection and response configuration",
2798
+ suggestedFor: [
2799
+ "Solid platforms",
2800
+ "Trigger zones",
2801
+ "Collectibles",
2802
+ "Hazards"
2803
+ ],
2804
+ dataEntities: [
2805
+ {
2806
+ name: "CollisionState",
2807
+ runtime: true,
2808
+ fields: [
2809
+ { name: "isColliding", type: "boolean", default: false },
2810
+ { name: "collidingWith", type: "array", default: [] }
2811
+ ]
2812
+ }
2813
+ ],
2814
+ stateMachine: {
2815
+ initial: "Active",
2816
+ states: [
2817
+ { name: "Active", isInitial: true },
2818
+ { name: "Disabled" }
2819
+ ],
2820
+ events: [
2821
+ { key: "COLLISION" },
2822
+ { key: "TRIGGER_ENTER" },
2823
+ { key: "TRIGGER_EXIT" },
2824
+ { key: "ENABLE" },
2825
+ { key: "DISABLE" }
2826
+ ],
2827
+ transitions: [
2828
+ {
2829
+ from: "Active",
2830
+ event: "COLLISION",
2831
+ effects: [
2832
+ ["set", "@entity.isColliding", true],
2833
+ ["set", "@entity.collidingWith", ["array/append", "@entity.collidingWith", "@payload.entityId"]],
2834
+ [
2835
+ "if",
2836
+ "@config.onCollision",
2837
+ ["emit", "@config.onCollision", { entityId: "@payload.entityId", side: "@payload.side" }]
2838
+ ]
2839
+ ]
2840
+ },
2841
+ {
2842
+ from: "Active",
2843
+ event: "TRIGGER_ENTER",
2844
+ effects: [
2845
+ [
2846
+ "if",
2847
+ "@config.onTrigger",
2848
+ ["emit", "@config.onTrigger", { entityId: "@payload.entityId", action: "enter" }]
2849
+ ]
2850
+ ]
2851
+ },
2852
+ {
2853
+ from: "Active",
2854
+ event: "TRIGGER_EXIT",
2855
+ effects: [
2856
+ ["set", "@entity.collidingWith", ["array/filter", "@entity.collidingWith", ["fn", "id", ["!=", "@id", "@payload.entityId"]]]],
2857
+ [
2858
+ "if",
2859
+ ["=", ["array/len", "@entity.collidingWith"], 0],
2860
+ ["set", "@entity.isColliding", false]
2861
+ ]
2862
+ ]
2863
+ },
2864
+ {
2865
+ from: "Active",
2866
+ to: "Disabled",
2867
+ event: "DISABLE",
2868
+ effects: [
2869
+ ["set", "@entity.isColliding", false],
2870
+ ["set", "@entity.collidingWith", []]
2871
+ ]
2872
+ },
2873
+ {
2874
+ from: "Disabled",
2875
+ to: "Active",
2876
+ event: "ENABLE",
2877
+ effects: []
2878
+ }
2879
+ ]
2880
+ },
2881
+ configSchema: {
2882
+ required: [],
2883
+ optional: [
2884
+ { name: "type", type: "string", description: "Collision type", default: "solid", enum: ["solid", "trigger"] },
2885
+ { name: "layer", type: "string", description: "Collision layer", default: "default" },
2886
+ { name: "collidesWith", type: "array", description: "Layers to collide with", default: ["default"] },
2887
+ { name: "onCollision", type: "event", description: "Event to emit on collision" },
2888
+ { name: "onTrigger", type: "event", description: "Event to emit on trigger" }
2889
+ ]
2890
+ }
2891
+ };
2892
+ var GAME_CORE_BEHAVIORS = [
2893
+ GAME_LOOP_BEHAVIOR,
2894
+ PHYSICS_2D_BEHAVIOR,
2895
+ INPUT_BEHAVIOR,
2896
+ COLLISION_BEHAVIOR
2897
+ ];
2898
+
2899
+ // behaviors/game-entity.ts
2900
+ var HEALTH_BEHAVIOR = {
2901
+ name: "std/Health",
2902
+ category: "game-entity",
2903
+ description: "Entity health with damage, healing, invulnerability, and death",
2904
+ suggestedFor: [
2905
+ "Player characters",
2906
+ "Enemies",
2907
+ "Destructible objects",
2908
+ "Bosses"
2909
+ ],
2910
+ dataEntities: [
2911
+ {
2912
+ name: "HealthState",
2913
+ runtime: true,
2914
+ fields: [
2915
+ { name: "currentHealth", type: "number", default: 100 },
2916
+ { name: "maxHealth", type: "number", default: 100 },
2917
+ { name: "isInvulnerable", type: "boolean", default: false },
2918
+ { name: "lastDamageTime", type: "number", default: 0 }
2919
+ ]
2920
+ }
2921
+ ],
2922
+ stateMachine: {
2923
+ initial: "Alive",
2924
+ states: [
2925
+ { name: "Alive", isInitial: true },
2926
+ { name: "Damaged" },
2927
+ { name: "Invulnerable" },
2928
+ { name: "Dead" }
2929
+ ],
2930
+ events: [
2931
+ { key: "INIT" },
2932
+ { key: "DAMAGE" },
2933
+ { key: "HEAL" },
2934
+ { key: "DIE" },
2935
+ { key: "RESPAWN" },
2936
+ { key: "INVULNERABILITY_END" }
2937
+ ],
2938
+ transitions: [
2939
+ {
2940
+ from: "*",
2941
+ to: "Alive",
2942
+ event: "INIT",
2943
+ effects: [
2944
+ ["set", "@entity.currentHealth", "@config.maxHealth"],
2945
+ ["set", "@entity.maxHealth", "@config.maxHealth"],
2946
+ ["set", "@entity.isInvulnerable", false],
2947
+ ["render", "hud.health", "health-bar", {
2948
+ current: "@entity.currentHealth",
2949
+ max: "@entity.maxHealth"
2950
+ }]
2951
+ ]
2952
+ },
2953
+ {
2954
+ from: "Alive",
2955
+ to: "Damaged",
2956
+ event: "DAMAGE",
2957
+ guard: ["not", "@entity.isInvulnerable"],
2958
+ effects: [
2959
+ ["set", "@entity.currentHealth", ["math/max", 0, ["-", "@entity.currentHealth", "@payload.amount"]]],
2960
+ ["set", "@entity.lastDamageTime", "@now"],
2961
+ [
2962
+ "if",
2963
+ ["<=", "@entity.currentHealth", 0],
2964
+ ["emit", "DIE"],
2965
+ [
2966
+ "do",
2967
+ ["set", "@entity.isInvulnerable", true],
2968
+ ["render", "entity.flash", "damage-flash", {}]
2969
+ ]
2970
+ ]
2971
+ ]
2972
+ },
2973
+ {
2974
+ from: ["Damaged", "Invulnerable"],
2975
+ to: "Alive",
2976
+ event: "INVULNERABILITY_END",
2977
+ effects: [
2978
+ ["set", "@entity.isInvulnerable", false]
2979
+ ]
2980
+ },
2981
+ {
2982
+ from: ["Alive", "Damaged", "Invulnerable"],
2983
+ event: "HEAL",
2984
+ effects: [
2985
+ ["set", "@entity.currentHealth", ["math/min", "@entity.maxHealth", ["+", "@entity.currentHealth", "@payload.amount"]]],
2986
+ ["render", "entity.effect", "heal-effect", {}]
2987
+ ]
2988
+ },
2989
+ {
2990
+ from: ["Alive", "Damaged", "Invulnerable"],
2991
+ to: "Dead",
2992
+ event: "DIE",
2993
+ effects: [
2994
+ ["set", "@entity.currentHealth", 0],
2995
+ ["emit", "@config.onDeath", { entityId: "@entity.id" }],
2996
+ ["render", "entity.sprite", "death-animation", {}]
2997
+ ]
2998
+ },
2999
+ {
3000
+ from: "Dead",
3001
+ to: "Alive",
3002
+ event: "RESPAWN",
3003
+ effects: [
3004
+ ["emit", "INIT"]
3005
+ ]
3006
+ }
3007
+ ]
3008
+ },
3009
+ ticks: [
3010
+ {
3011
+ name: "InvulnerabilityTimer",
3012
+ interval: "frame",
3013
+ guard: ["and", "@entity.isInvulnerable", [">", ["-", "@now", "@entity.lastDamageTime"], "@config.invulnerabilityTime"]],
3014
+ effects: [
3015
+ ["emit", "INVULNERABILITY_END"]
3016
+ ]
3017
+ }
3018
+ ],
3019
+ configSchema: {
3020
+ required: [
3021
+ { name: "maxHealth", type: "number", description: "Maximum health points" }
3022
+ ],
3023
+ optional: [
3024
+ { name: "invulnerabilityTime", type: "number", description: "Invulnerability duration after damage (ms)", default: 500 },
3025
+ { name: "onDeath", type: "event", description: "Event to emit on death", default: "ENTITY_DIED" },
3026
+ { name: "showHealthBar", type: "boolean", description: "Render health bar", default: true }
3027
+ ]
3028
+ }
3029
+ };
3030
+ var SCORE_BEHAVIOR = {
3031
+ name: "std/Score",
3032
+ category: "game-entity",
3033
+ description: "Score tracking with points, combos, and multipliers",
3034
+ suggestedFor: [
3035
+ "Arcade games",
3036
+ "Puzzle games",
3037
+ "Platformers with collectibles",
3038
+ "Competitive games"
3039
+ ],
3040
+ dataEntities: [
3041
+ {
3042
+ name: "ScoreState",
3043
+ runtime: true,
3044
+ singleton: true,
3045
+ fields: [
3046
+ { name: "currentScore", type: "number", default: 0 },
3047
+ { name: "highScore", type: "number", default: 0 },
3048
+ { name: "comboCount", type: "number", default: 0 },
3049
+ { name: "multiplier", type: "number", default: 1 },
3050
+ { name: "lastScoreTime", type: "number", default: 0 }
3051
+ ]
3052
+ }
3053
+ ],
3054
+ stateMachine: {
3055
+ initial: "Active",
3056
+ states: [
3057
+ { name: "Active", isInitial: true }
3058
+ ],
3059
+ events: [
3060
+ { key: "INIT" },
3061
+ { key: "ADD_POINTS" },
3062
+ { key: "COMBO_HIT" },
3063
+ { key: "COMBO_BREAK" },
3064
+ { key: "RESET" },
3065
+ { key: "SAVE_HIGH_SCORE" }
3066
+ ],
3067
+ transitions: [
3068
+ {
3069
+ from: "*",
3070
+ event: "INIT",
3071
+ effects: [
3072
+ ["set", "@entity.currentScore", 0],
3073
+ ["set", "@entity.comboCount", 0],
3074
+ ["set", "@entity.multiplier", 1],
3075
+ ["render", "hud.score", "score-display", {
3076
+ score: "@entity.currentScore",
3077
+ highScore: "@entity.highScore",
3078
+ combo: "@entity.comboCount",
3079
+ multiplier: "@entity.multiplier"
3080
+ }]
3081
+ ]
3082
+ },
3083
+ {
3084
+ event: "ADD_POINTS",
3085
+ effects: [
3086
+ ["set", "@entity.currentScore", ["+", "@entity.currentScore", ["*", "@payload.points", "@entity.multiplier"]]],
3087
+ ["set", "@entity.lastScoreTime", "@now"],
3088
+ ["render", "entity.effect", "score-popup", {
3089
+ points: ["*", "@payload.points", "@entity.multiplier"],
3090
+ position: "@payload.position"
3091
+ }]
3092
+ ]
3093
+ },
3094
+ {
3095
+ event: "COMBO_HIT",
3096
+ effects: [
3097
+ ["set", "@entity.comboCount", ["+", "@entity.comboCount", 1]],
3098
+ ["set", "@entity.multiplier", ["math/min", "@config.maxMultiplier", ["+", 1, ["/", "@entity.comboCount", 5]]]],
3099
+ ["set", "@entity.lastScoreTime", "@now"]
3100
+ ]
3101
+ },
3102
+ {
3103
+ event: "COMBO_BREAK",
3104
+ effects: [
3105
+ ["set", "@entity.comboCount", 0],
3106
+ ["set", "@entity.multiplier", 1]
3107
+ ]
3108
+ },
3109
+ {
3110
+ event: "RESET",
3111
+ effects: [
3112
+ [
3113
+ "if",
3114
+ [">", "@entity.currentScore", "@entity.highScore"],
3115
+ ["set", "@entity.highScore", "@entity.currentScore"]
3116
+ ],
3117
+ ["emit", "INIT"]
3118
+ ]
3119
+ },
3120
+ {
3121
+ event: "SAVE_HIGH_SCORE",
3122
+ guard: [">", "@entity.currentScore", "@entity.highScore"],
3123
+ effects: [
3124
+ ["set", "@entity.highScore", "@entity.currentScore"],
3125
+ ["persist", "save", "HighScore", { score: "@entity.highScore" }]
3126
+ ]
3127
+ }
3128
+ ]
3129
+ },
3130
+ ticks: [
3131
+ {
3132
+ name: "ComboTimeout",
3133
+ interval: "frame",
3134
+ guard: ["and", [">", "@entity.comboCount", 0], [">", ["-", "@now", "@entity.lastScoreTime"], "@config.comboTimeWindow"]],
3135
+ effects: [
3136
+ ["emit", "COMBO_BREAK"]
3137
+ ]
3138
+ }
3139
+ ],
3140
+ configSchema: {
3141
+ required: [],
3142
+ optional: [
3143
+ { name: "comboTimeWindow", type: "number", description: "Time window for combos (ms)", default: 2e3 },
3144
+ { name: "maxMultiplier", type: "number", description: "Maximum combo multiplier", default: 10 },
3145
+ { name: "persistHighScore", type: "boolean", description: "Save high score to storage", default: true }
3146
+ ]
3147
+ }
3148
+ };
3149
+ var MOVEMENT_BEHAVIOR = {
3150
+ name: "std/Movement",
3151
+ category: "game-entity",
3152
+ description: "Entity movement with speed and direction",
3153
+ suggestedFor: [
3154
+ "Player characters",
3155
+ "NPCs",
3156
+ "Enemies",
3157
+ "Moving platforms"
3158
+ ],
3159
+ requiredFields: [
3160
+ { name: "x", type: "number", description: "Entity X position" },
3161
+ { name: "y", type: "number", description: "Entity Y position" }
3162
+ ],
3163
+ dataEntities: [
3164
+ {
3165
+ name: "MovementState",
3166
+ runtime: true,
3167
+ fields: [
3168
+ { name: "direction", type: "number", default: 0 },
3169
+ { name: "facingRight", type: "boolean", default: true },
3170
+ { name: "canJump", type: "boolean", default: true }
3171
+ ]
3172
+ }
3173
+ ],
3174
+ stateMachine: {
3175
+ initial: "Idle",
3176
+ states: [
3177
+ { name: "Idle", isInitial: true },
3178
+ { name: "Moving" },
3179
+ { name: "Jumping" },
3180
+ { name: "Falling" }
3181
+ ],
3182
+ events: [
3183
+ { key: "MOVE" },
3184
+ { key: "STOP" },
3185
+ { key: "JUMP" },
3186
+ { key: "LAND" }
3187
+ ],
3188
+ transitions: [
3189
+ {
3190
+ from: "Idle",
3191
+ to: "Moving",
3192
+ event: "MOVE",
3193
+ effects: [
3194
+ ["set", "@entity.direction", "@payload.direction"],
3195
+ [
3196
+ "if",
3197
+ [">", "@payload.direction", 0],
3198
+ ["set", "@entity.facingRight", true]
3199
+ ],
3200
+ [
3201
+ "if",
3202
+ ["<", "@payload.direction", 0],
3203
+ ["set", "@entity.facingRight", false]
3204
+ ]
3205
+ ]
3206
+ },
3207
+ {
3208
+ from: "Moving",
3209
+ event: "MOVE",
3210
+ effects: [
3211
+ ["set", "@entity.direction", "@payload.direction"],
3212
+ [
3213
+ "if",
3214
+ [">", "@payload.direction", 0],
3215
+ ["set", "@entity.facingRight", true]
3216
+ ],
3217
+ [
3218
+ "if",
3219
+ ["<", "@payload.direction", 0],
3220
+ ["set", "@entity.facingRight", false]
3221
+ ]
3222
+ ]
3223
+ },
3224
+ {
3225
+ from: "Moving",
3226
+ to: "Idle",
3227
+ event: "STOP",
3228
+ effects: [
3229
+ ["set", "@entity.direction", 0]
3230
+ ]
3231
+ },
3232
+ {
3233
+ from: ["Idle", "Moving"],
3234
+ to: "Jumping",
3235
+ event: "JUMP",
3236
+ guard: "@entity.canJump",
3237
+ effects: [
3238
+ ["set", "@entity.canJump", false],
3239
+ ["emit", "APPLY_FORCE", { fx: 0, fy: "@config.jumpForce" }]
3240
+ ]
3241
+ },
3242
+ {
3243
+ from: ["Jumping", "Falling"],
3244
+ to: "Idle",
3245
+ event: "LAND",
3246
+ effects: [
3247
+ ["set", "@entity.canJump", true],
3248
+ [
3249
+ "if",
3250
+ ["!=", "@entity.direction", 0],
3251
+ ["emit", "MOVE", { direction: "@entity.direction" }]
3252
+ ]
3253
+ ]
3254
+ }
3255
+ ]
3256
+ },
3257
+ ticks: [
3258
+ {
3259
+ name: "ApplyMovement",
3260
+ interval: "frame",
3261
+ guard: ["!=", "@entity.direction", 0],
3262
+ effects: [
3263
+ ["set", "@entity.x", ["+", "@entity.x", ["*", "@entity.direction", "@config.moveSpeed"]]]
3264
+ ]
3265
+ }
3266
+ ],
3267
+ configSchema: {
3268
+ required: [],
3269
+ optional: [
3270
+ { name: "moveSpeed", type: "number", description: "Movement speed (pixels/frame)", default: 5 },
3271
+ { name: "jumpForce", type: "number", description: "Jump velocity", default: -12 },
3272
+ { name: "acceleration", type: "number", description: "Acceleration rate", default: 0.5 },
3273
+ { name: "deceleration", type: "number", description: "Deceleration rate", default: 0.3 }
3274
+ ]
3275
+ }
3276
+ };
3277
+ var COMBAT_BEHAVIOR = {
3278
+ name: "std/Combat",
3279
+ category: "game-entity",
3280
+ description: "Combat system with attacks, cooldowns, and hitboxes",
3281
+ suggestedFor: [
3282
+ "Fighting games",
3283
+ "Action RPGs",
3284
+ "Beat-em-ups",
3285
+ "Boss encounters"
3286
+ ],
3287
+ dataEntities: [
3288
+ {
3289
+ name: "CombatState",
3290
+ runtime: true,
3291
+ fields: [
3292
+ { name: "isAttacking", type: "boolean", default: false },
3293
+ { name: "attackStartTime", type: "number", default: 0 },
3294
+ { name: "hitEntities", type: "array", default: [] }
3295
+ ]
3296
+ }
3297
+ ],
3298
+ stateMachine: {
3299
+ initial: "Ready",
3300
+ states: [
3301
+ { name: "Ready", isInitial: true },
3302
+ { name: "Attacking" },
3303
+ { name: "Cooldown" }
3304
+ ],
3305
+ events: [
3306
+ { key: "ATTACK" },
3307
+ { key: "ATTACK_END" },
3308
+ { key: "HIT_CONNECT" },
3309
+ { key: "COOLDOWN_END" }
3310
+ ],
3311
+ transitions: [
3312
+ {
3313
+ from: "Ready",
3314
+ to: "Attacking",
3315
+ event: "ATTACK",
3316
+ effects: [
3317
+ ["set", "@entity.isAttacking", true],
3318
+ ["set", "@entity.attackStartTime", "@now"],
3319
+ ["set", "@entity.hitEntities", []],
3320
+ ["render", "entity.sprite", "attack-animation", {}],
3321
+ ["render", "entity.hitbox", "hitbox", {
3322
+ active: true,
3323
+ offset: "@config.hitboxOffset",
3324
+ size: "@config.hitboxSize"
3325
+ }]
3326
+ ]
3327
+ },
3328
+ {
3329
+ from: "Attacking",
3330
+ event: "HIT_CONNECT",
3331
+ guard: ["not", ["array/includes", "@entity.hitEntities", "@payload.entityId"]],
3332
+ effects: [
3333
+ ["set", "@entity.hitEntities", ["array/append", "@entity.hitEntities", "@payload.entityId"]],
3334
+ ["emit", "DAMAGE", { target: "@payload.entityId", amount: "@config.attackDamage" }],
3335
+ ["render", "effect.impact", "hit-effect", { position: "@payload.position" }]
3336
+ ]
3337
+ },
3338
+ {
3339
+ from: "Attacking",
3340
+ to: "Cooldown",
3341
+ event: "ATTACK_END",
3342
+ effects: [
3343
+ ["set", "@entity.isAttacking", false],
3344
+ ["render", "entity.hitbox", null]
3345
+ ]
3346
+ },
3347
+ {
3348
+ from: "Cooldown",
3349
+ to: "Ready",
3350
+ event: "COOLDOWN_END",
3351
+ effects: []
3352
+ }
3353
+ ]
3354
+ },
3355
+ ticks: [
3356
+ {
3357
+ name: "AttackDuration",
3358
+ interval: "frame",
3359
+ guard: ["and", "@entity.isAttacking", [">", ["-", "@now", "@entity.attackStartTime"], "@config.attackDuration"]],
3360
+ effects: [
3361
+ ["emit", "ATTACK_END"]
3362
+ ]
3363
+ },
3364
+ {
3365
+ name: "CooldownTimer",
3366
+ interval: "frame",
3367
+ guard: ["and", ["=", "@state", "Cooldown"], [">", ["-", "@now", "@entity.attackStartTime"], ["+", "@config.attackDuration", "@config.cooldownDuration"]]],
3368
+ effects: [
3369
+ ["emit", "COOLDOWN_END"]
3370
+ ]
3371
+ }
3372
+ ],
3373
+ configSchema: {
3374
+ required: [],
3375
+ optional: [
3376
+ { name: "attackDamage", type: "number", description: "Damage per attack", default: 10 },
3377
+ { name: "attackDuration", type: "number", description: "Attack animation duration (ms)", default: 200 },
3378
+ { name: "cooldownDuration", type: "number", description: "Cooldown between attacks (ms)", default: 300 },
3379
+ { name: "hitboxOffset", type: "object", description: "Hitbox offset from entity", default: { x: 20, y: 0 } },
3380
+ { name: "hitboxSize", type: "object", description: "Hitbox dimensions", default: { width: 30, height: 40 } }
3381
+ ]
3382
+ }
3383
+ };
3384
+ var INVENTORY_BEHAVIOR = {
3385
+ name: "std/Inventory",
3386
+ category: "game-entity",
3387
+ description: "Item collection, storage, and usage",
3388
+ suggestedFor: [
3389
+ "RPGs",
3390
+ "Adventure games",
3391
+ "Survival games",
3392
+ "Collectible-based games"
3393
+ ],
3394
+ dataEntities: [
3395
+ {
3396
+ name: "InventoryState",
3397
+ runtime: true,
3398
+ fields: [
3399
+ { name: "items", type: "array", default: [] },
3400
+ { name: "selectedSlot", type: "number", default: 0 },
3401
+ { name: "isOpen", type: "boolean", default: false },
3402
+ { name: "equipped", type: "object", default: {} }
3403
+ ]
3404
+ }
3405
+ ],
3406
+ stateMachine: {
3407
+ initial: "Empty",
3408
+ states: [
3409
+ { name: "Empty", isInitial: true },
3410
+ { name: "HasItems" },
3411
+ { name: "Full" }
3412
+ ],
3413
+ events: [
3414
+ { key: "COLLECT" },
3415
+ { key: "USE" },
3416
+ { key: "DROP" },
3417
+ { key: "EQUIP" },
3418
+ { key: "UNEQUIP" },
3419
+ { key: "OPEN" },
3420
+ { key: "CLOSE" },
3421
+ { key: "INVENTORY_EMPTY" }
3422
+ ],
3423
+ transitions: [
3424
+ {
3425
+ from: ["Empty", "HasItems"],
3426
+ to: "HasItems",
3427
+ event: "COLLECT",
3428
+ guard: ["<", ["array/len", "@entity.items"], "@config.maxSlots"],
3429
+ effects: [
3430
+ ["set", "@entity.items", ["array/append", "@entity.items", "@payload.item"]],
3431
+ ["render", "effect.collect", "collect-effect", { item: "@payload.item" }],
3432
+ ["notify", { type: "info", message: ["str/concat", "Collected ", "@payload.item.name"] }]
3433
+ ]
3434
+ },
3435
+ {
3436
+ from: "HasItems",
3437
+ event: "USE",
3438
+ effects: [
3439
+ [
3440
+ "let",
3441
+ [["item", ["array/nth", "@entity.items", "@payload.slot"]]],
3442
+ [
3443
+ "if",
3444
+ "@item.onUse",
3445
+ ["emit", "@item.onUse", { item: "@item" }]
3446
+ ],
3447
+ [
3448
+ "if",
3449
+ "@item.consumable",
3450
+ ["set", "@entity.items", ["array/filter", "@entity.items", ["fn", "i", "idx", ["!=", "@idx", "@payload.slot"]]]]
3451
+ ]
3452
+ ],
3453
+ [
3454
+ "if",
3455
+ ["=", ["array/len", "@entity.items"], 0],
3456
+ ["emit", "INVENTORY_EMPTY"]
3457
+ ]
3458
+ ]
3459
+ },
3460
+ {
3461
+ from: "HasItems",
3462
+ event: "DROP",
3463
+ effects: [
3464
+ [
3465
+ "let",
3466
+ [["item", ["array/nth", "@entity.items", "@payload.slot"]]],
3467
+ ["set", "@entity.items", ["array/filter", "@entity.items", ["fn", "i", "idx", ["!=", "@idx", "@payload.slot"]]]],
3468
+ ["emit", "ITEM_DROPPED", { item: "@item", position: { x: "@entity.x", y: "@entity.y" } }]
3469
+ ],
3470
+ [
3471
+ "if",
3472
+ ["=", ["array/len", "@entity.items"], 0],
3473
+ ["emit", "INVENTORY_EMPTY"]
3474
+ ]
3475
+ ]
3476
+ },
3477
+ {
3478
+ from: "HasItems",
3479
+ to: "Empty",
3480
+ event: "INVENTORY_EMPTY",
3481
+ effects: []
3482
+ },
3483
+ {
3484
+ event: "EQUIP",
3485
+ effects: [
3486
+ ["set", "@entity.equipped", ["object/set", "@entity.equipped", "@payload.slot", "@payload.item"]],
3487
+ ["emit", "STATS_UPDATED", { equipped: "@entity.equipped" }]
3488
+ ]
3489
+ },
3490
+ {
3491
+ event: "UNEQUIP",
3492
+ effects: [
3493
+ ["set", "@entity.equipped", ["object/remove", "@entity.equipped", "@payload.slot"]],
3494
+ ["emit", "STATS_UPDATED", { equipped: "@entity.equipped" }]
3495
+ ]
3496
+ },
3497
+ {
3498
+ event: "OPEN",
3499
+ effects: [
3500
+ ["set", "@entity.isOpen", true],
3501
+ ["render", "overlay.inventory", "inventory-panel", {
3502
+ items: "@entity.items",
3503
+ selectedSlot: "@entity.selectedSlot",
3504
+ equipped: "@entity.equipped",
3505
+ maxSlots: "@config.maxSlots",
3506
+ onUse: "USE",
3507
+ onDrop: "DROP",
3508
+ onEquip: "EQUIP",
3509
+ onClose: "CLOSE"
3510
+ }]
3511
+ ]
3512
+ },
3513
+ {
3514
+ event: "CLOSE",
3515
+ effects: [
3516
+ ["set", "@entity.isOpen", false],
3517
+ ["render", "overlay.inventory", null]
3518
+ ]
3519
+ }
3520
+ ]
3521
+ },
3522
+ configSchema: {
3523
+ required: [],
3524
+ optional: [
3525
+ { name: "maxSlots", type: "number", description: "Maximum inventory slots", default: 20 },
3526
+ { name: "stackable", type: "boolean", description: "Allow item stacking", default: true },
3527
+ { name: "maxStack", type: "number", description: "Maximum stack size", default: 99 }
3528
+ ]
3529
+ }
3530
+ };
3531
+ var GAME_ENTITY_BEHAVIORS = [
3532
+ HEALTH_BEHAVIOR,
3533
+ SCORE_BEHAVIOR,
3534
+ MOVEMENT_BEHAVIOR,
3535
+ COMBAT_BEHAVIOR,
3536
+ INVENTORY_BEHAVIOR
3537
+ ];
3538
+
3539
+ // behaviors/game-ui.ts
3540
+ var GAME_FLOW_BEHAVIOR = {
3541
+ name: "std/GameFlow",
3542
+ category: "game-ui",
3543
+ description: "Master game flow: menu, play, pause, game over, victory",
3544
+ suggestedFor: [
3545
+ "All games",
3546
+ "Game state management",
3547
+ "Menu systems",
3548
+ "Win/lose conditions"
3549
+ ],
3550
+ dataEntities: [
3551
+ {
3552
+ name: "GameFlowState",
3553
+ runtime: true,
3554
+ singleton: true,
3555
+ fields: [
3556
+ { name: "playTime", type: "number", default: 0 },
3557
+ { name: "attempts", type: "number", default: 0 },
3558
+ { name: "lastState", type: "string", default: "Menu" }
3559
+ ]
3560
+ }
3561
+ ],
3562
+ stateMachine: {
3563
+ initial: "Menu",
3564
+ states: [
3565
+ { name: "Menu", isInitial: true },
3566
+ { name: "Playing" },
3567
+ { name: "Paused" },
3568
+ { name: "GameOver" },
3569
+ { name: "Victory" }
3570
+ ],
3571
+ events: [
3572
+ { key: "START" },
3573
+ { key: "PAUSE" },
3574
+ { key: "RESUME" },
3575
+ { key: "GAME_OVER" },
3576
+ { key: "VICTORY" },
3577
+ { key: "RESTART" },
3578
+ { key: "QUIT" }
3579
+ ],
3580
+ transitions: [
3581
+ {
3582
+ from: "*",
3583
+ to: "Menu",
3584
+ event: "QUIT",
3585
+ effects: [
3586
+ ["emit", "STOP"],
3587
+ ["render", "screen", "game-menu", {
3588
+ title: "@config.title",
3589
+ onStart: "START"
3590
+ }]
3591
+ ]
3592
+ },
3593
+ {
3594
+ from: "Menu",
3595
+ to: "Playing",
3596
+ event: "START",
3597
+ effects: [
3598
+ ["set", "@entity.attempts", ["+", "@entity.attempts", 1]],
3599
+ ["set", "@entity.playTime", 0],
3600
+ ["emit", "GAME_LOOP_START"],
3601
+ ["render", "screen", null],
3602
+ ["render", "canvas", "game-canvas", {}]
3603
+ ]
3604
+ },
3605
+ {
3606
+ from: "Playing",
3607
+ to: "Paused",
3608
+ event: "PAUSE",
3609
+ guard: "@config.allowPause",
3610
+ effects: [
3611
+ ["set", "@entity.lastState", "Playing"],
3612
+ ["emit", "GAME_LOOP_PAUSE"],
3613
+ ["render", "overlay", "game-pause-overlay", {
3614
+ onResume: "RESUME",
3615
+ onQuit: "QUIT",
3616
+ playTime: "@entity.playTime"
3617
+ }]
3618
+ ]
3619
+ },
3620
+ {
3621
+ from: "Paused",
3622
+ to: "Playing",
3623
+ event: "RESUME",
3624
+ effects: [
3625
+ ["emit", "GAME_LOOP_RESUME"],
3626
+ ["render", "overlay", null]
3627
+ ]
3628
+ },
3629
+ {
3630
+ from: "Playing",
3631
+ to: "GameOver",
3632
+ event: "GAME_OVER",
3633
+ effects: [
3634
+ ["emit", "STOP"],
3635
+ ["render", "overlay", "game-over-screen", {
3636
+ victory: false,
3637
+ playTime: "@entity.playTime",
3638
+ attempts: "@entity.attempts",
3639
+ onRestart: "RESTART",
3640
+ onQuit: "QUIT"
3641
+ }]
3642
+ ]
3643
+ },
3644
+ {
3645
+ from: "Playing",
3646
+ to: "Victory",
3647
+ event: "VICTORY",
3648
+ effects: [
3649
+ ["emit", "STOP"],
3650
+ ["render", "overlay", "game-over-screen", {
3651
+ victory: true,
3652
+ playTime: "@entity.playTime",
3653
+ attempts: "@entity.attempts",
3654
+ onRestart: "RESTART",
3655
+ onQuit: "QUIT"
3656
+ }]
3657
+ ]
3658
+ },
3659
+ {
3660
+ from: ["GameOver", "Victory"],
3661
+ to: "Playing",
3662
+ event: "RESTART",
3663
+ effects: [
3664
+ ["render", "overlay", null],
3665
+ ["emit", "GAME_RESET"],
3666
+ ["emit", "START"]
3667
+ ]
3668
+ }
3669
+ ]
3670
+ },
3671
+ configSchema: {
3672
+ required: [],
3673
+ optional: [
3674
+ { name: "title", type: "string", description: "Game title", default: "Game" },
3675
+ { name: "showMenu", type: "boolean", description: "Show main menu", default: true },
3676
+ { name: "allowPause", type: "boolean", description: "Allow pausing", default: true }
3677
+ ]
3678
+ }
3679
+ };
3680
+ var DIALOGUE_BEHAVIOR = {
3681
+ name: "std/Dialogue",
3682
+ category: "game-ui",
3683
+ description: "NPC dialogue system with branching conversations",
3684
+ suggestedFor: [
3685
+ "RPGs",
3686
+ "Adventure games",
3687
+ "Story-driven games",
3688
+ "NPC interactions"
3689
+ ],
3690
+ dataEntities: [
3691
+ {
3692
+ name: "DialogueState",
3693
+ runtime: true,
3694
+ fields: [
3695
+ { name: "dialogueTree", type: "array", default: [] },
3696
+ { name: "currentNode", type: "number", default: 0 },
3697
+ { name: "displayedText", type: "string", default: "" },
3698
+ { name: "isTyping", type: "boolean", default: false },
3699
+ { name: "speaker", type: "string", default: "" },
3700
+ { name: "typeIndex", type: "number", default: 0 },
3701
+ { name: "lastTypeTime", type: "number", default: 0 }
3702
+ ]
3703
+ }
3704
+ ],
3705
+ stateMachine: {
3706
+ initial: "Hidden",
3707
+ states: [
3708
+ { name: "Hidden", isInitial: true },
3709
+ { name: "Typing" },
3710
+ { name: "Showing" },
3711
+ { name: "Choice" }
3712
+ ],
3713
+ events: [
3714
+ { key: "SHOW" },
3715
+ { key: "NEXT" },
3716
+ { key: "SELECT_CHOICE" },
3717
+ { key: "SKIP" },
3718
+ { key: "CLOSE" },
3719
+ { key: "TYPE_CHAR" },
3720
+ { key: "TYPE_COMPLETE" }
3721
+ ],
3722
+ transitions: [
3723
+ {
3724
+ from: "Hidden",
3725
+ to: "Typing",
3726
+ event: "SHOW",
3727
+ effects: [
3728
+ ["set", "@entity.dialogueTree", "@payload.dialogue"],
3729
+ ["set", "@entity.currentNode", 0],
3730
+ ["set", "@entity.isTyping", true],
3731
+ ["set", "@entity.displayedText", ""],
3732
+ ["set", "@entity.typeIndex", 0],
3733
+ ["set", "@entity.lastTypeTime", "@now"],
3734
+ ["emit", "GAME_PAUSE"],
3735
+ ["render", "overlay.dialogue", "dialogue-box", {
3736
+ speaker: "@entity.speaker",
3737
+ text: "@entity.displayedText",
3738
+ isTyping: "@entity.isTyping",
3739
+ onNext: "NEXT",
3740
+ onSkip: "SKIP"
3741
+ }]
3742
+ ]
3743
+ },
3744
+ {
3745
+ from: "Typing",
3746
+ event: "TYPE_CHAR",
3747
+ effects: [
3748
+ [
3749
+ "let",
3750
+ [["currentDialogue", ["array/nth", "@entity.dialogueTree", "@entity.currentNode"]]],
3751
+ [
3752
+ "do",
3753
+ ["set", "@entity.typeIndex", ["+", "@entity.typeIndex", 1]],
3754
+ ["set", "@entity.displayedText", ["str/slice", "@currentDialogue.text", 0, "@entity.typeIndex"]],
3755
+ ["set", "@entity.lastTypeTime", "@now"]
3756
+ ]
3757
+ ]
3758
+ ]
3759
+ },
3760
+ {
3761
+ from: "Typing",
3762
+ to: "Showing",
3763
+ event: "TYPE_COMPLETE",
3764
+ effects: [
3765
+ ["set", "@entity.isTyping", false]
3766
+ ]
3767
+ },
3768
+ {
3769
+ from: "Typing",
3770
+ to: "Showing",
3771
+ event: "SKIP",
3772
+ effects: [
3773
+ [
3774
+ "let",
3775
+ [["currentDialogue", ["array/nth", "@entity.dialogueTree", "@entity.currentNode"]]],
3776
+ [
3777
+ "do",
3778
+ ["set", "@entity.isTyping", false],
3779
+ ["set", "@entity.displayedText", "@currentDialogue.text"]
3780
+ ]
3781
+ ]
3782
+ ]
3783
+ },
3784
+ {
3785
+ from: "Showing",
3786
+ event: "NEXT",
3787
+ guard: ["not", ["object/get", ["array/nth", "@entity.dialogueTree", "@entity.currentNode"], "choices"]],
3788
+ effects: [
3789
+ [
3790
+ "if",
3791
+ [">=", "@entity.currentNode", ["-", ["array/len", "@entity.dialogueTree"], 1]],
3792
+ ["emit", "CLOSE"],
3793
+ [
3794
+ "do",
3795
+ ["set", "@entity.currentNode", ["+", "@entity.currentNode", 1]],
3796
+ ["set", "@entity.isTyping", true],
3797
+ ["set", "@entity.displayedText", ""],
3798
+ ["set", "@entity.typeIndex", 0]
3799
+ ]
3800
+ ]
3801
+ ]
3802
+ },
3803
+ {
3804
+ from: "Showing",
3805
+ to: "Choice",
3806
+ event: "NEXT",
3807
+ guard: ["object/get", ["array/nth", "@entity.dialogueTree", "@entity.currentNode"], "choices"],
3808
+ effects: [
3809
+ [
3810
+ "let",
3811
+ [["currentDialogue", ["array/nth", "@entity.dialogueTree", "@entity.currentNode"]]],
3812
+ ["render", "overlay.dialogue", "dialogue-box", {
3813
+ choices: "@currentDialogue.choices",
3814
+ onSelect: "SELECT_CHOICE"
3815
+ }]
3816
+ ]
3817
+ ]
3818
+ },
3819
+ {
3820
+ from: "Choice",
3821
+ to: "Typing",
3822
+ event: "SELECT_CHOICE",
3823
+ effects: [
3824
+ [
3825
+ "let",
3826
+ [["currentDialogue", ["array/nth", "@entity.dialogueTree", "@entity.currentNode"]]],
3827
+ [
3828
+ "let",
3829
+ [["choice", ["array/nth", "@currentDialogue.choices", "@payload.index"]]],
3830
+ [
3831
+ "do",
3832
+ [
3833
+ "if",
3834
+ "@choice.nextNode",
3835
+ ["set", "@entity.currentNode", "@choice.nextNode"],
3836
+ ["set", "@entity.currentNode", ["+", "@entity.currentNode", 1]]
3837
+ ],
3838
+ [
3839
+ "if",
3840
+ "@choice.effect",
3841
+ ["emit", "@choice.effect"]
3842
+ ]
3843
+ ]
3844
+ ]
3845
+ ],
3846
+ ["set", "@entity.isTyping", true],
3847
+ ["set", "@entity.displayedText", ""],
3848
+ ["set", "@entity.typeIndex", 0]
3849
+ ]
3850
+ },
3851
+ {
3852
+ from: ["Typing", "Showing", "Choice"],
3853
+ to: "Hidden",
3854
+ event: "CLOSE",
3855
+ effects: [
3856
+ ["set", "@entity.dialogueTree", []],
3857
+ ["set", "@entity.currentNode", 0],
3858
+ ["emit", "GAME_RESUME"],
3859
+ ["render", "overlay.dialogue", null]
3860
+ ]
3861
+ }
3862
+ ]
3863
+ },
3864
+ ticks: [
3865
+ {
3866
+ name: "TypewriterEffect",
3867
+ interval: "frame",
3868
+ guard: ["and", "@entity.isTyping", [">", ["-", "@now", "@entity.lastTypeTime"], ["/", 1e3, "@config.typingSpeed"]]],
3869
+ effects: [
3870
+ [
3871
+ "let",
3872
+ [["currentDialogue", ["array/nth", "@entity.dialogueTree", "@entity.currentNode"]]],
3873
+ [
3874
+ "if",
3875
+ ["<", "@entity.typeIndex", ["str/len", "@currentDialogue.text"]],
3876
+ ["emit", "TYPE_CHAR"],
3877
+ ["emit", "TYPE_COMPLETE"]
3878
+ ]
3879
+ ]
3880
+ ]
3881
+ }
3882
+ ],
3883
+ configSchema: {
3884
+ required: [],
3885
+ optional: [
3886
+ { name: "typingSpeed", type: "number", description: "Characters per second", default: 30 },
3887
+ { name: "autoAdvance", type: "boolean", description: "Auto-advance after typing", default: false },
3888
+ { name: "autoAdvanceDelay", type: "number", description: "Delay before auto-advance (ms)", default: 2e3 },
3889
+ { name: "showPortrait", type: "boolean", description: "Show speaker portrait", default: true }
3890
+ ]
3891
+ }
3892
+ };
3893
+ var LEVEL_PROGRESS_BEHAVIOR = {
3894
+ name: "std/LevelProgress",
3895
+ category: "game-ui",
3896
+ description: "Level progression with unlock, selection, and completion tracking",
3897
+ suggestedFor: [
3898
+ "Level-based games",
3899
+ "Puzzle games",
3900
+ "Platformers with levels",
3901
+ "Mobile games"
3902
+ ],
3903
+ dataEntities: [
3904
+ {
3905
+ name: "LevelProgressState",
3906
+ runtime: true,
3907
+ singleton: true,
3908
+ fields: [
3909
+ { name: "currentLevel", type: "number", default: 0 },
3910
+ { name: "unlockedLevels", type: "array", default: [0] },
3911
+ { name: "levelStars", type: "object", default: {} },
3912
+ { name: "totalStars", type: "number", default: 0 }
3913
+ ]
3914
+ }
3915
+ ],
3916
+ stateMachine: {
3917
+ initial: "Browsing",
3918
+ states: [
3919
+ { name: "Browsing", isInitial: true },
3920
+ { name: "LevelLoading" },
3921
+ { name: "InLevel" }
3922
+ ],
3923
+ events: [
3924
+ { key: "INIT" },
3925
+ { key: "SELECT_LEVEL" },
3926
+ { key: "LEVEL_LOADED" },
3927
+ { key: "COMPLETE_LEVEL" },
3928
+ { key: "UNLOCK_LEVEL" },
3929
+ { key: "BACK_TO_SELECT" }
3930
+ ],
3931
+ transitions: [
3932
+ {
3933
+ from: "*",
3934
+ to: "Browsing",
3935
+ event: "INIT",
3936
+ effects: [
3937
+ ["render", "screen", "level-select", {
3938
+ levels: "@config.levels",
3939
+ unlockedLevels: "@entity.unlockedLevels",
3940
+ levelStars: "@entity.levelStars",
3941
+ starsPerLevel: "@config.starsPerLevel",
3942
+ totalStars: "@entity.totalStars",
3943
+ onSelect: "SELECT_LEVEL"
3944
+ }]
3945
+ ]
3946
+ },
3947
+ {
3948
+ from: "Browsing",
3949
+ to: "LevelLoading",
3950
+ event: "SELECT_LEVEL",
3951
+ guard: ["array/includes", "@entity.unlockedLevels", "@payload.levelIndex"],
3952
+ effects: [
3953
+ ["set", "@entity.currentLevel", "@payload.levelIndex"],
3954
+ ["render", "screen", "loading-screen", {
3955
+ level: ["array/nth", "@config.levels", "@payload.levelIndex"]
3956
+ }],
3957
+ ["emit", "LOAD_LEVEL", { levelData: ["array/nth", "@config.levels", "@payload.levelIndex"] }]
3958
+ ]
3959
+ },
3960
+ {
3961
+ from: "LevelLoading",
3962
+ to: "InLevel",
3963
+ event: "LEVEL_LOADED",
3964
+ effects: [
3965
+ ["render", "screen", null],
3966
+ ["emit", "START"]
3967
+ ]
3968
+ },
3969
+ {
3970
+ from: "InLevel",
3971
+ event: "COMPLETE_LEVEL",
3972
+ effects: [
3973
+ ["set", "@entity.levelStars", [
3974
+ "object/set",
3975
+ "@entity.levelStars",
3976
+ ["str/toString", "@entity.currentLevel"],
3977
+ ["math/max", "@payload.stars", ["object/get", "@entity.levelStars", ["str/toString", "@entity.currentLevel"], 0]]
3978
+ ]],
3979
+ ["set", "@entity.totalStars", ["array/reduce", ["object/values", "@entity.levelStars"], ["fn", "sum", "v", ["+", "@sum", "@v"]], 0]],
3980
+ [
3981
+ "if",
3982
+ ["and", "@config.unlockNext", ["<", "@entity.currentLevel", ["-", ["array/len", "@config.levels"], 1]]],
3983
+ ["emit", "UNLOCK_LEVEL", { levelIndex: ["+", "@entity.currentLevel", 1] }]
3984
+ ],
3985
+ [
3986
+ "if",
3987
+ "@config.persistProgress",
3988
+ ["persist", "save", "LevelProgress", {
3989
+ unlockedLevels: "@entity.unlockedLevels",
3990
+ levelStars: "@entity.levelStars"
3991
+ }]
3992
+ ]
3993
+ ]
3994
+ },
3995
+ {
3996
+ event: "UNLOCK_LEVEL",
3997
+ guard: ["not", ["array/includes", "@entity.unlockedLevels", "@payload.levelIndex"]],
3998
+ effects: [
3999
+ ["set", "@entity.unlockedLevels", ["array/append", "@entity.unlockedLevels", "@payload.levelIndex"]]
4000
+ ]
4001
+ },
4002
+ {
4003
+ from: "InLevel",
4004
+ to: "Browsing",
4005
+ event: "BACK_TO_SELECT",
4006
+ effects: [
4007
+ ["emit", "INIT"]
4008
+ ]
4009
+ }
4010
+ ]
4011
+ },
4012
+ configSchema: {
4013
+ required: [
4014
+ { name: "levels", type: "array", description: "Level definitions" }
4015
+ ],
4016
+ optional: [
4017
+ { name: "starsPerLevel", type: "number", description: "Max stars per level", default: 3 },
4018
+ { name: "unlockNext", type: "boolean", description: "Auto-unlock next level on complete", default: true },
4019
+ { name: "persistProgress", type: "boolean", description: "Save progress to storage", default: true }
4020
+ ]
4021
+ }
4022
+ };
4023
+ var GAME_UI_BEHAVIORS = [
4024
+ GAME_FLOW_BEHAVIOR,
4025
+ DIALOGUE_BEHAVIOR,
4026
+ LEVEL_PROGRESS_BEHAVIOR
4027
+ ];
4028
+
4029
+ // behaviors/registry.ts
4030
+ var STANDARD_BEHAVIORS = [
4031
+ ...UI_INTERACTION_BEHAVIORS,
4032
+ ...DATA_MANAGEMENT_BEHAVIORS,
4033
+ ...ASYNC_BEHAVIORS,
4034
+ ...FEEDBACK_BEHAVIORS,
4035
+ ...GAME_CORE_BEHAVIORS,
4036
+ ...GAME_ENTITY_BEHAVIORS,
4037
+ ...GAME_UI_BEHAVIORS
4038
+ ];
4039
+ var BEHAVIOR_REGISTRY = STANDARD_BEHAVIORS.reduce(
4040
+ (acc, behavior) => {
4041
+ acc[behavior.name] = behavior;
4042
+ return acc;
4043
+ },
4044
+ {}
4045
+ );
4046
+ var BEHAVIORS_BY_CATEGORY = {
4047
+ "ui-interaction": UI_INTERACTION_BEHAVIORS,
4048
+ "data-management": DATA_MANAGEMENT_BEHAVIORS,
4049
+ "async": ASYNC_BEHAVIORS,
4050
+ "feedback": FEEDBACK_BEHAVIORS,
4051
+ "game-core": GAME_CORE_BEHAVIORS,
4052
+ "game-entity": GAME_ENTITY_BEHAVIORS,
4053
+ "game-ui": GAME_UI_BEHAVIORS
4054
+ };
4055
+ function getBehavior(name) {
4056
+ return BEHAVIOR_REGISTRY[name];
4057
+ }
4058
+ function isKnownBehavior(name) {
4059
+ return name in BEHAVIOR_REGISTRY;
4060
+ }
4061
+ function getBehaviorsByCategory(category) {
4062
+ return BEHAVIORS_BY_CATEGORY[category] ?? [];
4063
+ }
4064
+ function getAllBehaviorNames() {
4065
+ return Object.keys(BEHAVIOR_REGISTRY);
4066
+ }
4067
+ function getAllBehaviors() {
4068
+ return STANDARD_BEHAVIORS;
4069
+ }
4070
+ function getAllBehaviorMetadata() {
4071
+ return STANDARD_BEHAVIORS.map(getBehaviorMetadata);
4072
+ }
4073
+ function findBehaviorsForUseCase(useCase) {
4074
+ const lowerUseCase = useCase.toLowerCase();
4075
+ return STANDARD_BEHAVIORS.filter(
4076
+ (behavior) => behavior.suggestedFor?.some(
4077
+ (suggestion) => suggestion.toLowerCase().includes(lowerUseCase) || lowerUseCase.includes(suggestion.toLowerCase())
4078
+ ) ?? false
4079
+ );
4080
+ }
4081
+ function getBehaviorsForEvent(event) {
4082
+ return STANDARD_BEHAVIORS.filter((behavior) => {
4083
+ const events = behavior.stateMachine?.events || [];
4084
+ return events.some((e) => (typeof e === "string" ? e : e.key) === event);
4085
+ });
4086
+ }
4087
+ function getBehaviorsWithState(state) {
4088
+ return STANDARD_BEHAVIORS.filter((behavior) => {
4089
+ const states = behavior.stateMachine?.states || [];
4090
+ return states.some((s) => (typeof s === "string" ? s : s.name) === state);
4091
+ });
4092
+ }
4093
+ function validateBehaviorReference(name) {
4094
+ if (!name.startsWith("std/")) {
4095
+ return `Behavior name must start with 'std/': ${name}`;
4096
+ }
4097
+ if (!isKnownBehavior(name)) {
4098
+ const suggestions = findSimilarBehaviors(name);
4099
+ if (suggestions.length > 0) {
4100
+ return `Unknown behavior '${name}'. Did you mean: ${suggestions.join(", ")}?`;
4101
+ }
4102
+ return `Unknown behavior: ${name}`;
4103
+ }
4104
+ return null;
4105
+ }
4106
+ function findSimilarBehaviors(name) {
4107
+ const normalizedInput = name.toLowerCase().replace("std/", "");
4108
+ return getAllBehaviorNames().filter((behaviorName) => {
4109
+ const normalizedBehavior = behaviorName.toLowerCase().replace("std/", "");
4110
+ return normalizedBehavior.includes(normalizedInput) || normalizedInput.includes(normalizedBehavior) || levenshteinDistance(normalizedInput, normalizedBehavior) <= 3;
4111
+ });
4112
+ }
4113
+ function levenshteinDistance(a, b) {
4114
+ if (a.length === 0) return b.length;
4115
+ if (b.length === 0) return a.length;
4116
+ const matrix = [];
4117
+ for (let i = 0; i <= b.length; i++) {
4118
+ matrix[i] = [i];
4119
+ }
4120
+ for (let j = 0; j <= a.length; j++) {
4121
+ matrix[0][j] = j;
4122
+ }
4123
+ for (let i = 1; i <= b.length; i++) {
4124
+ for (let j = 1; j <= a.length; j++) {
4125
+ if (b.charAt(i - 1) === a.charAt(j - 1)) {
4126
+ matrix[i][j] = matrix[i - 1][j - 1];
4127
+ } else {
4128
+ matrix[i][j] = Math.min(
4129
+ matrix[i - 1][j - 1] + 1,
4130
+ matrix[i][j - 1] + 1,
4131
+ matrix[i - 1][j] + 1
4132
+ );
4133
+ }
4134
+ }
4135
+ }
4136
+ return matrix[b.length][a.length];
4137
+ }
4138
+ function getBehaviorLibraryStats() {
4139
+ const byCategory = {};
4140
+ let totalStates = 0;
4141
+ let totalEvents = 0;
4142
+ let totalTransitions = 0;
4143
+ let totalTicks = 0;
4144
+ for (const behavior of STANDARD_BEHAVIORS) {
4145
+ byCategory[behavior.category] = (byCategory[behavior.category] ?? 0) + 1;
4146
+ const sm = behavior.stateMachine;
4147
+ if (sm) {
4148
+ totalStates += (sm.states || []).length;
4149
+ totalEvents += (sm.events || []).length;
4150
+ totalTransitions += (sm.transitions || []).length;
4151
+ }
4152
+ totalTicks += (behavior.ticks || []).length;
4153
+ }
4154
+ return {
4155
+ totalBehaviors: STANDARD_BEHAVIORS.length,
4156
+ byCategory,
4157
+ totalStates,
4158
+ totalEvents,
4159
+ totalTransitions,
4160
+ totalTicks
4161
+ };
4162
+ }
4163
+
4164
+ export { BEHAVIORS_BY_CATEGORY, BEHAVIOR_REGISTRY, STANDARD_BEHAVIORS, findBehaviorsForUseCase, getAllBehaviorMetadata, getAllBehaviorNames, getAllBehaviors, getBehavior, getBehaviorLibraryStats, getBehaviorsByCategory, getBehaviorsForEvent, getBehaviorsWithState, isKnownBehavior, validateBehaviorReference };
4165
+ //# sourceMappingURL=registry.js.map
4166
+ //# sourceMappingURL=registry.js.map