@almadar/std 16.243.0 → 16.244.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/behaviors/behaviors-registry.json +72537 -31220
- package/behaviors/lolo/agent/atoms/std-agent-context.lolo +24 -4
- package/behaviors/lolo/agent/atoms/std-agent-memory.lolo +20 -5
- package/behaviors/lolo/agent/atoms/std-agent-proposal.lolo +550 -0
- package/behaviors/lolo/agent/atoms/std-agent-session.lolo +284 -25
- package/behaviors/lolo/agent/atoms/std-agent-suggestions.lolo +841 -0
- package/behaviors/lolo/agent/atoms/std-agent-tool-loop.lolo +58 -8
- package/behaviors/lolo/agent/organisms/std-agent-assistant.lolo +1 -0
- package/behaviors/lolo/infra/atoms/std-page-treat.lolo +28 -1
- package/behaviors/lolo/ui/avl/atoms/ui-avl-state-machine.lolo +22 -0
- package/behaviors/lolo/ui/avl/atoms/ui-avl-transition-explainer.lolo +175 -0
- package/behaviors/lolo/ui/avl/atoms/ui-module-card.lolo +22 -0
- package/behaviors/lolo/ui/core/atoms/std-app-layout.lolo +23 -4
- package/behaviors/lolo/ui/core/atoms/std-hero.lolo +72 -33
- package/behaviors/lolo/ui/core/molecules/ui-agent-chat-feed.lolo +1 -1
- package/behaviors/lolo/ui/core/molecules/ui-markdown-content.lolo +54 -0
- package/behaviors/lolo/ui/core/molecules/ui-upload-drop-zone.lolo +5 -0
- package/behaviors/lolo/ui/core/organisms/ui-segment-renderer.lolo +127 -3
- package/behaviors/lolo/ui/core/organisms/ui-state-machine-view.lolo +22 -0
- package/behaviors/lolo/ui/core/templates/ui-dashboard-layout.lolo +2 -2
- package/behaviors/lolo/ui/learning/atoms/std-learn-arrangement.lolo +87 -17
- package/behaviors/lolo/ui/learning/atoms/std-learn-classify.lolo +172 -37
- package/behaviors/lolo/ui/learning/atoms/std-learn-coupled-sim.lolo +183 -70
- package/behaviors/lolo/ui/learning/atoms/std-learn-derivation.lolo +78 -13
- package/behaviors/lolo/ui/learning/atoms/std-learn-diagram.lolo +58 -2
- package/behaviors/lolo/ui/learning/atoms/std-learn-doser.lolo +107 -12
- package/behaviors/lolo/ui/learning/atoms/std-learn-estimate.lolo +83 -10
- package/behaviors/lolo/ui/learning/atoms/std-learn-goal-seek.lolo +130 -9
- package/behaviors/lolo/ui/learning/atoms/std-learn-grid-sim.lolo +143 -59
- package/behaviors/lolo/ui/learning/atoms/std-learn-hotspot.lolo +96 -22
- package/behaviors/lolo/ui/learning/atoms/std-learn-live-sim.lolo +66 -5
- package/behaviors/lolo/ui/learning/atoms/std-learn-predict.lolo +84 -6
- package/behaviors/lolo/ui/learning/atoms/std-learn-sandbox.lolo +80 -14
- package/behaviors/lolo/ui/learning/atoms/std-learn-scatter-fit.lolo +99 -5
- package/behaviors/lolo/ui/learning/atoms/std-learn-scenario.lolo +81 -7
- package/behaviors/lolo/ui/learning/atoms/std-learn-speed-drill.lolo +83 -7
- package/behaviors/lolo/ui/learning/atoms/std-learn-stepper.lolo +224 -99
- package/behaviors/lolo/ui/learning/atoms/std-learn-tour-3d.lolo +63 -2
- package/behaviors/lolo/ui/learning/atoms/std-learn-trace-player.lolo +99 -38
- package/behaviors/lolo/ui/learning/atoms/std-learn-transport.lolo +7 -7
- package/behaviors/lolo/ui/learning/atoms/std-learn-tree.lolo +69 -4
- package/behaviors/lolo-behavior-contracts.json +1 -1
- package/behaviors/registry/agent/atoms/std-agent-context.orb +205 -6
- package/behaviors/registry/agent/atoms/std-agent-memory.orb +146 -4
- package/behaviors/registry/agent/atoms/std-agent-proposal.orb +1972 -0
- package/behaviors/registry/agent/atoms/std-agent-session.orb +2021 -597
- package/behaviors/registry/agent/atoms/std-agent-suggestions.orb +5079 -0
- package/behaviors/registry/agent/atoms/std-agent-tool-loop.orb +287 -5
- package/behaviors/registry/agent/organisms/std-agent-assistant.orb +7 -0
- package/behaviors/registry/factory-signatures.json +1 -1
- package/behaviors/registry/infra/atoms/std-page-treat.orb +327 -2
- package/behaviors/registry/ui/avl/atoms/ui-avl-state-machine.orb +134 -0
- package/behaviors/registry/ui/avl/atoms/ui-avl-transition-explainer.orb +678 -0
- package/behaviors/registry/ui/avl/atoms/ui-module-card.orb +122 -0
- package/behaviors/registry/ui/core/atoms/std-app-layout.orb +73 -4
- package/behaviors/registry/ui/core/atoms/std-hero.orb +174 -97
- package/behaviors/registry/ui/core/molecules/ui-markdown-content.orb +204 -1
- package/behaviors/registry/ui/core/molecules/ui-upload-drop-zone.orb +12 -0
- package/behaviors/registry/ui/core/organisms/ui-segment-renderer.orb +683 -30
- package/behaviors/registry/ui/learning/atoms/std-learn-arrangement.orb +748 -21
- package/behaviors/registry/ui/learning/atoms/std-learn-classify.orb +1429 -41
- package/behaviors/registry/ui/learning/atoms/std-learn-coupled-sim.orb +1031 -185
- package/behaviors/registry/ui/learning/atoms/std-learn-derivation.orb +807 -132
- package/behaviors/registry/ui/learning/atoms/std-learn-diagram.orb +553 -6
- package/behaviors/registry/ui/learning/atoms/std-learn-doser.orb +987 -21
- package/behaviors/registry/ui/learning/atoms/std-learn-estimate.orb +582 -16
- package/behaviors/registry/ui/learning/atoms/std-learn-goal-seek.orb +954 -13
- package/behaviors/registry/ui/learning/atoms/std-learn-grid-sim.orb +828 -88
- package/behaviors/registry/ui/learning/atoms/std-learn-hotspot.orb +730 -28
- package/behaviors/registry/ui/learning/atoms/std-learn-live-sim.orb +479 -9
- package/behaviors/registry/ui/learning/atoms/std-learn-predict.orb +797 -46
- package/behaviors/registry/ui/learning/atoms/std-learn-sandbox.orb +757 -58
- package/behaviors/registry/ui/learning/atoms/std-learn-scatter-fit.orb +1176 -164
- package/behaviors/registry/ui/learning/atoms/std-learn-scenario.orb +599 -12
- package/behaviors/registry/ui/learning/atoms/std-learn-speed-drill.orb +832 -150
- package/behaviors/registry/ui/learning/atoms/std-learn-stepper.orb +1561 -127
- package/behaviors/registry/ui/learning/atoms/std-learn-tour-3d.orb +655 -6
- package/behaviors/registry/ui/learning/atoms/std-learn-trace-player.orb +634 -43
- package/behaviors/registry/ui/learning/atoms/std-learn-transport.orb +85 -31
- package/behaviors/registry/ui/learning/atoms/std-learn-tree.orb +425 -9
- package/canonical-operators.json +45 -2
- package/dist/behaviors/exports-reader.js +16667 -7868
- package/dist/behaviors/functions/index.d.ts +711 -32
- package/dist/behaviors/functions/index.js +16651 -7869
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +16668 -7869
- package/dist/behaviors/query.js +16667 -7868
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +77 -53
- package/dist/behaviors-registry.json +72537 -31220
- package/dist/index.d.ts +3 -3
- package/dist/index.js +16101 -7275
- package/dist/knob-embeddings.hash.json +3 -3
- package/dist/knob-embeddings.json +11617 -1225
- package/dist/modules/anim.d.ts +1 -1
- package/dist/modules/array.d.ts +1 -1
- package/dist/modules/async.d.ts +1 -1
- package/dist/modules/behavior.d.ts +1 -1
- package/dist/modules/browser.d.ts +1 -1
- package/dist/modules/composition.d.ts +1 -1
- package/dist/modules/contract.d.ts +1 -1
- package/dist/modules/core.d.ts +1 -1
- package/dist/modules/core.js +29 -2
- package/dist/modules/data.d.ts +1 -1
- package/dist/modules/ease.d.ts +1 -1
- package/dist/modules/format.d.ts +1 -1
- package/dist/modules/geo.d.ts +1 -1
- package/dist/modules/graph.d.ts +1 -1
- package/dist/modules/grid.d.ts +1 -1
- package/dist/modules/i18n.d.ts +1 -1
- package/dist/modules/index.d.ts +1 -1
- package/dist/modules/index.js +29 -2
- package/dist/modules/integration.d.ts +1 -1
- package/dist/modules/json.d.ts +1 -1
- package/dist/modules/llm.d.ts +1 -1
- package/dist/modules/math.d.ts +1 -1
- package/dist/modules/memory.d.ts +1 -1
- package/dist/modules/nn.d.ts +1 -1
- package/dist/modules/noise.d.ts +1 -1
- package/dist/modules/object.d.ts +1 -1
- package/dist/modules/os.d.ts +1 -1
- package/dist/modules/path.d.ts +1 -1
- package/dist/modules/prob.d.ts +1 -1
- package/dist/modules/session.d.ts +1 -1
- package/dist/modules/str.d.ts +1 -1
- package/dist/modules/tensor.d.ts +1 -1
- package/dist/modules/time.d.ts +1 -1
- package/dist/modules/trace.d.ts +1 -1
- package/dist/modules/train.d.ts +1 -1
- package/dist/modules/validate.d.ts +1 -1
- package/dist/modules/vector.d.ts +1 -1
- package/dist/modules/workspace.d.ts +1 -1
- package/dist/registry/factory-signatures.json +1 -1
- package/dist/registry.d.ts +2 -2
- package/dist/registry.js +29 -2
- package/dist/{types-Cdb321uM.d.ts → types-Y-yYWEOX.d.ts} +1 -1
- package/i18n/ar.json +3 -1
- package/i18n/en.json +2 -0
- package/i18n/sl.json +3 -1
- package/package.json +3 -3
|
@@ -62,6 +62,9 @@ orbital LearnStepperOrbital {
|
|
|
62
62
|
id : string!
|
|
63
63
|
active : boolean = false
|
|
64
64
|
title : string
|
|
65
|
+
stages : [LearnStepperStage]
|
|
66
|
+
categories : [LearnStepperCategory]
|
|
67
|
+
categorySummaries : [LearnStepperCategorySummary]
|
|
65
68
|
cursorIndex : number
|
|
66
69
|
activeFilter : string
|
|
67
70
|
narration : string
|
|
@@ -78,35 +81,38 @@ orbital LearnStepperOrbital {
|
|
|
78
81
|
initial: idle
|
|
79
82
|
|
|
80
83
|
state idle {
|
|
81
|
-
INIT -> idle when (== @config.matchMode "")
|
|
84
|
+
INIT -> idle when (and (== @config.matchMode "") (== @config.rosterSource "config"))
|
|
82
85
|
(set @entity.active true)
|
|
83
86
|
(set @entity.title @config.title)
|
|
87
|
+
(set @entity.stages @config.stages)
|
|
88
|
+
(set @entity.categories @config.categories)
|
|
89
|
+
(set @entity.categorySummaries @config.categorySummaries)
|
|
84
90
|
(set @entity.cursorIndex -1)
|
|
85
91
|
(set @entity.activeFilter "all")
|
|
86
92
|
(let (
|
|
87
|
-
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @
|
|
88
|
-
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @
|
|
89
|
-
(totalStages (array/len @
|
|
93
|
+
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @entity.stages @entity.cursorIndex) position) (- @config.minPosition 1)))
|
|
94
|
+
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @entity.stages @entity.cursorIndex) null))
|
|
95
|
+
(totalStages (array/len @entity.stages))
|
|
90
96
|
(atEnd (and (>= @entity.cursorIndex 0) (>= @entity.cursorIndex (- @totalStages 1))))
|
|
91
97
|
(stageLabel (if (!= @currentStage null) (object/get @currentStage label) ""))
|
|
92
98
|
(stageDescription (if (!= @currentStage null) (object/get @currentStage description) @config.startPrompt))
|
|
93
99
|
(boundedDescription (if @atEnd (str/concat @stageDescription @config.atEndNote) @stageDescription))
|
|
94
100
|
(narration (if (!= @currentStage null) (str/concat (str/concat "" (object/get @currentStage position)) " — " @stageLabel ". " @boundedDescription) @config.startPrompt))
|
|
95
|
-
(tallyParts (array/map @
|
|
101
|
+
(tallyParts (array/map @entity.categories (fn cc (str/concat (object/get @cc label) ": " (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category))))))))))
|
|
96
102
|
(categoryTally (str/join @tallyParts " · "))
|
|
97
|
-
(tallyItems (array/map @
|
|
98
|
-
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @
|
|
103
|
+
(tallyItems (array/map @entity.categories (fn cc { label: (object/get @cc label), count: (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category)))))) })))
|
|
104
|
+
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @entity.categorySummaries (fn cs (== @cs.category @entity.activeFilter)))) summary)))
|
|
99
105
|
(axisWidth (- @config.width (+ @config.axisMarginLeft @config.axisMarginRight)))
|
|
100
106
|
(baseShapes [
|
|
101
107
|
{ type: line, id: "axis", x1: @config.axisMarginLeft, y1: @config.axisY, x2: (- @config.width @config.axisMarginRight), y2: @config.axisY, tone: "axis", stroke: "normal", opacity: 1 },
|
|
102
108
|
{ type: text, id: "minPositionLabel", x: @config.axisMarginLeft, y: (+ @config.axisY 26), text: (str/concat "" @config.minPosition), textSize: "xs", align: "left", tone: "label" },
|
|
103
109
|
{ type: text, id: "maxPositionLabel", x: (- @config.width @config.axisMarginRight), y: (+ @config.axisY 26), text: (str/concat "" @config.maxPosition), textSize: "xs", align: "right", tone: "label" }
|
|
104
110
|
])
|
|
105
|
-
(markerShapes (array/flatten (array/map @
|
|
111
|
+
(markerShapes (array/flatten (array/map @entity.stages (fn s (let (
|
|
106
112
|
(isRevealed (<= @s.position @currentPosition))
|
|
107
113
|
(isCurrent (== @s.position @currentPosition))
|
|
108
114
|
(matchesFilter (or (== @entity.activeFilter "all") (== @s.category @entity.activeFilter)))
|
|
109
|
-
(catColorObj (array/first (array/filter @
|
|
115
|
+
(catColorObj (array/first (array/filter @entity.categories (fn cc (== @cc.category @s.category)))))
|
|
110
116
|
(catColor (object/get @catColorObj color))
|
|
111
117
|
(col (if @isRevealed @catColor @config.unreachedColor))
|
|
112
118
|
(baseOpacity (if @isRevealed 0.9 0.35))
|
|
@@ -124,14 +130,14 @@ orbital LearnStepperOrbital {
|
|
|
124
130
|
]
|
|
125
131
|
)
|
|
126
132
|
)))))
|
|
127
|
-
(legendShapes (array/flatten (array/map @
|
|
128
|
-
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
129
|
-
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
133
|
+
(legendShapes (array/flatten (array/map @entity.categories [
|
|
134
|
+
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))), y: 22, radius: 5, tone: (object/get @item color), fillTone: (object/get @item color), fillStyle: "solid", opacity: 1 },
|
|
135
|
+
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))) 12), y: 26, text: (object/get @item label), textSize: "xs", align: "left", tone: "label" }
|
|
130
136
|
])))
|
|
131
137
|
(allShapes (array/concat @baseShapes @markerShapes @legendShapes))
|
|
132
138
|
(filterButtons (array/concat [
|
|
133
139
|
{ type: button, action: FILTER_CATEGORY, actionPayload: { category: "all" }, label: @config.allLabel, variant: (if (== @entity.activeFilter "all") "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter "all") "true" "false") }
|
|
134
|
-
] (array/map @
|
|
140
|
+
] (array/map @entity.categories (fn cc { type: button, action: FILTER_CATEGORY, actionPayload: { category: (object/get @cc category) }, label: (object/get @cc label), variant: (if (== @entity.activeFilter (object/get @cc category)) "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter (object/get @cc category)) "true" "false") }))))
|
|
135
141
|
)
|
|
136
142
|
(do
|
|
137
143
|
(set @entity.narration @narration)
|
|
@@ -154,15 +160,15 @@ orbital LearnStepperOrbital {
|
|
|
154
160
|
{ type: typography, variant: h4, content: @entity.title },
|
|
155
161
|
(if (== @config.summary "") null { type: typography, variant: body2, color: muted, content: @config.summary })
|
|
156
162
|
] },
|
|
157
|
-
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @
|
|
163
|
+
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "Complete" (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)))), variant: (if (<= @entity.cursorIndex -1) "neutral" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "success" "primary")) }
|
|
158
164
|
] },
|
|
159
165
|
{ type: stack, direction: horizontal, align: center, gap: sm, wrap: true, children: [
|
|
160
|
-
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @
|
|
166
|
+
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) },
|
|
161
167
|
{ type: button, action: PREV, label: "Prev", icon: "chevron-left", variant: secondary, disabled: (<= @entity.cursorIndex -1) },
|
|
162
168
|
{ type: button, action: RESET_STEPPER, label: "Reset", icon: "rotate-ccw", variant: ghost },
|
|
163
|
-
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @
|
|
169
|
+
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)) }
|
|
164
170
|
] },
|
|
165
|
-
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @
|
|
171
|
+
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @entity.stages), showPercentage: false },
|
|
166
172
|
{ type: stack, direction: horizontal, align: center, gap: xs, wrap: true, role: "group", aria-label: "Category lens", children: @entity.filterButtons },
|
|
167
173
|
{ type: math-canvas, width: @config.width, height: @config.height, backgroundColor: @config.backgroundColor, xMin: 0, xMax: @config.width, yMin: 0, yMax: @config.height, showAxes: false, showGrid: false, gridStep: 1, curves: [], points: [], vectors: [], shapes: @entity.shapes, interactive: @config.interactive, animate: @config.animate, keyMap: { ArrowRight: NEXT, ArrowLeft: PREV, KeyR: RESET_STEPPER } },
|
|
168
174
|
{ type: card, variant: bordered, padding: md, title: (if (!= @entity.currentStageLabel "") @entity.currentStageLabel "Not Started"), children: [
|
|
@@ -178,35 +184,38 @@ orbital LearnStepperOrbital {
|
|
|
178
184
|
(set @entity.active false)
|
|
179
185
|
(render-ui main null)
|
|
180
186
|
|
|
181
|
-
MODE_SELECTED -> idle when (== ?mode @config.matchMode)
|
|
187
|
+
MODE_SELECTED -> idle when (and (== ?mode @config.matchMode) (== @config.rosterSource "config"))
|
|
182
188
|
(set @entity.active true)
|
|
183
189
|
(set @entity.title @config.title)
|
|
190
|
+
(set @entity.stages @config.stages)
|
|
191
|
+
(set @entity.categories @config.categories)
|
|
192
|
+
(set @entity.categorySummaries @config.categorySummaries)
|
|
184
193
|
(set @entity.cursorIndex -1)
|
|
185
194
|
(set @entity.activeFilter "all")
|
|
186
195
|
(let (
|
|
187
|
-
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @
|
|
188
|
-
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @
|
|
189
|
-
(totalStages (array/len @
|
|
196
|
+
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @entity.stages @entity.cursorIndex) position) (- @config.minPosition 1)))
|
|
197
|
+
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @entity.stages @entity.cursorIndex) null))
|
|
198
|
+
(totalStages (array/len @entity.stages))
|
|
190
199
|
(atEnd (and (>= @entity.cursorIndex 0) (>= @entity.cursorIndex (- @totalStages 1))))
|
|
191
200
|
(stageLabel (if (!= @currentStage null) (object/get @currentStage label) ""))
|
|
192
201
|
(stageDescription (if (!= @currentStage null) (object/get @currentStage description) @config.startPrompt))
|
|
193
202
|
(boundedDescription (if @atEnd (str/concat @stageDescription @config.atEndNote) @stageDescription))
|
|
194
203
|
(narration (if (!= @currentStage null) (str/concat (str/concat "" (object/get @currentStage position)) " — " @stageLabel ". " @boundedDescription) @config.startPrompt))
|
|
195
|
-
(tallyParts (array/map @
|
|
204
|
+
(tallyParts (array/map @entity.categories (fn cc (str/concat (object/get @cc label) ": " (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category))))))))))
|
|
196
205
|
(categoryTally (str/join @tallyParts " · "))
|
|
197
|
-
(tallyItems (array/map @
|
|
198
|
-
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @
|
|
206
|
+
(tallyItems (array/map @entity.categories (fn cc { label: (object/get @cc label), count: (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category)))))) })))
|
|
207
|
+
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @entity.categorySummaries (fn cs (== @cs.category @entity.activeFilter)))) summary)))
|
|
199
208
|
(axisWidth (- @config.width (+ @config.axisMarginLeft @config.axisMarginRight)))
|
|
200
209
|
(baseShapes [
|
|
201
210
|
{ type: line, id: "axis", x1: @config.axisMarginLeft, y1: @config.axisY, x2: (- @config.width @config.axisMarginRight), y2: @config.axisY, tone: "axis", stroke: "normal", opacity: 1 },
|
|
202
211
|
{ type: text, id: "minPositionLabel", x: @config.axisMarginLeft, y: (+ @config.axisY 26), text: (str/concat "" @config.minPosition), textSize: "xs", align: "left", tone: "label" },
|
|
203
212
|
{ type: text, id: "maxPositionLabel", x: (- @config.width @config.axisMarginRight), y: (+ @config.axisY 26), text: (str/concat "" @config.maxPosition), textSize: "xs", align: "right", tone: "label" }
|
|
204
213
|
])
|
|
205
|
-
(markerShapes (array/flatten (array/map @
|
|
214
|
+
(markerShapes (array/flatten (array/map @entity.stages (fn s (let (
|
|
206
215
|
(isRevealed (<= @s.position @currentPosition))
|
|
207
216
|
(isCurrent (== @s.position @currentPosition))
|
|
208
217
|
(matchesFilter (or (== @entity.activeFilter "all") (== @s.category @entity.activeFilter)))
|
|
209
|
-
(catColorObj (array/first (array/filter @
|
|
218
|
+
(catColorObj (array/first (array/filter @entity.categories (fn cc (== @cc.category @s.category)))))
|
|
210
219
|
(catColor (object/get @catColorObj color))
|
|
211
220
|
(col (if @isRevealed @catColor @config.unreachedColor))
|
|
212
221
|
(baseOpacity (if @isRevealed 0.9 0.35))
|
|
@@ -224,14 +233,14 @@ orbital LearnStepperOrbital {
|
|
|
224
233
|
]
|
|
225
234
|
)
|
|
226
235
|
)))))
|
|
227
|
-
(legendShapes (array/flatten (array/map @
|
|
228
|
-
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
229
|
-
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
236
|
+
(legendShapes (array/flatten (array/map @entity.categories [
|
|
237
|
+
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))), y: 22, radius: 5, tone: (object/get @item color), fillTone: (object/get @item color), fillStyle: "solid", opacity: 1 },
|
|
238
|
+
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))) 12), y: 26, text: (object/get @item label), textSize: "xs", align: "left", tone: "label" }
|
|
230
239
|
])))
|
|
231
240
|
(allShapes (array/concat @baseShapes @markerShapes @legendShapes))
|
|
232
241
|
(filterButtons (array/concat [
|
|
233
242
|
{ type: button, action: FILTER_CATEGORY, actionPayload: { category: "all" }, label: @config.allLabel, variant: (if (== @entity.activeFilter "all") "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter "all") "true" "false") }
|
|
234
|
-
] (array/map @
|
|
243
|
+
] (array/map @entity.categories (fn cc { type: button, action: FILTER_CATEGORY, actionPayload: { category: (object/get @cc category) }, label: (object/get @cc label), variant: (if (== @entity.activeFilter (object/get @cc category)) "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter (object/get @cc category)) "true" "false") }))))
|
|
235
244
|
)
|
|
236
245
|
(do
|
|
237
246
|
(set @entity.narration @narration)
|
|
@@ -254,15 +263,15 @@ orbital LearnStepperOrbital {
|
|
|
254
263
|
{ type: typography, variant: h4, content: @entity.title },
|
|
255
264
|
(if (== @config.summary "") null { type: typography, variant: body2, color: muted, content: @config.summary })
|
|
256
265
|
] },
|
|
257
|
-
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @
|
|
266
|
+
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "Complete" (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)))), variant: (if (<= @entity.cursorIndex -1) "neutral" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "success" "primary")) }
|
|
258
267
|
] },
|
|
259
268
|
{ type: stack, direction: horizontal, align: center, gap: sm, wrap: true, children: [
|
|
260
|
-
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @
|
|
269
|
+
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) },
|
|
261
270
|
{ type: button, action: PREV, label: "Prev", icon: "chevron-left", variant: secondary, disabled: (<= @entity.cursorIndex -1) },
|
|
262
271
|
{ type: button, action: RESET_STEPPER, label: "Reset", icon: "rotate-ccw", variant: ghost },
|
|
263
|
-
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @
|
|
272
|
+
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)) }
|
|
264
273
|
] },
|
|
265
|
-
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @
|
|
274
|
+
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @entity.stages), showPercentage: false },
|
|
266
275
|
{ type: stack, direction: horizontal, align: center, gap: xs, wrap: true, role: "group", aria-label: "Category lens", children: @entity.filterButtons },
|
|
267
276
|
{ type: math-canvas, width: @config.width, height: @config.height, backgroundColor: @config.backgroundColor, xMin: 0, xMax: @config.width, yMin: 0, yMax: @config.height, showAxes: false, showGrid: false, gridStep: 1, curves: [], points: [], vectors: [], shapes: @entity.shapes, interactive: @config.interactive, animate: @config.animate, keyMap: { ArrowRight: NEXT, ArrowLeft: PREV, KeyR: RESET_STEPPER } },
|
|
268
277
|
{ type: card, variant: bordered, padding: md, title: (if (!= @entity.currentStageLabel "") @entity.currentStageLabel "Not Started"), children: [
|
|
@@ -274,32 +283,136 @@ orbital LearnStepperOrbital {
|
|
|
274
283
|
]
|
|
275
284
|
})
|
|
276
285
|
|
|
286
|
+
ROSTER_LOADED -> idle when (and (== @config.rosterSource "event") (and (== ?mode @config.matchMode) (and (> (array/len ?stages) 0) (> (array/len ?categories) 0))))
|
|
287
|
+
(set @entity.active true)
|
|
288
|
+
(set @entity.title @config.title)
|
|
289
|
+
(set @entity.stages ?stages)
|
|
290
|
+
(set @entity.categories ?categories)
|
|
291
|
+
(set @entity.categorySummaries ?categorySummaries)
|
|
292
|
+
(set @entity.cursorIndex -1)
|
|
293
|
+
(set @entity.activeFilter "all")
|
|
294
|
+
(let (
|
|
295
|
+
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @entity.stages @entity.cursorIndex) position) (- @config.minPosition 1)))
|
|
296
|
+
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @entity.stages @entity.cursorIndex) null))
|
|
297
|
+
(totalStages (array/len @entity.stages))
|
|
298
|
+
(atEnd (and (>= @entity.cursorIndex 0) (>= @entity.cursorIndex (- @totalStages 1))))
|
|
299
|
+
(stageLabel (if (!= @currentStage null) (object/get @currentStage label) ""))
|
|
300
|
+
(stageDescription (if (!= @currentStage null) (object/get @currentStage description) @config.startPrompt))
|
|
301
|
+
(boundedDescription (if @atEnd (str/concat @stageDescription @config.atEndNote) @stageDescription))
|
|
302
|
+
(narration (if (!= @currentStage null) (str/concat (str/concat "" (object/get @currentStage position)) " — " @stageLabel ". " @boundedDescription) @config.startPrompt))
|
|
303
|
+
(tallyParts (array/map @entity.categories (fn cc (str/concat (object/get @cc label) ": " (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category))))))))))
|
|
304
|
+
(categoryTally (str/join @tallyParts " · "))
|
|
305
|
+
(tallyItems (array/map @entity.categories (fn cc { label: (object/get @cc label), count: (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category)))))) })))
|
|
306
|
+
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @entity.categorySummaries (fn cs (== @cs.category @entity.activeFilter)))) summary)))
|
|
307
|
+
(axisWidth (- @config.width (+ @config.axisMarginLeft @config.axisMarginRight)))
|
|
308
|
+
(baseShapes [
|
|
309
|
+
{ type: line, id: "axis", x1: @config.axisMarginLeft, y1: @config.axisY, x2: (- @config.width @config.axisMarginRight), y2: @config.axisY, tone: "axis", stroke: "normal", opacity: 1 },
|
|
310
|
+
{ type: text, id: "minPositionLabel", x: @config.axisMarginLeft, y: (+ @config.axisY 26), text: (str/concat "" @config.minPosition), textSize: "xs", align: "left", tone: "label" },
|
|
311
|
+
{ type: text, id: "maxPositionLabel", x: (- @config.width @config.axisMarginRight), y: (+ @config.axisY 26), text: (str/concat "" @config.maxPosition), textSize: "xs", align: "right", tone: "label" }
|
|
312
|
+
])
|
|
313
|
+
(markerShapes (array/flatten (array/map @entity.stages (fn s (let (
|
|
314
|
+
(isRevealed (<= @s.position @currentPosition))
|
|
315
|
+
(isCurrent (== @s.position @currentPosition))
|
|
316
|
+
(matchesFilter (or (== @entity.activeFilter "all") (== @s.category @entity.activeFilter)))
|
|
317
|
+
(catColorObj (array/first (array/filter @entity.categories (fn cc (== @cc.category @s.category)))))
|
|
318
|
+
(catColor (object/get @catColorObj color))
|
|
319
|
+
(col (if @isRevealed @catColor @config.unreachedColor))
|
|
320
|
+
(baseOpacity (if @isRevealed 0.9 0.35))
|
|
321
|
+
(finalOpacity (if @matchesFilter @baseOpacity (* @baseOpacity 0.25)))
|
|
322
|
+
(xPos (+ @config.axisMarginLeft (* (/ (- @s.position @config.minPosition) (- @config.maxPosition @config.minPosition)) @axisWidth)))
|
|
323
|
+
(rad (if @isCurrent @config.markerHighlightRadius @config.markerRadius))
|
|
324
|
+
)
|
|
325
|
+
(if @isCurrent
|
|
326
|
+
[
|
|
327
|
+
{ type: circle, id: (str/concat "ring-" @s.position), x: @xPos, y: @config.axisY, radius: (+ @rad 5), tone: @catColor, fillStyle: "outline", stroke: "bold", opacity: 1 },
|
|
328
|
+
{ type: circle, id: (str/concat "marker-" @s.position), x: @xPos, y: @config.axisY, radius: @rad, tone: @col, fillTone: @col, fillStyle: "solid", opacity: @finalOpacity }
|
|
329
|
+
]
|
|
330
|
+
[
|
|
331
|
+
{ type: circle, id: (str/concat "marker-" @s.position), x: @xPos, y: @config.axisY, radius: @rad, tone: @col, fillTone: @col, fillStyle: "solid", opacity: @finalOpacity }
|
|
332
|
+
]
|
|
333
|
+
)
|
|
334
|
+
)))))
|
|
335
|
+
(legendShapes (array/flatten (array/map @entity.categories [
|
|
336
|
+
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))), y: 22, radius: 5, tone: (object/get @item color), fillTone: (object/get @item color), fillStyle: "solid", opacity: 1 },
|
|
337
|
+
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))) 12), y: 26, text: (object/get @item label), textSize: "xs", align: "left", tone: "label" }
|
|
338
|
+
])))
|
|
339
|
+
(allShapes (array/concat @baseShapes @markerShapes @legendShapes))
|
|
340
|
+
(filterButtons (array/concat [
|
|
341
|
+
{ type: button, action: FILTER_CATEGORY, actionPayload: { category: "all" }, label: @config.allLabel, variant: (if (== @entity.activeFilter "all") "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter "all") "true" "false") }
|
|
342
|
+
] (array/map @entity.categories (fn cc { type: button, action: FILTER_CATEGORY, actionPayload: { category: (object/get @cc category) }, label: (object/get @cc label), variant: (if (== @entity.activeFilter (object/get @cc category)) "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter (object/get @cc category)) "true" "false") }))))
|
|
343
|
+
)
|
|
344
|
+
(do
|
|
345
|
+
(set @entity.narration @narration)
|
|
346
|
+
(set @entity.currentStageLabel @stageLabel)
|
|
347
|
+
(set @entity.currentStageDescription @boundedDescription)
|
|
348
|
+
(set @entity.categoryTally @categoryTally)
|
|
349
|
+
(set @entity.tallyItems @tallyItems)
|
|
350
|
+
(set @entity.visibleThreadNote @visibleThreadNote)
|
|
351
|
+
(set @entity.shapes @allShapes)
|
|
352
|
+
(set @entity.filterButtons @filterButtons)
|
|
353
|
+
)
|
|
354
|
+
)
|
|
355
|
+
(render-ui main {
|
|
356
|
+
type: box
|
|
357
|
+
padding: md
|
|
358
|
+
children: [
|
|
359
|
+
{ type: stack, direction: vertical, gap: md, children: [
|
|
360
|
+
{ type: stack, direction: horizontal, justify: between, align: start, gap: md, children: [
|
|
361
|
+
{ type: stack, direction: vertical, gap: xs, children: [
|
|
362
|
+
{ type: typography, variant: h4, content: @entity.title },
|
|
363
|
+
(if (== @config.summary "") null { type: typography, variant: body2, color: muted, content: @config.summary })
|
|
364
|
+
] },
|
|
365
|
+
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "Complete" (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)))), variant: (if (<= @entity.cursorIndex -1) "neutral" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "success" "primary")) }
|
|
366
|
+
] },
|
|
367
|
+
{ type: stack, direction: horizontal, align: center, gap: sm, wrap: true, children: [
|
|
368
|
+
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) },
|
|
369
|
+
{ type: button, action: PREV, label: "Prev", icon: "chevron-left", variant: secondary, disabled: (<= @entity.cursorIndex -1) },
|
|
370
|
+
{ type: button, action: RESET_STEPPER, label: "Reset", icon: "rotate-ccw", variant: ghost },
|
|
371
|
+
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)) }
|
|
372
|
+
] },
|
|
373
|
+
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @entity.stages), showPercentage: false },
|
|
374
|
+
{ type: stack, direction: horizontal, align: center, gap: xs, wrap: true, role: "group", aria-label: "Category lens", children: @entity.filterButtons },
|
|
375
|
+
{ type: math-canvas, width: @config.width, height: @config.height, backgroundColor: @config.backgroundColor, xMin: 0, xMax: @config.width, yMin: 0, yMax: @config.height, showAxes: false, showGrid: false, gridStep: 1, curves: [], points: [], vectors: [], shapes: @entity.shapes, interactive: @config.interactive, animate: @config.animate, keyMap: { ArrowRight: NEXT, ArrowLeft: PREV, KeyR: RESET_STEPPER } },
|
|
376
|
+
{ type: card, variant: bordered, padding: md, title: (if (!= @entity.currentStageLabel "") @entity.currentStageLabel "Not Started"), children: [
|
|
377
|
+
{ type: typography, variant: body, content: @entity.currentStageDescription }
|
|
378
|
+
] },
|
|
379
|
+
{ type: stack, direction: horizontal, gap: xs, wrap: true, children: (array/map @entity.tallyItems (fn t { type: badge, variant: neutral, label: (str/concat (object/get @t label) ": " (str/concat "" (object/get @t count))) })) },
|
|
380
|
+
{ type: typography, variant: caption, color: muted, content: @entity.visibleThreadNote }
|
|
381
|
+
] }
|
|
382
|
+
]
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
ROSTER_LOADED -> idle when (and (== @config.rosterSource "event") (not (== ?mode @config.matchMode)))
|
|
386
|
+
(set @entity.active false)
|
|
387
|
+
(render-ui main null)
|
|
388
|
+
|
|
389
|
+
|
|
277
390
|
NEXT -> idle when (== @entity.active true)
|
|
278
|
-
(set @entity.cursorIndex (math/min (+ @entity.cursorIndex 1) (- (array/len @
|
|
391
|
+
(set @entity.cursorIndex (math/min (+ @entity.cursorIndex 1) (- (array/len @entity.stages) 1)))
|
|
279
392
|
(let (
|
|
280
|
-
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @
|
|
281
|
-
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @
|
|
282
|
-
(totalStages (array/len @
|
|
393
|
+
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @entity.stages @entity.cursorIndex) position) (- @config.minPosition 1)))
|
|
394
|
+
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @entity.stages @entity.cursorIndex) null))
|
|
395
|
+
(totalStages (array/len @entity.stages))
|
|
283
396
|
(atEnd (and (>= @entity.cursorIndex 0) (>= @entity.cursorIndex (- @totalStages 1))))
|
|
284
397
|
(stageLabel (if (!= @currentStage null) (object/get @currentStage label) ""))
|
|
285
398
|
(stageDescription (if (!= @currentStage null) (object/get @currentStage description) @config.startPrompt))
|
|
286
399
|
(boundedDescription (if @atEnd (str/concat @stageDescription @config.atEndNote) @stageDescription))
|
|
287
400
|
(narration (if (!= @currentStage null) (str/concat (str/concat "" (object/get @currentStage position)) " — " @stageLabel ". " @boundedDescription) @config.startPrompt))
|
|
288
|
-
(tallyParts (array/map @
|
|
401
|
+
(tallyParts (array/map @entity.categories (fn cc (str/concat (object/get @cc label) ": " (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category))))))))))
|
|
289
402
|
(categoryTally (str/join @tallyParts " · "))
|
|
290
|
-
(tallyItems (array/map @
|
|
291
|
-
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @
|
|
403
|
+
(tallyItems (array/map @entity.categories (fn cc { label: (object/get @cc label), count: (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category)))))) })))
|
|
404
|
+
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @entity.categorySummaries (fn cs (== @cs.category @entity.activeFilter)))) summary)))
|
|
292
405
|
(axisWidth (- @config.width (+ @config.axisMarginLeft @config.axisMarginRight)))
|
|
293
406
|
(baseShapes [
|
|
294
407
|
{ type: line, id: "axis", x1: @config.axisMarginLeft, y1: @config.axisY, x2: (- @config.width @config.axisMarginRight), y2: @config.axisY, tone: "axis", stroke: "normal", opacity: 1 },
|
|
295
408
|
{ type: text, id: "minPositionLabel", x: @config.axisMarginLeft, y: (+ @config.axisY 26), text: (str/concat "" @config.minPosition), textSize: "xs", align: "left", tone: "label" },
|
|
296
409
|
{ type: text, id: "maxPositionLabel", x: (- @config.width @config.axisMarginRight), y: (+ @config.axisY 26), text: (str/concat "" @config.maxPosition), textSize: "xs", align: "right", tone: "label" }
|
|
297
410
|
])
|
|
298
|
-
(markerShapes (array/flatten (array/map @
|
|
411
|
+
(markerShapes (array/flatten (array/map @entity.stages (fn s (let (
|
|
299
412
|
(isRevealed (<= @s.position @currentPosition))
|
|
300
413
|
(isCurrent (== @s.position @currentPosition))
|
|
301
414
|
(matchesFilter (or (== @entity.activeFilter "all") (== @s.category @entity.activeFilter)))
|
|
302
|
-
(catColorObj (array/first (array/filter @
|
|
415
|
+
(catColorObj (array/first (array/filter @entity.categories (fn cc (== @cc.category @s.category)))))
|
|
303
416
|
(catColor (object/get @catColorObj color))
|
|
304
417
|
(col (if @isRevealed @catColor @config.unreachedColor))
|
|
305
418
|
(baseOpacity (if @isRevealed 0.9 0.35))
|
|
@@ -317,14 +430,14 @@ orbital LearnStepperOrbital {
|
|
|
317
430
|
]
|
|
318
431
|
)
|
|
319
432
|
)))))
|
|
320
|
-
(legendShapes (array/flatten (array/map @
|
|
321
|
-
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
322
|
-
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
433
|
+
(legendShapes (array/flatten (array/map @entity.categories [
|
|
434
|
+
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))), y: 22, radius: 5, tone: (object/get @item color), fillTone: (object/get @item color), fillStyle: "solid", opacity: 1 },
|
|
435
|
+
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))) 12), y: 26, text: (object/get @item label), textSize: "xs", align: "left", tone: "label" }
|
|
323
436
|
])))
|
|
324
437
|
(allShapes (array/concat @baseShapes @markerShapes @legendShapes))
|
|
325
438
|
(filterButtons (array/concat [
|
|
326
439
|
{ type: button, action: FILTER_CATEGORY, actionPayload: { category: "all" }, label: @config.allLabel, variant: (if (== @entity.activeFilter "all") "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter "all") "true" "false") }
|
|
327
|
-
] (array/map @
|
|
440
|
+
] (array/map @entity.categories (fn cc { type: button, action: FILTER_CATEGORY, actionPayload: { category: (object/get @cc category) }, label: (object/get @cc label), variant: (if (== @entity.activeFilter (object/get @cc category)) "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter (object/get @cc category)) "true" "false") }))))
|
|
328
441
|
)
|
|
329
442
|
(do
|
|
330
443
|
(set @entity.narration @narration)
|
|
@@ -347,15 +460,15 @@ orbital LearnStepperOrbital {
|
|
|
347
460
|
{ type: typography, variant: h4, content: @entity.title },
|
|
348
461
|
(if (== @config.summary "") null { type: typography, variant: body2, color: muted, content: @config.summary })
|
|
349
462
|
] },
|
|
350
|
-
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @
|
|
463
|
+
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "Complete" (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)))), variant: (if (<= @entity.cursorIndex -1) "neutral" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "success" "primary")) }
|
|
351
464
|
] },
|
|
352
465
|
{ type: stack, direction: horizontal, align: center, gap: sm, wrap: true, children: [
|
|
353
|
-
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @
|
|
466
|
+
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) },
|
|
354
467
|
{ type: button, action: PREV, label: "Prev", icon: "chevron-left", variant: secondary, disabled: (<= @entity.cursorIndex -1) },
|
|
355
468
|
{ type: button, action: RESET_STEPPER, label: "Reset", icon: "rotate-ccw", variant: ghost },
|
|
356
|
-
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @
|
|
469
|
+
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)) }
|
|
357
470
|
] },
|
|
358
|
-
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @
|
|
471
|
+
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @entity.stages), showPercentage: false },
|
|
359
472
|
{ type: stack, direction: horizontal, align: center, gap: xs, wrap: true, role: "group", aria-label: "Category lens", children: @entity.filterButtons },
|
|
360
473
|
{ type: math-canvas, width: @config.width, height: @config.height, backgroundColor: @config.backgroundColor, xMin: 0, xMax: @config.width, yMin: 0, yMax: @config.height, showAxes: false, showGrid: false, gridStep: 1, curves: [], points: [], vectors: [], shapes: @entity.shapes, interactive: @config.interactive, animate: @config.animate, keyMap: { ArrowRight: NEXT, ArrowLeft: PREV, KeyR: RESET_STEPPER } },
|
|
361
474
|
{ type: card, variant: bordered, padding: md, title: (if (!= @entity.currentStageLabel "") @entity.currentStageLabel "Not Started"), children: [
|
|
@@ -371,29 +484,29 @@ orbital LearnStepperOrbital {
|
|
|
371
484
|
PREV -> idle when (== @entity.active true)
|
|
372
485
|
(set @entity.cursorIndex (math/max (- @entity.cursorIndex 1) -1))
|
|
373
486
|
(let (
|
|
374
|
-
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @
|
|
375
|
-
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @
|
|
376
|
-
(totalStages (array/len @
|
|
487
|
+
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @entity.stages @entity.cursorIndex) position) (- @config.minPosition 1)))
|
|
488
|
+
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @entity.stages @entity.cursorIndex) null))
|
|
489
|
+
(totalStages (array/len @entity.stages))
|
|
377
490
|
(atEnd (and (>= @entity.cursorIndex 0) (>= @entity.cursorIndex (- @totalStages 1))))
|
|
378
491
|
(stageLabel (if (!= @currentStage null) (object/get @currentStage label) ""))
|
|
379
492
|
(stageDescription (if (!= @currentStage null) (object/get @currentStage description) @config.startPrompt))
|
|
380
493
|
(boundedDescription (if @atEnd (str/concat @stageDescription @config.atEndNote) @stageDescription))
|
|
381
494
|
(narration (if (!= @currentStage null) (str/concat (str/concat "" (object/get @currentStage position)) " — " @stageLabel ". " @boundedDescription) @config.startPrompt))
|
|
382
|
-
(tallyParts (array/map @
|
|
495
|
+
(tallyParts (array/map @entity.categories (fn cc (str/concat (object/get @cc label) ": " (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category))))))))))
|
|
383
496
|
(categoryTally (str/join @tallyParts " · "))
|
|
384
|
-
(tallyItems (array/map @
|
|
385
|
-
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @
|
|
497
|
+
(tallyItems (array/map @entity.categories (fn cc { label: (object/get @cc label), count: (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category)))))) })))
|
|
498
|
+
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @entity.categorySummaries (fn cs (== @cs.category @entity.activeFilter)))) summary)))
|
|
386
499
|
(axisWidth (- @config.width (+ @config.axisMarginLeft @config.axisMarginRight)))
|
|
387
500
|
(baseShapes [
|
|
388
501
|
{ type: line, id: "axis", x1: @config.axisMarginLeft, y1: @config.axisY, x2: (- @config.width @config.axisMarginRight), y2: @config.axisY, tone: "axis", stroke: "normal", opacity: 1 },
|
|
389
502
|
{ type: text, id: "minPositionLabel", x: @config.axisMarginLeft, y: (+ @config.axisY 26), text: (str/concat "" @config.minPosition), textSize: "xs", align: "left", tone: "label" },
|
|
390
503
|
{ type: text, id: "maxPositionLabel", x: (- @config.width @config.axisMarginRight), y: (+ @config.axisY 26), text: (str/concat "" @config.maxPosition), textSize: "xs", align: "right", tone: "label" }
|
|
391
504
|
])
|
|
392
|
-
(markerShapes (array/flatten (array/map @
|
|
505
|
+
(markerShapes (array/flatten (array/map @entity.stages (fn s (let (
|
|
393
506
|
(isRevealed (<= @s.position @currentPosition))
|
|
394
507
|
(isCurrent (== @s.position @currentPosition))
|
|
395
508
|
(matchesFilter (or (== @entity.activeFilter "all") (== @s.category @entity.activeFilter)))
|
|
396
|
-
(catColorObj (array/first (array/filter @
|
|
509
|
+
(catColorObj (array/first (array/filter @entity.categories (fn cc (== @cc.category @s.category)))))
|
|
397
510
|
(catColor (object/get @catColorObj color))
|
|
398
511
|
(col (if @isRevealed @catColor @config.unreachedColor))
|
|
399
512
|
(baseOpacity (if @isRevealed 0.9 0.35))
|
|
@@ -411,14 +524,14 @@ orbital LearnStepperOrbital {
|
|
|
411
524
|
]
|
|
412
525
|
)
|
|
413
526
|
)))))
|
|
414
|
-
(legendShapes (array/flatten (array/map @
|
|
415
|
-
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
416
|
-
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
527
|
+
(legendShapes (array/flatten (array/map @entity.categories [
|
|
528
|
+
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))), y: 22, radius: 5, tone: (object/get @item color), fillTone: (object/get @item color), fillStyle: "solid", opacity: 1 },
|
|
529
|
+
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))) 12), y: 26, text: (object/get @item label), textSize: "xs", align: "left", tone: "label" }
|
|
417
530
|
])))
|
|
418
531
|
(allShapes (array/concat @baseShapes @markerShapes @legendShapes))
|
|
419
532
|
(filterButtons (array/concat [
|
|
420
533
|
{ type: button, action: FILTER_CATEGORY, actionPayload: { category: "all" }, label: @config.allLabel, variant: (if (== @entity.activeFilter "all") "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter "all") "true" "false") }
|
|
421
|
-
] (array/map @
|
|
534
|
+
] (array/map @entity.categories (fn cc { type: button, action: FILTER_CATEGORY, actionPayload: { category: (object/get @cc category) }, label: (object/get @cc label), variant: (if (== @entity.activeFilter (object/get @cc category)) "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter (object/get @cc category)) "true" "false") }))))
|
|
422
535
|
)
|
|
423
536
|
(do
|
|
424
537
|
(set @entity.narration @narration)
|
|
@@ -441,15 +554,15 @@ orbital LearnStepperOrbital {
|
|
|
441
554
|
{ type: typography, variant: h4, content: @entity.title },
|
|
442
555
|
(if (== @config.summary "") null { type: typography, variant: body2, color: muted, content: @config.summary })
|
|
443
556
|
] },
|
|
444
|
-
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @
|
|
557
|
+
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "Complete" (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)))), variant: (if (<= @entity.cursorIndex -1) "neutral" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "success" "primary")) }
|
|
445
558
|
] },
|
|
446
559
|
{ type: stack, direction: horizontal, align: center, gap: sm, wrap: true, children: [
|
|
447
|
-
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @
|
|
560
|
+
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) },
|
|
448
561
|
{ type: button, action: PREV, label: "Prev", icon: "chevron-left", variant: secondary, disabled: (<= @entity.cursorIndex -1) },
|
|
449
562
|
{ type: button, action: RESET_STEPPER, label: "Reset", icon: "rotate-ccw", variant: ghost },
|
|
450
|
-
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @
|
|
563
|
+
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)) }
|
|
451
564
|
] },
|
|
452
|
-
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @
|
|
565
|
+
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @entity.stages), showPercentage: false },
|
|
453
566
|
{ type: stack, direction: horizontal, align: center, gap: xs, wrap: true, role: "group", aria-label: "Category lens", children: @entity.filterButtons },
|
|
454
567
|
{ type: math-canvas, width: @config.width, height: @config.height, backgroundColor: @config.backgroundColor, xMin: 0, xMax: @config.width, yMin: 0, yMax: @config.height, showAxes: false, showGrid: false, gridStep: 1, curves: [], points: [], vectors: [], shapes: @entity.shapes, interactive: @config.interactive, animate: @config.animate, keyMap: { ArrowRight: NEXT, ArrowLeft: PREV, KeyR: RESET_STEPPER } },
|
|
455
568
|
{ type: card, variant: bordered, padding: md, title: (if (!= @entity.currentStageLabel "") @entity.currentStageLabel "Not Started"), children: [
|
|
@@ -465,29 +578,29 @@ orbital LearnStepperOrbital {
|
|
|
465
578
|
FILTER_CATEGORY -> idle when (== @entity.active true)
|
|
466
579
|
(set @entity.activeFilter ?category)
|
|
467
580
|
(let (
|
|
468
|
-
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @
|
|
469
|
-
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @
|
|
470
|
-
(totalStages (array/len @
|
|
581
|
+
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @entity.stages @entity.cursorIndex) position) (- @config.minPosition 1)))
|
|
582
|
+
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @entity.stages @entity.cursorIndex) null))
|
|
583
|
+
(totalStages (array/len @entity.stages))
|
|
471
584
|
(atEnd (and (>= @entity.cursorIndex 0) (>= @entity.cursorIndex (- @totalStages 1))))
|
|
472
585
|
(stageLabel (if (!= @currentStage null) (object/get @currentStage label) ""))
|
|
473
586
|
(stageDescription (if (!= @currentStage null) (object/get @currentStage description) @config.startPrompt))
|
|
474
587
|
(boundedDescription (if @atEnd (str/concat @stageDescription @config.atEndNote) @stageDescription))
|
|
475
588
|
(narration (if (!= @currentStage null) (str/concat (str/concat "" (object/get @currentStage position)) " — " @stageLabel ". " @boundedDescription) @config.startPrompt))
|
|
476
|
-
(tallyParts (array/map @
|
|
589
|
+
(tallyParts (array/map @entity.categories (fn cc (str/concat (object/get @cc label) ": " (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category))))))))))
|
|
477
590
|
(categoryTally (str/join @tallyParts " · "))
|
|
478
|
-
(tallyItems (array/map @
|
|
479
|
-
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @
|
|
591
|
+
(tallyItems (array/map @entity.categories (fn cc { label: (object/get @cc label), count: (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category)))))) })))
|
|
592
|
+
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @entity.categorySummaries (fn cs (== @cs.category @entity.activeFilter)))) summary)))
|
|
480
593
|
(axisWidth (- @config.width (+ @config.axisMarginLeft @config.axisMarginRight)))
|
|
481
594
|
(baseShapes [
|
|
482
595
|
{ type: line, id: "axis", x1: @config.axisMarginLeft, y1: @config.axisY, x2: (- @config.width @config.axisMarginRight), y2: @config.axisY, tone: "axis", stroke: "normal", opacity: 1 },
|
|
483
596
|
{ type: text, id: "minPositionLabel", x: @config.axisMarginLeft, y: (+ @config.axisY 26), text: (str/concat "" @config.minPosition), textSize: "xs", align: "left", tone: "label" },
|
|
484
597
|
{ type: text, id: "maxPositionLabel", x: (- @config.width @config.axisMarginRight), y: (+ @config.axisY 26), text: (str/concat "" @config.maxPosition), textSize: "xs", align: "right", tone: "label" }
|
|
485
598
|
])
|
|
486
|
-
(markerShapes (array/flatten (array/map @
|
|
599
|
+
(markerShapes (array/flatten (array/map @entity.stages (fn s (let (
|
|
487
600
|
(isRevealed (<= @s.position @currentPosition))
|
|
488
601
|
(isCurrent (== @s.position @currentPosition))
|
|
489
602
|
(matchesFilter (or (== @entity.activeFilter "all") (== @s.category @entity.activeFilter)))
|
|
490
|
-
(catColorObj (array/first (array/filter @
|
|
603
|
+
(catColorObj (array/first (array/filter @entity.categories (fn cc (== @cc.category @s.category)))))
|
|
491
604
|
(catColor (object/get @catColorObj color))
|
|
492
605
|
(col (if @isRevealed @catColor @config.unreachedColor))
|
|
493
606
|
(baseOpacity (if @isRevealed 0.9 0.35))
|
|
@@ -505,14 +618,14 @@ orbital LearnStepperOrbital {
|
|
|
505
618
|
]
|
|
506
619
|
)
|
|
507
620
|
)))))
|
|
508
|
-
(legendShapes (array/flatten (array/map @
|
|
509
|
-
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
510
|
-
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
621
|
+
(legendShapes (array/flatten (array/map @entity.categories [
|
|
622
|
+
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))), y: 22, radius: 5, tone: (object/get @item color), fillTone: (object/get @item color), fillStyle: "solid", opacity: 1 },
|
|
623
|
+
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))) 12), y: 26, text: (object/get @item label), textSize: "xs", align: "left", tone: "label" }
|
|
511
624
|
])))
|
|
512
625
|
(allShapes (array/concat @baseShapes @markerShapes @legendShapes))
|
|
513
626
|
(filterButtons (array/concat [
|
|
514
627
|
{ type: button, action: FILTER_CATEGORY, actionPayload: { category: "all" }, label: @config.allLabel, variant: (if (== @entity.activeFilter "all") "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter "all") "true" "false") }
|
|
515
|
-
] (array/map @
|
|
628
|
+
] (array/map @entity.categories (fn cc { type: button, action: FILTER_CATEGORY, actionPayload: { category: (object/get @cc category) }, label: (object/get @cc label), variant: (if (== @entity.activeFilter (object/get @cc category)) "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter (object/get @cc category)) "true" "false") }))))
|
|
516
629
|
)
|
|
517
630
|
(do
|
|
518
631
|
(set @entity.narration @narration)
|
|
@@ -535,15 +648,15 @@ orbital LearnStepperOrbital {
|
|
|
535
648
|
{ type: typography, variant: h4, content: @entity.title },
|
|
536
649
|
(if (== @config.summary "") null { type: typography, variant: body2, color: muted, content: @config.summary })
|
|
537
650
|
] },
|
|
538
|
-
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @
|
|
651
|
+
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "Complete" (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)))), variant: (if (<= @entity.cursorIndex -1) "neutral" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "success" "primary")) }
|
|
539
652
|
] },
|
|
540
653
|
{ type: stack, direction: horizontal, align: center, gap: sm, wrap: true, children: [
|
|
541
|
-
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @
|
|
654
|
+
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) },
|
|
542
655
|
{ type: button, action: PREV, label: "Prev", icon: "chevron-left", variant: secondary, disabled: (<= @entity.cursorIndex -1) },
|
|
543
656
|
{ type: button, action: RESET_STEPPER, label: "Reset", icon: "rotate-ccw", variant: ghost },
|
|
544
|
-
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @
|
|
657
|
+
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)) }
|
|
545
658
|
] },
|
|
546
|
-
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @
|
|
659
|
+
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @entity.stages), showPercentage: false },
|
|
547
660
|
{ type: stack, direction: horizontal, align: center, gap: xs, wrap: true, role: "group", aria-label: "Category lens", children: @entity.filterButtons },
|
|
548
661
|
{ type: math-canvas, width: @config.width, height: @config.height, backgroundColor: @config.backgroundColor, xMin: 0, xMax: @config.width, yMin: 0, yMax: @config.height, showAxes: false, showGrid: false, gridStep: 1, curves: [], points: [], vectors: [], shapes: @entity.shapes, interactive: @config.interactive, animate: @config.animate, keyMap: { ArrowRight: NEXT, ArrowLeft: PREV, KeyR: RESET_STEPPER } },
|
|
549
662
|
{ type: card, variant: bordered, padding: md, title: (if (!= @entity.currentStageLabel "") @entity.currentStageLabel "Not Started"), children: [
|
|
@@ -560,29 +673,29 @@ orbital LearnStepperOrbital {
|
|
|
560
673
|
(set @entity.cursorIndex -1)
|
|
561
674
|
(set @entity.activeFilter "all")
|
|
562
675
|
(let (
|
|
563
|
-
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @
|
|
564
|
-
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @
|
|
565
|
-
(totalStages (array/len @
|
|
676
|
+
(currentPosition (if (>= @entity.cursorIndex 0) (object/get (array/nth @entity.stages @entity.cursorIndex) position) (- @config.minPosition 1)))
|
|
677
|
+
(currentStage (if (>= @entity.cursorIndex 0) (array/nth @entity.stages @entity.cursorIndex) null))
|
|
678
|
+
(totalStages (array/len @entity.stages))
|
|
566
679
|
(atEnd (and (>= @entity.cursorIndex 0) (>= @entity.cursorIndex (- @totalStages 1))))
|
|
567
680
|
(stageLabel (if (!= @currentStage null) (object/get @currentStage label) ""))
|
|
568
681
|
(stageDescription (if (!= @currentStage null) (object/get @currentStage description) @config.startPrompt))
|
|
569
682
|
(boundedDescription (if @atEnd (str/concat @stageDescription @config.atEndNote) @stageDescription))
|
|
570
683
|
(narration (if (!= @currentStage null) (str/concat (str/concat "" (object/get @currentStage position)) " — " @stageLabel ". " @boundedDescription) @config.startPrompt))
|
|
571
|
-
(tallyParts (array/map @
|
|
684
|
+
(tallyParts (array/map @entity.categories (fn cc (str/concat (object/get @cc label) ": " (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category))))))))))
|
|
572
685
|
(categoryTally (str/join @tallyParts " · "))
|
|
573
|
-
(tallyItems (array/map @
|
|
574
|
-
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @
|
|
686
|
+
(tallyItems (array/map @entity.categories (fn cc { label: (object/get @cc label), count: (array/len (array/filter @entity.stages (fn s (and (<= @s.position @currentPosition) (== @s.category (object/get @cc category)))))) })))
|
|
687
|
+
(visibleThreadNote (if (== @entity.activeFilter "all") @config.allSummary (object/get (array/first (array/filter @entity.categorySummaries (fn cs (== @cs.category @entity.activeFilter)))) summary)))
|
|
575
688
|
(axisWidth (- @config.width (+ @config.axisMarginLeft @config.axisMarginRight)))
|
|
576
689
|
(baseShapes [
|
|
577
690
|
{ type: line, id: "axis", x1: @config.axisMarginLeft, y1: @config.axisY, x2: (- @config.width @config.axisMarginRight), y2: @config.axisY, tone: "axis", stroke: "normal", opacity: 1 },
|
|
578
691
|
{ type: text, id: "minPositionLabel", x: @config.axisMarginLeft, y: (+ @config.axisY 26), text: (str/concat "" @config.minPosition), textSize: "xs", align: "left", tone: "label" },
|
|
579
692
|
{ type: text, id: "maxPositionLabel", x: (- @config.width @config.axisMarginRight), y: (+ @config.axisY 26), text: (str/concat "" @config.maxPosition), textSize: "xs", align: "right", tone: "label" }
|
|
580
693
|
])
|
|
581
|
-
(markerShapes (array/flatten (array/map @
|
|
694
|
+
(markerShapes (array/flatten (array/map @entity.stages (fn s (let (
|
|
582
695
|
(isRevealed (<= @s.position @currentPosition))
|
|
583
696
|
(isCurrent (== @s.position @currentPosition))
|
|
584
697
|
(matchesFilter (or (== @entity.activeFilter "all") (== @s.category @entity.activeFilter)))
|
|
585
|
-
(catColorObj (array/first (array/filter @
|
|
698
|
+
(catColorObj (array/first (array/filter @entity.categories (fn cc (== @cc.category @s.category)))))
|
|
586
699
|
(catColor (object/get @catColorObj color))
|
|
587
700
|
(col (if @isRevealed @catColor @config.unreachedColor))
|
|
588
701
|
(baseOpacity (if @isRevealed 0.9 0.35))
|
|
@@ -600,14 +713,14 @@ orbital LearnStepperOrbital {
|
|
|
600
713
|
]
|
|
601
714
|
)
|
|
602
715
|
)))))
|
|
603
|
-
(legendShapes (array/flatten (array/map @
|
|
604
|
-
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
605
|
-
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @
|
|
716
|
+
(legendShapes (array/flatten (array/map @entity.categories [
|
|
717
|
+
{ type: circle, id: (str/concat "legend-dot-" @index), x: (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))), y: 22, radius: 5, tone: (object/get @item color), fillTone: (object/get @item color), fillStyle: "solid", opacity: 1 },
|
|
718
|
+
{ type: text, id: (str/concat "legend-label-" @index), x: (+ (+ @config.axisMarginLeft (* @index (/ @axisWidth (array/len @entity.categories)))) 12), y: 26, text: (object/get @item label), textSize: "xs", align: "left", tone: "label" }
|
|
606
719
|
])))
|
|
607
720
|
(allShapes (array/concat @baseShapes @markerShapes @legendShapes))
|
|
608
721
|
(filterButtons (array/concat [
|
|
609
722
|
{ type: button, action: FILTER_CATEGORY, actionPayload: { category: "all" }, label: @config.allLabel, variant: (if (== @entity.activeFilter "all") "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter "all") "true" "false") }
|
|
610
|
-
] (array/map @
|
|
723
|
+
] (array/map @entity.categories (fn cc { type: button, action: FILTER_CATEGORY, actionPayload: { category: (object/get @cc category) }, label: (object/get @cc label), variant: (if (== @entity.activeFilter (object/get @cc category)) "secondary" "ghost"), size: sm, aria-pressed: (if (== @entity.activeFilter (object/get @cc category)) "true" "false") }))))
|
|
611
724
|
)
|
|
612
725
|
(do
|
|
613
726
|
(set @entity.narration @narration)
|
|
@@ -630,15 +743,15 @@ orbital LearnStepperOrbital {
|
|
|
630
743
|
{ type: typography, variant: h4, content: @entity.title },
|
|
631
744
|
(if (== @config.summary "") null { type: typography, variant: body2, color: muted, content: @config.summary })
|
|
632
745
|
] },
|
|
633
|
-
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @
|
|
746
|
+
{ type: badge, label: (if (<= @entity.cursorIndex -1) "Not started" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "Complete" (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)))), variant: (if (<= @entity.cursorIndex -1) "neutral" (if (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) "success" "primary")) }
|
|
634
747
|
] },
|
|
635
748
|
{ type: stack, direction: horizontal, align: center, gap: sm, wrap: true, children: [
|
|
636
|
-
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @
|
|
749
|
+
{ type: button, action: NEXT, label: "Next", icon: "chevron-right", variant: primary, disabled: (>= @entity.cursorIndex (- (array/len @entity.stages) 1)) },
|
|
637
750
|
{ type: button, action: PREV, label: "Prev", icon: "chevron-left", variant: secondary, disabled: (<= @entity.cursorIndex -1) },
|
|
638
751
|
{ type: button, action: RESET_STEPPER, label: "Reset", icon: "rotate-ccw", variant: ghost },
|
|
639
|
-
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @
|
|
752
|
+
{ type: typography, variant: caption, color: muted, content: (str/concat "Stage " (+ @entity.cursorIndex 1) " of " (array/len @entity.stages)) }
|
|
640
753
|
] },
|
|
641
|
-
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @
|
|
754
|
+
{ type: progress-bar, value: (+ @entity.cursorIndex 1), max: (array/len @entity.stages), showPercentage: false },
|
|
642
755
|
{ type: stack, direction: horizontal, align: center, gap: xs, wrap: true, role: "group", aria-label: "Category lens", children: @entity.filterButtons },
|
|
643
756
|
{ type: math-canvas, width: @config.width, height: @config.height, backgroundColor: @config.backgroundColor, xMin: 0, xMax: @config.width, yMin: 0, yMax: @config.height, showAxes: false, showGrid: false, gridStep: 1, curves: [], points: [], vectors: [], shapes: @entity.shapes, interactive: @config.interactive, animate: @config.animate, keyMap: { ArrowRight: NEXT, ArrowLeft: PREV, KeyR: RESET_STEPPER } },
|
|
644
757
|
{ type: card, variant: bordered, padding: md, title: (if (!= @entity.currentStageLabel "") @entity.currentStageLabel "Not Started"), children: [
|
|
@@ -659,6 +772,14 @@ orbital LearnStepperOrbital {
|
|
|
659
772
|
}
|
|
660
773
|
@description "Lab router broadcast naming the active mode; this instrument renders when the mode equals matchMode, otherwise renders null."
|
|
661
774
|
@tier "domain"
|
|
775
|
+
ROSTER_LOADED {
|
|
776
|
+
mode : string!
|
|
777
|
+
stages : [LearnStepperStage]!
|
|
778
|
+
categories : [LearnStepperCategory]!
|
|
779
|
+
categorySummaries : [LearnStepperCategorySummary]!
|
|
780
|
+
}
|
|
781
|
+
@description "Runtime content feed, honoured only when rosterSource is event — mode names the instrument it is for (the matchMode it carries, blank when standalone) and stages, categories and categorySummaries are the roster; a matching instrument re-initialises from it exactly as INIT does from config, any other instrument hides."
|
|
782
|
+
@tier "domain"
|
|
662
783
|
NEXT {
|
|
663
784
|
}
|
|
664
785
|
@description "Learner advanced the cursor to the next stage in the ordered roster; clamps at the last stage with a narrated end note rather than wrapping."
|
|
@@ -694,6 +815,10 @@ orbital LearnStepperOrbital {
|
|
|
694
815
|
@label "Match Mode"
|
|
695
816
|
@description "When composed behind a lab router, the MODE_SELECTED mode value this instrument responds to. Empty string means standalone — render immediately on INIT."
|
|
696
817
|
@tier "presentation"
|
|
818
|
+
rosterSource : "config" | "event" = "config"
|
|
819
|
+
@label "Roster Source"
|
|
820
|
+
@description "Where the stages, categories and category summaries come from: config reads those knobs at INIT; event waits for ROSTER_LOADED and takes them from its payload. The axis range (minPosition/maxPosition) stays config."
|
|
821
|
+
@tier "domain"
|
|
697
822
|
title : string = "Stepper"
|
|
698
823
|
@label "Title"
|
|
699
824
|
@description "The instrument's name, the header's one hero."
|