@almadar/std 16.176.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.
- package/behaviors/lolo/ui/avl/atoms/ui-behavior-view.lolo +1 -1
- package/behaviors/lolo/ui/avl/atoms/ui-module-card.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/std-modal.lolo +13 -0
- package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +29 -1
- package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +19 -5
- package/behaviors/lolo/ui/core/organisms/ui-form.lolo +19 -5
- package/behaviors/lolo/ui/core/organisms/ui-segment-renderer.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/std-motion-body.lolo +139 -0
- package/behaviors/lolo/ui/game/atoms/ui-action-palette.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-action-tile.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-canvas-2d.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-canvas.lolo +3 -3
- package/behaviors/lolo/ui/game/atoms/ui-draw-group.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-draw-shape-layer.lolo +3 -3
- package/behaviors/lolo/ui/game/atoms/ui-draw-shape.lolo +3 -3
- package/behaviors/lolo/ui/game/atoms/ui-draw-sprite-layer.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-draw-sprite.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-draw-text-layer.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-draw-text.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-sequence-bar.lolo +2 -2
- package/behaviors/lolo/ui/game/atoms/ui-trait-slot.lolo +3 -3
- package/behaviors/lolo/ui/learning/atoms/ui-biology-canvas.lolo +2 -2
- package/behaviors/lolo/ui/learning/atoms/ui-chemistry-canvas.lolo +2 -2
- package/behaviors/lolo/ui/learning/atoms/ui-math-canvas.lolo +12 -0
- package/behaviors/lolo/ui/learning/atoms/ui-physics-canvas.lolo +2 -2
- package/behaviors/registry/ui/avl/atoms/ui-behavior-view.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/ui-module-card.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-modal.orb +34 -0
- package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +110 -2
- package/behaviors/registry/ui/core/organisms/ui-form-section.orb +52 -6
- package/behaviors/registry/ui/core/organisms/ui-form.orb +52 -6
- package/behaviors/registry/ui/core/organisms/ui-segment-renderer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-motion-body.orb +1015 -0
- package/behaviors/registry/ui/game/atoms/ui-action-palette.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-action-tile.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-canvas-2d.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-canvas.orb +3 -3
- package/behaviors/registry/ui/game/atoms/ui-draw-group.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-shape-layer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-shape.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-sprite-layer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-sprite.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-text-layer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-text.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-sequence-bar.orb +3 -3
- package/behaviors/registry/ui/game/atoms/ui-trait-slot.orb +5 -5
- package/behaviors/registry/ui/learning/atoms/ui-algo-graph-canvas.orb +18 -1
- package/behaviors/registry/ui/learning/atoms/ui-algorithm-canvas.orb +26 -1
- package/behaviors/registry/ui/learning/atoms/ui-biology-canvas.orb +28 -3
- package/behaviors/registry/ui/learning/atoms/ui-chemistry-canvas.orb +28 -3
- package/behaviors/registry/ui/learning/atoms/ui-learning-canvas.orb +26 -1
- package/behaviors/registry/ui/learning/atoms/ui-math-canvas.orb +84 -31
- package/behaviors/registry/ui/learning/atoms/ui-physics-canvas.orb +28 -3
- package/dist/behaviors/exports-reader.js +2152 -1874
- package/dist/behaviors/functions/index.d.ts +129 -21
- package/dist/behaviors/functions/index.js +2150 -1875
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +2153 -1875
- package/dist/behaviors/query.js +2152 -1874
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +369 -365
- package/dist/behaviors-registry.json +251 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2153 -1875
- package/dist/knob-embeddings.hash.json +3 -3
- package/dist/knob-embeddings.json +1 -1
- package/dist/registry/factory-signatures.json +1 -1
- package/package.json +2 -2
|
@@ -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 :
|
|
72
|
+
formValues : object!
|
|
66
73
|
globalVariables : Map string json!
|
|
67
74
|
localVariables : Map string json
|
|
68
|
-
entity :
|
|
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 :
|
|
111
|
-
formValues : Map string
|
|
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 :
|
|
72
|
+
formValues : object!
|
|
66
73
|
globalVariables : Map string json!
|
|
67
74
|
localVariables : Map string json
|
|
68
|
-
entity :
|
|
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 :
|
|
111
|
-
formValues : Map string
|
|
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"
|
|
@@ -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
|
+
}
|
|
@@ -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 : [
|
|
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 :
|
|
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 :
|
|
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 : [
|
|
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 :
|
|
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 : [
|
|
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 : [
|
|
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 : [
|
|
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 : [
|
|
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 :
|
|
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"
|
|
@@ -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 :
|
|
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"
|
|
@@ -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 :
|
|
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 :
|
|
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 :
|
|
38
|
+
stateMachine : object
|
|
39
39
|
}
|
|
40
40
|
type SequenceBarSLOTDROPItemIconUrl = {
|
|
41
41
|
url : asset!
|