@almadar/std 16.175.0 → 16.177.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 (68) hide show
  1. package/behaviors/lolo/ui/avl/atoms/ui-behavior-view.lolo +1 -1
  2. package/behaviors/lolo/ui/avl/atoms/ui-module-card.lolo +1 -1
  3. package/behaviors/lolo/ui/core/atoms/std-modal.lolo +13 -0
  4. package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +29 -1
  5. package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +19 -5
  6. package/behaviors/lolo/ui/core/organisms/ui-form.lolo +19 -5
  7. package/behaviors/lolo/ui/core/organisms/ui-segment-renderer.lolo +1 -1
  8. package/behaviors/lolo/ui/game/atoms/std-motion-body.lolo +139 -0
  9. package/behaviors/lolo/ui/game/atoms/ui-action-palette.lolo +1 -1
  10. package/behaviors/lolo/ui/game/atoms/ui-action-tile.lolo +1 -1
  11. package/behaviors/lolo/ui/game/atoms/ui-canvas-2d.lolo +1 -1
  12. package/behaviors/lolo/ui/game/atoms/ui-canvas.lolo +3 -3
  13. package/behaviors/lolo/ui/game/atoms/ui-draw-group.lolo +1 -1
  14. package/behaviors/lolo/ui/game/atoms/ui-draw-shape-layer.lolo +3 -3
  15. package/behaviors/lolo/ui/game/atoms/ui-draw-shape.lolo +3 -3
  16. package/behaviors/lolo/ui/game/atoms/ui-draw-sprite-layer.lolo +1 -1
  17. package/behaviors/lolo/ui/game/atoms/ui-draw-sprite.lolo +1 -1
  18. package/behaviors/lolo/ui/game/atoms/ui-draw-text-layer.lolo +1 -1
  19. package/behaviors/lolo/ui/game/atoms/ui-draw-text.lolo +1 -1
  20. package/behaviors/lolo/ui/game/atoms/ui-sequence-bar.lolo +2 -2
  21. package/behaviors/lolo/ui/game/atoms/ui-trait-slot.lolo +3 -3
  22. package/behaviors/lolo/ui/learning/atoms/ui-biology-canvas.lolo +2 -2
  23. package/behaviors/lolo/ui/learning/atoms/ui-chemistry-canvas.lolo +2 -2
  24. package/behaviors/lolo/ui/learning/atoms/ui-math-canvas.lolo +12 -0
  25. package/behaviors/lolo/ui/learning/atoms/ui-physics-canvas.lolo +2 -2
  26. package/behaviors/registry/ui/avl/atoms/ui-behavior-view.orb +1 -1
  27. package/behaviors/registry/ui/avl/atoms/ui-module-card.orb +1 -1
  28. package/behaviors/registry/ui/core/atoms/std-modal.orb +34 -0
  29. package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +110 -2
  30. package/behaviors/registry/ui/core/organisms/ui-form-section.orb +52 -6
  31. package/behaviors/registry/ui/core/organisms/ui-form.orb +52 -6
  32. package/behaviors/registry/ui/core/organisms/ui-segment-renderer.orb +1 -1
  33. package/behaviors/registry/ui/game/atoms/std-motion-body.orb +1015 -0
  34. package/behaviors/registry/ui/game/atoms/ui-action-palette.orb +1 -1
  35. package/behaviors/registry/ui/game/atoms/ui-action-tile.orb +1 -1
  36. package/behaviors/registry/ui/game/atoms/ui-canvas-2d.orb +1 -1
  37. package/behaviors/registry/ui/game/atoms/ui-canvas.orb +3 -3
  38. package/behaviors/registry/ui/game/atoms/ui-draw-group.orb +1 -1
  39. package/behaviors/registry/ui/game/atoms/ui-draw-shape-layer.orb +1 -1
  40. package/behaviors/registry/ui/game/atoms/ui-draw-shape.orb +1 -1
  41. package/behaviors/registry/ui/game/atoms/ui-draw-sprite-layer.orb +1 -1
  42. package/behaviors/registry/ui/game/atoms/ui-draw-sprite.orb +1 -1
  43. package/behaviors/registry/ui/game/atoms/ui-draw-text-layer.orb +1 -1
  44. package/behaviors/registry/ui/game/atoms/ui-draw-text.orb +1 -1
  45. package/behaviors/registry/ui/game/atoms/ui-sequence-bar.orb +3 -3
  46. package/behaviors/registry/ui/game/atoms/ui-trait-slot.orb +5 -5
  47. package/behaviors/registry/ui/learning/atoms/ui-algo-graph-canvas.orb +18 -1
  48. package/behaviors/registry/ui/learning/atoms/ui-algorithm-canvas.orb +26 -1
  49. package/behaviors/registry/ui/learning/atoms/ui-biology-canvas.orb +28 -3
  50. package/behaviors/registry/ui/learning/atoms/ui-chemistry-canvas.orb +28 -3
  51. package/behaviors/registry/ui/learning/atoms/ui-learning-canvas.orb +26 -1
  52. package/behaviors/registry/ui/learning/atoms/ui-math-canvas.orb +84 -31
  53. package/behaviors/registry/ui/learning/atoms/ui-physics-canvas.orb +28 -3
  54. package/dist/behaviors/exports-reader.js +2152 -1874
  55. package/dist/behaviors/functions/index.d.ts +129 -21
  56. package/dist/behaviors/functions/index.js +2150 -1875
  57. package/dist/behaviors/index.d.ts +1 -1
  58. package/dist/behaviors/index.js +2153 -1875
  59. package/dist/behaviors/query.js +2152 -1874
  60. package/dist/behaviors-embeddings.hash.json +3 -3
  61. package/dist/behaviors-embeddings.json +307 -303
  62. package/dist/behaviors-registry.json +257 -4
  63. package/dist/index.d.ts +1 -1
  64. package/dist/index.js +2153 -1875
  65. package/dist/knob-embeddings.hash.json +3 -3
  66. package/dist/knob-embeddings.json +1 -1
  67. package/dist/registry/factory-signatures.json +1 -1
  68. package/package.json +2 -2
@@ -17,7 +17,7 @@ orbital BehaviorViewOrbital {
17
17
  }
18
18
 
19
19
  config {
20
- data : json = {}
20
+ data : object = {}
21
21
  @label "Data"
22
22
  @description "data prop"
23
23
  @tier "presentation"
@@ -18,7 +18,7 @@ orbital ModuleCardOrbital {
18
18
  }
19
19
 
20
20
  config {
21
- data : json = {}
21
+ data : object = {}
22
22
  @label "Data"
23
23
  @description "data prop"
24
24
  @tier "presentation"
@@ -8,6 +8,13 @@ app std-modal "1.0.0"
8
8
  ;; notify) belong in a sibling coordinator trait that
9
9
  ;; `listens { ModalTrait SAVE -> DO_PERSIST }`.
10
10
  orbital ModalRecordOrbital {
11
+ type ModalFieldOverride = {
12
+ name : string!
13
+ label : string
14
+ placeholder : string
15
+ hint : string
16
+ }
17
+
11
18
  type ModalRecordLoaded = Event { data : [ModalRecord] }
12
19
 
13
20
  type ModalRecordLoadFailed = Event { error : string, code : string }
@@ -48,6 +55,7 @@ orbital ModalRecordOrbital {
48
55
  }, { type: divider }, {
49
56
  cancelEvent: CLOSE
50
57
  entity: ?row
58
+ fieldOverrides: @config.fieldOverrides
51
59
  fields: @config.fields
52
60
  mode: @config.mode
53
61
  submitEvent: SAVE
@@ -127,6 +135,11 @@ orbital ModalRecordOrbital {
127
135
  @description "Entity fields rendered as inputs inside the modal form."
128
136
  @synonyms "form fields, inputs, editable fields, field list"
129
137
  @tier "domain"
138
+ fieldOverrides : [ModalFieldOverride] = []
139
+ @label "Any per-field display copy overrides?"
140
+ @description "Per-field label/placeholder/hint overrides, keyed by field name. Types, options and required-ness stay entity-schema-driven (declare once on the entity); override only display copy the entity's @description doesn't fit."
141
+ @synonyms "field labels, custom labels, help text overrides, placeholder text"
142
+ @tier "presentation"
130
143
  mode : string = create
131
144
  @label "Is this for creating or editing?"
132
145
  @description "create = blank form; edit = pre-filled from the selected row."
@@ -29,9 +29,25 @@ orbital DetailPanelOrbital {
29
29
  navigatesTo : string
30
30
  variant : "primary" | "secondary" | "ghost" | "danger"
31
31
  }
32
+ type DetailPanelBackAction = {
33
+ label : string!
34
+ icon : icon
35
+ event : string
36
+ navigatesTo : string
37
+ variant : "primary" | "secondary" | "ghost" | "danger"
38
+ }
32
39
  type DetailPanelFieldsItem = {
33
40
  key : string!
34
41
  header : string
42
+ type : string
43
+ values : [string]
44
+ relation : string
45
+ }
46
+ type DetailPanelRelationsDataValueItem = {
47
+ value : string!
48
+ label : string!
49
+ description : string
50
+ disabled : boolean
35
51
  }
36
52
 
37
53
  entity DetailPanelItem [runtime] {
@@ -63,6 +79,7 @@ orbital DetailPanelOrbital {
63
79
  avatar: @config.avatar
64
80
  sections: @config.sections
65
81
  actions: @config.actions
82
+ backAction: @config.backAction
66
83
  footer: @config.footer
67
84
  slideOver: @config.slideOver
68
85
  fields: @config.fields
@@ -73,6 +90,7 @@ orbital DetailPanelOrbital {
73
90
  width: @config.width
74
91
  displayFields: @config.displayFields
75
92
  showActions: @config.showActions
93
+ relationsData: @config.relationsData
76
94
  type: detail-panel
77
95
  })
78
96
  DetailPanelLoaded -> idle
@@ -95,6 +113,7 @@ orbital DetailPanelOrbital {
95
113
  avatar: @config.avatar
96
114
  sections: @config.sections
97
115
  actions: @config.actions
116
+ backAction: @config.backAction
98
117
  footer: @config.footer
99
118
  slideOver: @config.slideOver
100
119
  fields: @config.fields
@@ -105,6 +124,7 @@ orbital DetailPanelOrbital {
105
124
  width: @config.width
106
125
  displayFields: @config.displayFields
107
126
  showActions: @config.showActions
127
+ relationsData: @config.relationsData
108
128
  type: detail-panel
109
129
  })
110
130
  }
@@ -186,6 +206,10 @@ orbital DetailPanelOrbital {
186
206
  @label "Actions"
187
207
  @description "Unified actions array - first action with variant='primary' is the main action"
188
208
  @tier "presentation"
209
+ backAction : DetailPanelBackAction
210
+ @label "Back Action"
211
+ @description "Navigation-back affordance. Renders top-LEFT before the title (OS/back convention — Almadar_UX §8.4), spatially separated from the right-aligned action buttons + close X. Never inferred from actions[] labels."
212
+ @tier "presentation"
189
213
  footer : node
190
214
  @label "Footer"
191
215
  @description "footer prop"
@@ -194,7 +218,7 @@ orbital DetailPanelOrbital {
194
218
  @label "Slide Over"
195
219
  @description "slideOver prop"
196
220
  @tier "presentation"
197
- fields : [DetailPanelFieldsItem] = [{ key: "Key", header: "Header" }, { key: "Key 2", header: "Header 2" }]
221
+ fields : [DetailPanelFieldsItem] = [{ key: "Key", header: "Header", type: "Type", values: ["Item", "Item 2"], relation: "Relation" }, { key: "Key 2", header: "Header 2", type: "Type 2", values: ["Item", "Item 2"], relation: "Relation 2" }]
198
222
  @label "Fields"
199
223
  @description "Fields to display - accepts string[], {key, header}[], or DetailField[]"
200
224
  @tier "presentation"
@@ -222,6 +246,10 @@ orbital DetailPanelOrbital {
222
246
  @label "Show Actions"
223
247
  @description "Show actions flag"
224
248
  @tier "presentation"
249
+ relationsData : Map string [DetailPanelRelationsDataValueItem] = {}
250
+ @label "Relations Data"
251
+ @description "Relation display data: { fieldName: [{value, label}] } — injected server-side by the runtime (relation-option injection) or bound by compiled codegen; resolves stored foreign ids to display names."
252
+ @tier "presentation"
225
253
  }
226
254
  }
227
255
 
@@ -20,6 +20,7 @@ orbital FormSectionOrbital {
20
20
  validation : FormSectionFieldsItemValidation
21
21
  readonly : boolean
22
22
  disabled : boolean
23
+ hint : string
23
24
  }
24
25
  type FormSectionFieldsItemOptionsItem = {
25
26
  value : string!
@@ -45,6 +46,12 @@ orbital FormSectionOrbital {
45
46
  description : string
46
47
  disabled : boolean
47
48
  }
49
+ type FormSectionFieldOverridesItem = {
50
+ name : string!
51
+ label : string
52
+ placeholder : string
53
+ hint : string
54
+ }
48
55
  type FormSectionHiddenCalculationsItem = {
49
56
  variableName : string!
50
57
  expression : SExpr!
@@ -62,10 +69,10 @@ orbital FormSectionOrbital {
62
69
  message : string!
63
70
  }
64
71
  type FormSectionEvaluationContext = {
65
- formValues : json!
72
+ formValues : object!
66
73
  globalVariables : Map string json!
67
74
  localVariables : Map string json
68
- entity : json
75
+ entity : object
69
76
  }
70
77
  type FormSectionSectionsItem = {
71
78
  id : string!
@@ -92,6 +99,7 @@ orbital FormSectionOrbital {
92
99
  validation : FormSectionSectionsItemFieldsItemValidation
93
100
  readonly : boolean
94
101
  disabled : boolean
102
+ hint : string
95
103
  }
96
104
  type FormSectionSectionsItemFieldsItemOptionsItem = {
97
105
  value : string!
@@ -107,8 +115,8 @@ orbital FormSectionOrbital {
107
115
  }
108
116
  type FormSectionFIELDCHANGEChange = {
109
117
  fieldId : string!
110
- value : json!
111
- formValues : Map string json!
118
+ value : object!
119
+ formValues : Map string object!
112
120
  }
113
121
 
114
122
  entity FormSectionItem [runtime] {
@@ -143,6 +151,7 @@ orbital FormSectionOrbital {
143
151
  cancelEvent: @config.cancelEvent
144
152
  relationsData: @config.relationsData
145
153
  relationsLoading: @config.relationsLoading
154
+ fieldOverrides: @config.fieldOverrides
146
155
  conditionalFields: @config.conditionalFields
147
156
  hiddenCalculations: @config.hiddenCalculations
148
157
  violationTriggers: @config.violationTriggers
@@ -176,6 +185,7 @@ orbital FormSectionOrbital {
176
185
  cancelEvent: @config.cancelEvent
177
186
  relationsData: @config.relationsData
178
187
  relationsLoading: @config.relationsLoading
188
+ fieldOverrides: @config.fieldOverrides
179
189
  conditionalFields: @config.conditionalFields
180
190
  hiddenCalculations: @config.hiddenCalculations
181
191
  violationTriggers: @config.violationTriggers
@@ -239,7 +249,7 @@ orbital FormSectionOrbital {
239
249
  @label "Mode"
240
250
  @description "Form mode — 'create' for new records, 'edit' for updating existing. Accepts `string` so schema-driven callers (whose `config.mode` is typed as `string` per the trait's declared config block) compile cleanly. The runtime treats anything other than 'edit' as 'create'."
241
251
  @tier "presentation"
242
- fields : [FormSectionFieldsItem] = [{ name: "Name", field: "Field", label: "Label", type: "Type", inputType: "Input Type", placeholder: "Placeholder", required: false, options: [{ value: "Value", label: "Label" }, { value: "Value 2", label: "Label 2" }], values: ["Item", "Item 2"], relation: { entity: "Entity", displayField: "Display Field", cardinality: one }, min: 1, max: 1, pattern: "Pattern", validation: { enum: ["Item", "Item 2"] }, readonly: false, disabled: false }, { name: "Name 2", field: "Field 2", label: "Label 2", type: "Type 2", inputType: "Input Type 2", placeholder: "Placeholder 2", required: true, options: [{ value: "Value", label: "Label" }, { value: "Value 2", label: "Label 2" }], values: ["Item", "Item 2"], relation: { entity: "Entity 2", displayField: "Display Field 2", cardinality: many }, min: 2, max: 2, pattern: "Pattern 2", validation: { enum: ["Item", "Item 2"] }, readonly: true, disabled: true }]
252
+ fields : [FormSectionFieldsItem] = [{ name: "Name", field: "Field", label: "Label", type: "Type", inputType: "Input Type", placeholder: "Placeholder", required: false, options: [{ value: "Value", label: "Label" }, { value: "Value 2", label: "Label 2" }], values: ["Item", "Item 2"], relation: { entity: "Entity", displayField: "Display Field", cardinality: one }, min: 1, max: 1, pattern: "Pattern", validation: { enum: ["Item", "Item 2"] }, readonly: false, disabled: false, hint: "Hint" }, { name: "Name 2", field: "Field 2", label: "Label 2", type: "Type 2", inputType: "Input Type 2", placeholder: "Placeholder 2", required: true, options: [{ value: "Value", label: "Label" }, { value: "Value 2", label: "Label 2" }], values: ["Item", "Item 2"], relation: { entity: "Entity 2", displayField: "Display Field 2", cardinality: many }, min: 2, max: 2, pattern: "Pattern 2", validation: { enum: ["Item", "Item 2"] }, readonly: true, disabled: true, hint: "Hint 2" }]
243
253
  @label "Fields"
244
254
  @description "Fields definition (schema format) - accepts readonly for generated const arrays"
245
255
  @tier "presentation"
@@ -287,6 +297,10 @@ orbital FormSectionOrbital {
287
297
  @label "Relations Loading"
288
298
  @description "Loading state for relation data: { fieldName: boolean }"
289
299
  @tier "presentation"
300
+ fieldOverrides : [FormSectionFieldOverridesItem] = []
301
+ @label "Field Overrides"
302
+ @description "Per-field display-copy overrides (label/placeholder/hint), merged by field name over the schema-enriched fields."
303
+ @tier "presentation"
290
304
  conditionalFields : Map string SExpr = {}
291
305
  @label "Conditional Fields"
292
306
  @description "Inspection form extensions"
@@ -20,6 +20,7 @@ orbital FormOrbital {
20
20
  validation : FormFieldsItemValidation
21
21
  readonly : boolean
22
22
  disabled : boolean
23
+ hint : string
23
24
  }
24
25
  type FormFieldsItemOptionsItem = {
25
26
  value : string!
@@ -45,6 +46,12 @@ orbital FormOrbital {
45
46
  description : string
46
47
  disabled : boolean
47
48
  }
49
+ type FormFieldOverridesItem = {
50
+ name : string!
51
+ label : string
52
+ placeholder : string
53
+ hint : string
54
+ }
48
55
  type FormHiddenCalculationsItem = {
49
56
  variableName : string!
50
57
  expression : SExpr!
@@ -62,10 +69,10 @@ orbital FormOrbital {
62
69
  message : string!
63
70
  }
64
71
  type FormEvaluationContext = {
65
- formValues : json!
72
+ formValues : object!
66
73
  globalVariables : Map string json!
67
74
  localVariables : Map string json
68
- entity : json
75
+ entity : object
69
76
  }
70
77
  type FormSectionsItem = {
71
78
  id : string!
@@ -92,6 +99,7 @@ orbital FormOrbital {
92
99
  validation : FormSectionsItemFieldsItemValidation
93
100
  readonly : boolean
94
101
  disabled : boolean
102
+ hint : string
95
103
  }
96
104
  type FormSectionsItemFieldsItemOptionsItem = {
97
105
  value : string!
@@ -107,8 +115,8 @@ orbital FormOrbital {
107
115
  }
108
116
  type FormFIELDCHANGEChange = {
109
117
  fieldId : string!
110
- value : json!
111
- formValues : Map string json!
118
+ value : object!
119
+ formValues : Map string object!
112
120
  }
113
121
 
114
122
  entity FormItem [runtime] {
@@ -143,6 +151,7 @@ orbital FormOrbital {
143
151
  cancelEvent: @config.cancelEvent
144
152
  relationsData: @config.relationsData
145
153
  relationsLoading: @config.relationsLoading
154
+ fieldOverrides: @config.fieldOverrides
146
155
  conditionalFields: @config.conditionalFields
147
156
  hiddenCalculations: @config.hiddenCalculations
148
157
  violationTriggers: @config.violationTriggers
@@ -176,6 +185,7 @@ orbital FormOrbital {
176
185
  cancelEvent: @config.cancelEvent
177
186
  relationsData: @config.relationsData
178
187
  relationsLoading: @config.relationsLoading
188
+ fieldOverrides: @config.fieldOverrides
179
189
  conditionalFields: @config.conditionalFields
180
190
  hiddenCalculations: @config.hiddenCalculations
181
191
  violationTriggers: @config.violationTriggers
@@ -239,7 +249,7 @@ orbital FormOrbital {
239
249
  @label "Mode"
240
250
  @description "Form mode — 'create' for new records, 'edit' for updating existing. Accepts `string` so schema-driven callers (whose `config.mode` is typed as `string` per the trait's declared config block) compile cleanly. The runtime treats anything other than 'edit' as 'create'."
241
251
  @tier "presentation"
242
- fields : [FormFieldsItem] = [{ name: "Name", field: "Field", label: "Label", type: "Type", inputType: "Input Type", placeholder: "Placeholder", required: false, options: [{ value: "Value", label: "Label" }, { value: "Value 2", label: "Label 2" }], values: ["Item", "Item 2"], relation: { entity: "Entity", displayField: "Display Field", cardinality: one }, min: 1, max: 1, pattern: "Pattern", validation: { enum: ["Item", "Item 2"] }, readonly: false, disabled: false }, { name: "Name 2", field: "Field 2", label: "Label 2", type: "Type 2", inputType: "Input Type 2", placeholder: "Placeholder 2", required: true, options: [{ value: "Value", label: "Label" }, { value: "Value 2", label: "Label 2" }], values: ["Item", "Item 2"], relation: { entity: "Entity 2", displayField: "Display Field 2", cardinality: many }, min: 2, max: 2, pattern: "Pattern 2", validation: { enum: ["Item", "Item 2"] }, readonly: true, disabled: true }]
252
+ fields : [FormFieldsItem] = [{ name: "Name", field: "Field", label: "Label", type: "Type", inputType: "Input Type", placeholder: "Placeholder", required: false, options: [{ value: "Value", label: "Label" }, { value: "Value 2", label: "Label 2" }], values: ["Item", "Item 2"], relation: { entity: "Entity", displayField: "Display Field", cardinality: one }, min: 1, max: 1, pattern: "Pattern", validation: { enum: ["Item", "Item 2"] }, readonly: false, disabled: false, hint: "Hint" }, { name: "Name 2", field: "Field 2", label: "Label 2", type: "Type 2", inputType: "Input Type 2", placeholder: "Placeholder 2", required: true, options: [{ value: "Value", label: "Label" }, { value: "Value 2", label: "Label 2" }], values: ["Item", "Item 2"], relation: { entity: "Entity 2", displayField: "Display Field 2", cardinality: many }, min: 2, max: 2, pattern: "Pattern 2", validation: { enum: ["Item", "Item 2"] }, readonly: true, disabled: true, hint: "Hint 2" }]
243
253
  @label "Fields"
244
254
  @description "Fields definition (schema format) - accepts readonly for generated const arrays"
245
255
  @tier "presentation"
@@ -287,6 +297,10 @@ orbital FormOrbital {
287
297
  @label "Relations Loading"
288
298
  @description "Loading state for relation data: { fieldName: boolean }"
289
299
  @tier "presentation"
300
+ fieldOverrides : [FormFieldOverridesItem] = []
301
+ @label "Field Overrides"
302
+ @description "Per-field display-copy overrides (label/placeholder/hint), merged by field name over the schema-enriched fields."
303
+ @tier "presentation"
290
304
  conditionalFields : Map string SExpr = {}
291
305
  @label "Conditional Fields"
292
306
  @description "Inspection form extensions"
@@ -26,7 +26,7 @@ orbital SegmentRendererOrbital {
26
26
  }
27
27
 
28
28
  config {
29
- segments : [json] = []
29
+ segments : [object] = []
30
30
  @label "Segments"
31
31
  @description "Parsed lesson segments (see `parseLessonSegments`)"
32
32
  @tier "presentation"
@@ -0,0 +1,139 @@
1
+ app std-motion-body "1.1.0"
2
+ "Headless continuous-motion authority: the SOLE writer of bodies + gravity + bias on physics boards. Every 50ms motion tick it integrates each body — thrust acceleration plus the board-wide bias field (biasAx/biasAy — the hill-force / wind / conveyor-belt channel, written only through the SET_BIAS intent) plus gravity feed velocity, damping bleeds it, maxSpeed caps it, velocity steps position, and the world walls clamp it (a clamped axis kills that axis's velocity). Intents: THRUST sets a body's acceleration (hold-to-push input: keydown pushes, keyup zeroes), IMPULSE kicks velocity instantly (jumps, d-pad nudges), PLACE teleports (spawns, curve-riding pins), SET_GRAVITY retunes the pull live, SET_BIAS steers the bias field, RESTART reseeds. Emits BODY_MOVED for the lead body (bodies[0]) every tick so boards that subscribe can react — boards that don't subscribe pay nothing. Renders nothing."
3
+ orbital MotionBodyOrbital {
4
+ type Body = {
5
+ id : string!
6
+ x : number!
7
+ y : number!
8
+ vx : number
9
+ vy : number
10
+ ax : number
11
+ ay : number
12
+ }
13
+
14
+ entity MotionBodyData [runtime, shared] {
15
+ id : string!
16
+ bodies : [Body]
17
+ gravity : number = 0
18
+ biasAx : number = 0
19
+ biasAy : number = 0
20
+ }
21
+
22
+ trait MotionBody -> @rebindable MotionBodyData [lifecycle] {
23
+ initial: active
24
+
25
+ state active {
26
+ INIT -> active
27
+ (set @entity.bodies @config.bodies)
28
+ (set @entity.gravity @config.gravity)
29
+
30
+ THRUST -> active
31
+ (set @entity.bodies (array/map @entity.bodies (fn b (if (== @b.id @payload.id) (object/merge @b { ax: @payload.ax, ay: @payload.ay }) @b))))
32
+
33
+ IMPULSE -> active
34
+ (set @entity.bodies (array/map @entity.bodies (fn b (if (== @b.id @payload.id) (object/merge @b { vx: (+ (object/get @b vx) @payload.dvx), vy: (+ (object/get @b vy) @payload.dvy) }) @b))))
35
+
36
+ PLACE -> active
37
+ (set @entity.bodies (array/map @entity.bodies (fn b (if (== @b.id @payload.id) (object/merge @b { x: @payload.x, y: @payload.y }) @b))))
38
+
39
+ SET_GRAVITY -> active
40
+ (set @entity.gravity @payload.gravity)
41
+
42
+ SET_BIAS -> active
43
+ (set @entity.biasAx @payload.biasAx)
44
+ (set @entity.biasAy @payload.biasAy)
45
+
46
+ RESTART -> active
47
+ (set @entity.bodies @config.bodies)
48
+ (set @entity.gravity @config.gravity)
49
+ }
50
+
51
+ ticks {
52
+ motionTick every 50ms
53
+ when (and @config.running (> (array/len @entity.bodies) 0))
54
+ (do
55
+ (set @entity.bodies (array/map @entity.bodies (fn b
56
+ (let ((nvx (math/clamp (* (+ (object/get @b vx) (* (+ (object/get @b ax) @entity.biasAx) 0.05)) @config.damping) (- 0 @config.maxSpeed) @config.maxSpeed)))
57
+ (let ((nvy (math/clamp (* (+ (object/get @b vy) (* (+ (+ (object/get @b ay) @entity.biasAy) @entity.gravity) 0.05)) @config.damping) (- 0 @config.maxSpeed) @config.maxSpeed)))
58
+ (let ((nx (math/clamp (+ (object/get @b x) (* @nvx 0.05)) @config.xMin @config.xMax)))
59
+ (let ((ny (math/clamp (+ (object/get @b y) (* @nvy 0.05)) @config.yMin @config.yMax)))
60
+ (object/merge @b {
61
+ x: @nx,
62
+ y: @ny,
63
+ vx: (if (or (== @nx @config.xMin) (== @nx @config.xMax)) 0 @nvx),
64
+ vy: (if (or (== @ny @config.yMin) (== @ny @config.yMax)) 0 @nvy)
65
+ }))))))))
66
+ (emit BODY_MOVED {
67
+ id: (object/get (array/first @entity.bodies) id),
68
+ x: (object/get (array/first @entity.bodies) x),
69
+ y: (object/get (array/first @entity.bodies) y),
70
+ vx: (object/get (array/first @entity.bodies) vx),
71
+ vy: (object/get (array/first @entity.bodies) vy),
72
+ speed: (math/hypot (object/get (array/first @entity.bodies) vx) (object/get (array/first @entity.bodies) vy))
73
+ }))
74
+ }
75
+
76
+ emits {
77
+ BODY_MOVED -> external {
78
+ id : string!
79
+ x : number!
80
+ y : number!
81
+ vx : number!
82
+ vy : number!
83
+ speed : number!
84
+ }
85
+ @description "Lead body (bodies[0]) after this motion tick: position, velocity, and scalar speed; boards render it, objective mechanics score it, game rules adapt from it"
86
+ @tier "domain"
87
+ }
88
+
89
+ listens {
90
+ THRUST { id : string!, ax : number!, ay : number! }
91
+ IMPULSE { id : string!, dvx : number!, dvy : number! }
92
+ PLACE { id : string!, x : number!, y : number! }
93
+ SET_GRAVITY { gravity : number! }
94
+ SET_BIAS { biasAx : number!, biasAy : number! }
95
+ RESTART { id : string }
96
+ }
97
+
98
+ config {
99
+ running : boolean = true
100
+ @label "Running"
101
+ @description "When true the 50ms motion tick integrates; toggle to freeze all bodies"
102
+ @tier "domain"
103
+ bodies : [Body] = []
104
+ @label "Initial Bodies"
105
+ @description "Seed roster — bodies[0] is the lead body reported by BODY_MOVED"
106
+ @tier "domain"
107
+ gravity : number = 0
108
+ @label "Gravity"
109
+ @description "Constant acceleration added to every body's vertical velocity each tick (positive pulls toward +y); seeded onto the entity so SET_GRAVITY can retune it live"
110
+ @tier "domain"
111
+ damping : number = 0.98
112
+ @label "Damping"
113
+ @description "Velocity retained each 50ms tick (1 = frictionless coast, 0.9 = quick stop); the ice-to-mud feel knob"
114
+ @tier "presentation"
115
+ maxSpeed : number = 8
116
+ @label "Max Speed"
117
+ @description "Per-axis speed cap in world units per second"
118
+ @tier "presentation"
119
+ xMin : number = -1000000
120
+ @label "Left Wall"
121
+ @description "Smallest x a body may hold; hitting it zeroes vx"
122
+ @tier "presentation"
123
+ xMax : number = 1000000
124
+ @label "Right Wall"
125
+ @description "Largest x a body may hold; hitting it zeroes vx"
126
+ @tier "presentation"
127
+ yMin : number = -1000000
128
+ @label "Floor"
129
+ @description "Smallest y a body may hold; hitting it zeroes vy"
130
+ @tier "presentation"
131
+ yMax : number = 1000000
132
+ @label "Ceiling"
133
+ @description "Largest y a body may hold; hitting it zeroes vy"
134
+ @tier "presentation"
135
+ }
136
+ }
137
+
138
+ page "/motion-body" as MotionBodyPage -> MotionBody
139
+ }
@@ -8,7 +8,7 @@ orbital ActionPaletteOrbital {
8
8
  description : string
9
9
  iconEmoji : string
10
10
  iconUrl : ActionPaletteActionsItemIconUrl
11
- stateMachine : json
11
+ stateMachine : object
12
12
  }
13
13
  type ActionPaletteActionsItemIconUrl = {
14
14
  url : asset!
@@ -14,7 +14,7 @@ orbital ActionTileOrbital {
14
14
  description : string
15
15
  iconEmoji : string
16
16
  iconUrl : ActionTileActionIconUrl
17
- stateMachine : json
17
+ stateMachine : object
18
18
  }
19
19
  type ActionTileActionIconUrl = {
20
20
  url : asset!
@@ -95,7 +95,7 @@ orbital Canvas2dOrbital {
95
95
  @label "Projection"
96
96
  @description "--- Projection ---"
97
97
  @tier "presentation"
98
- drawables : [json] = []
98
+ drawables : [object] = []
99
99
  @label "Drawables"
100
100
  @description "--- Scene ---"
101
101
  @tier "presentation"
@@ -81,7 +81,7 @@ orbital CanvasOrbital {
81
81
  @label "Mode"
82
82
  @description "Painter: 2D sprite/shape/text raster, or 3D mesh. Default '2d'."
83
83
  @tier "presentation"
84
- drawables : [json] = []
84
+ drawables : [object] = []
85
85
  @label "Drawables"
86
86
  @description "Neutral drawable descriptors — the `draw-*` children. Routed to the host's painter."
87
87
  @tier "presentation"
@@ -157,11 +157,11 @@ orbital CanvasOrbital {
157
157
  @label "Fog Of War"
158
158
  @description "fogOfWar prop"
159
159
  @tier "presentation"
160
- lighting : json = {}
160
+ lighting : object = {}
161
161
  @label "Lighting"
162
162
  @description "3D scene light rig as data — ambient/directional/hemisphere/point lights + optional 'room' environment for PBR reflections. Omitted → the standard fixed rig."
163
163
  @tier "presentation"
164
- post : json = {}
164
+ post : object = {}
165
165
  @label "Post"
166
166
  @description "3D post-processing stack — bloom (emissive glow / neon) and vignette. Omitted → no post pass."
167
167
  @tier "presentation"
@@ -87,7 +87,7 @@ orbital DrawGroupOrbital {
87
87
  @label "Clip"
88
88
  @description "Clip the group's items to an SVG path (`d` syntax) in world units relative to the group origin — masked reveals, meters, portraits."
89
89
  @tier "presentation"
90
- items : [json] = []
90
+ items : [object] = []
91
91
  @label "Items"
92
92
  @description "The grouped drawables, painted through the normal dispatch."
93
93
  @tier "presentation"
@@ -5,7 +5,7 @@ orbital DrawShapeLayerOrbital {
5
5
  type : json!
6
6
  shape : "cell" | "rect" | "ellipse" | "poly" | "path"!
7
7
  position : DrawShapeLayerItemsItemPosition!
8
- anchor : json
8
+ anchor : object
9
9
  width : number
10
10
  height : number
11
11
  radiusX : number
@@ -46,7 +46,7 @@ orbital DrawShapeLayerOrbital {
46
46
  center : DrawShapeLayerItemsItemGradientCenter
47
47
  radius : number
48
48
  angle : number
49
- stops : [json]!
49
+ stops : [object]!
50
50
  }
51
51
  type DrawShapeLayerItemsItemGradientFrom = {
52
52
  x : number!
@@ -74,7 +74,7 @@ orbital DrawShapeLayerOrbital {
74
74
  center : DrawShapeLayerItemsItemStrokeGradientCenter
75
75
  radius : number
76
76
  angle : number
77
- stops : [json]!
77
+ stops : [object]!
78
78
  }
79
79
  type DrawShapeLayerItemsItemStrokeGradientFrom = {
80
80
  x : number!
@@ -17,7 +17,7 @@ orbital DrawShapeOrbital {
17
17
  center : DrawShapeGradientCenter
18
18
  radius : number
19
19
  angle : number
20
- stops : [json]!
20
+ stops : [object]!
21
21
  }
22
22
  type DrawShapeGradientFrom = {
23
23
  x : number!
@@ -45,7 +45,7 @@ orbital DrawShapeOrbital {
45
45
  center : DrawShapeStrokeGradientCenter
46
46
  radius : number
47
47
  angle : number
48
- stops : [json]!
48
+ stops : [object]!
49
49
  }
50
50
  type DrawShapeStrokeGradientFrom = {
51
51
  x : number!
@@ -143,7 +143,7 @@ orbital DrawShapeOrbital {
143
143
  @label "Position"
144
144
  @description "Logical scene position; the projector maps it to pixels / world."
145
145
  @tier "presentation"
146
- anchor : json = {}
146
+ anchor : object = {}
147
147
  @label "Anchor"
148
148
  @description "How the shape aligns to its projected position. Default varies by `shape`."
149
149
  @tier "presentation"
@@ -5,7 +5,7 @@ orbital DrawSpriteLayerOrbital {
5
5
  type : json!
6
6
  position : DrawSpriteLayerItemsItemPosition!
7
7
  asset : DrawSpriteLayerItemsItemAsset!
8
- anchor : json
8
+ anchor : object
9
9
  width : number
10
10
  height : number
11
11
  frame : DrawSpriteLayerItemsItemFrame
@@ -66,7 +66,7 @@ orbital DrawSpriteOrbital {
66
66
  @label "Asset"
67
67
  @description "The image / atlas reference to blit."
68
68
  @tier "presentation"
69
- anchor : json = {}
69
+ anchor : object = {}
70
70
  @label "Anchor"
71
71
  @description "How the sprite aligns to its projected position. Default `'top-left'`."
72
72
  @tier "presentation"
@@ -5,7 +5,7 @@ orbital DrawTextLayerOrbital {
5
5
  type : json!
6
6
  text : string!
7
7
  position : DrawTextLayerItemsItemPosition!
8
- anchor : json
8
+ anchor : object
9
9
  offsetX : number
10
10
  offsetY : number
11
11
  color : string!
@@ -40,7 +40,7 @@ orbital DrawTextOrbital {
40
40
  @label "Position"
41
41
  @description "Logical scene position; the projector maps it to pixels / world."
42
42
  @tier "presentation"
43
- anchor : json = {}
43
+ anchor : object = {}
44
44
  @label "Anchor"
45
45
  @description "anchor prop"
46
46
  @tier "presentation"
@@ -8,7 +8,7 @@ orbital SequenceBarOrbital {
8
8
  description : string
9
9
  iconEmoji : string
10
10
  iconUrl : SequenceBarSlotsItemIconUrl
11
- stateMachine : json
11
+ stateMachine : object
12
12
  }
13
13
  type SequenceBarSlotsItemIconUrl = {
14
14
  url : asset!
@@ -35,7 +35,7 @@ orbital SequenceBarOrbital {
35
35
  description : string
36
36
  iconEmoji : string
37
37
  iconUrl : SequenceBarSLOTDROPItemIconUrl
38
- stateMachine : json
38
+ stateMachine : object
39
39
  }
40
40
  type SequenceBarSLOTDROPItemIconUrl = {
41
41
  url : asset!