package miaou-core
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Miaou core/widgets (no drivers, no SDL)
Install
dune-project
Dependency
Authors
Maintainers
Sources
v0.5.2.tar.gz
md5=60a3b9f181f24572a06a9492532bfdda
sha512=fcc35a275066be2900e6201782faf47503076fa4640f08cf78067835a6f447b74613009e55b2ac799adb7ca46f1bffa261fc5971753f2cc3c6bef327511c7ef6
doc/src/miaou_widgets_layout/wizard_widget.ml.html
Source file wizard_widget.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133(*****************************************************************************) (* *) (* SPDX-License-Identifier: MIT *) (* Copyright (c) 2026 Nomadic Labs <contact@nomadic-labs.com> *) (* *) (*****************************************************************************) module W = Miaou_widgets_display.Widgets type 'state step = { title : string; render : 'state -> focus:bool -> size:LTerm_geom.size -> string; validate : 'state -> (unit, string) result; on_key : 'state -> key:string -> 'state; } type 'state t = { steps : 'state step array; current : int; state : 'state; error : string option; cancelled : bool; finished : bool; } let create ~steps ~initial = if Array.length steps = 0 then invalid_arg "Wizard_widget.create: steps must be non-empty" ; { steps; current = 0; state = initial; error = None; cancelled = false; finished = false; } let current_step t = t.steps.(t.current) let state t = t.state let set_state t state = {t with state} let current_index t = t.current let step_count t = Array.length t.steps let current_title t = (current_step t).title let is_finished t = t.finished let is_cancelled t = t.cancelled let current_error t = t.error let advance t = if t.finished || t.cancelled then t else let step = current_step t in match step.validate t.state with | Error msg -> {t with error = Some msg} | Ok () -> if t.current = Array.length t.steps - 1 then {t with finished = true; error = None} else {t with current = t.current + 1; error = None} let back t = if t.current = 0 then t else {t with current = t.current - 1; error = None} let cancel t = {t with cancelled = true} let handle_key t ~key = if t.finished || t.cancelled then t else match key with | "Enter" -> advance t | "Escape" | "Esc" -> cancel t | "C-Left" | "Shift-Tab" | "S-Tab" -> back t | _ -> let step = current_step t in {t with state = step.on_key t.state ~key; error = None} let t = let n = Array.length t.steps in let buf = Buffer.create 64 in for i = 0 to n - 1 do let title = t.steps.(i).title in let dot = if i = t.current then "●" else if i < t.current then "●" else "○" in let label = Printf.sprintf "%s %d. %s" dot (i + 1) title in let styled = if i = t.current then W.themed_emphasis label else if i < t.current then W.themed_muted label else W.themed_text label in Buffer.add_string buf styled ; if i < n - 1 then Buffer.add_string buf (W.themed_muted " → ") done ; Buffer.contents buf let render t ~focus ~size = let step = current_step t in let header = breadcrumbs t in let body = step.render t.state ~focus ~size in let error_line = match t.error with | Some msg -> "\n" ^ W.themed_error ("✗ " ^ msg) | None -> "" in let = let n = Array.length t.steps in let next_or_finish = if t.current = n - 1 then "Finish" else "Next" in let parts = [ Some (W.themed_muted (Printf.sprintf "[Enter: %s]" next_or_finish)); (if t.current > 0 then Some (W.themed_muted "[Shift+Tab: Back]") else None); Some (W.themed_muted "[Esc: Cancel]"); ] in let parts = List.filter_map (fun x -> x) parts in String.concat " " parts in let status = if t.finished then W.themed_success "✓ Wizard complete." else if t.cancelled then W.themed_warning "⊘ Wizard cancelled." else nav_hint in String.concat "\n" [header; ""; body; error_line; ""; status] let () = Miaou_registry.register ~name:"wizard" ~mli:[%blob "wizard_widget.mli"] ()
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>