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_navigation/breadcrumbs_widget.ml.html
Source file breadcrumbs_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(*****************************************************************************) (* *) (* SPDX-License-Identifier: MIT *) (* Copyright (c) 2025 Nomadic Labs <contact@nomadic-labs.com> *) (* *) (*****************************************************************************) [@@@warning "-32-34-37-69"] module W = Miaou_widgets_display.Widgets module Helpers = Miaou_helpers.Helpers type crumb = {id : string; label : string; on_enter : (unit -> unit) option} type t = {crumbs : crumb list; selected : int} let crumb ~id ~label ?on_enter () = {id; label; on_enter} let id c = c.id let label c = c.label let clamp idx len = if len = 0 then 0 else max 0 (min (len - 1) idx) let make crumbs = let crumbs = List.filter (fun c -> String.length c.label > 0) crumbs |> List.map (fun c -> {id = c.id; label = c.label; on_enter = c.on_enter}) in {crumbs; selected = clamp 0 (List.length crumbs)} let current t = List.nth_opt t.crumbs t.selected let move t dir = let len = List.length t.crumbs in if len = 0 then t else let next = match dir with | `Left -> max 0 (t.selected - 1) | `Right -> min (len - 1) (t.selected + 1) | `First -> 0 | `Last -> len - 1 in {t with selected = next} let select t ~id = let rec find i = function | [] -> t.selected | c :: cs -> if String.equal c.id id then i else find (i + 1) cs in let len = List.length t.crumbs in let idx = clamp (find 0 t.crumbs) len in {t with selected = idx} let handle_event ?(bubble_unhandled = false) t ~key = match Miaou_core.Keys.of_string key with | Some Miaou_core.Keys.Left -> (move t `Left, `Handled) | Some Miaou_core.Keys.Right -> (move t `Right, `Handled) | Some (Miaou_core.Keys.Char "Home") -> (move t `First, `Handled) | Some (Miaou_core.Keys.Char "End") -> (move t `Last, `Handled) | Some Miaou_core.Keys.Enter -> ( match current t with | Some {on_enter = Some f; _} -> f () ; (t, `Handled) | _ -> (t, if bubble_unhandled then `Bubble else `Handled)) | _ -> ( (* Check for mouse click to select crumb *) match Miaou_helpers.Mouse.parse_click key with | Some {col; _} -> ( (* Calculate which crumb was clicked based on column position. Each crumb is: "label" + " > " separator (3 chars). *) let rec find_crumb idx pos crumbs = match crumbs with | [] -> None | crumb :: rest -> let crumb_width = String.length crumb.label in let sep_width = if rest = [] then 0 else 3 in (* " > " *) let total = crumb_width + sep_width in if col >= pos && col < pos + crumb_width then Some idx else find_crumb (idx + 1) (pos + total) rest in match find_crumb 0 1 t.crumbs with | Some idx -> ( let t' = {t with selected = idx} in (* Also trigger on_enter if clicking *) match List.nth_opt t'.crumbs idx with | Some {on_enter = Some f; _} -> f () ; (t', `Handled) | _ -> (t', `Handled)) | None -> (t, if bubble_unhandled then `Bubble else `Handled)) | None -> (t, if bubble_unhandled then `Bubble else `Handled)) let handle_key t ~key = let t, status = handle_event t ~key in (t, match status with `Handled -> `Handled | `Bubble -> `Ignored) let render t ~focus = let parts = List.mapi (fun i c -> let base = if i = t.selected then W.bold c.label else W.dim c.label in if focus && i = t.selected then W.title_highlight base else base) t.crumbs in match parts with [] -> "" | _ -> Helpers.concat_with_sep (W.dim " > ") parts
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>