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
134
135
136
137
// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2026 FernTech
//! Tier-3 style protocol for `Calendar`. See `docs/styling-system.md`.
//!
//! Multi-method trait because `Calendar` paints three distinct cell
//! shapes, each with its own state semantics:
//!
//! * **Day cell** (`make_day_cell`) — the 6×7 grid of day numbers.
//! Static state (today / out-of-month / disabled) is computed at
//! build time; the selection-derived fill role and the roving-focus
//! ring are reactive signals so navigation doesn't rebuild 42 cells.
//! * **Zoom cell** (`make_zoom_cell`) — the 4×3 month / year picker
//! cells. Hover and pressed are reactive (cells handle their own
//! pointer state); `selected` is reactive against the visible month.
//! * **Header** (`make_header`) — the prev-double / prev / title /
//! next / next-double row. The four arrow buttons and the title
//! button are pre-built (the widget computes the mode-aware step
//! callbacks); the style only lays them out.
//!
//! Outer chrome (the calendar's background frame + padding) is a thin
//! popover-style surface and stays widget-owned via raw shape tokens —
//! not an additional style method.
use Rc;
use crateBuildContext;
use crateSignal;
use crateWidgetId;
/// Selection-derived fill state for a day cell. The reactive signal in
/// `CalendarDayConfig` recomputes on every selection change without
/// re-`build()`ing the cell.
/// Per-day cell input to `CalendarStyle::make_day_cell`.
///
/// The static fields (`is_today`, `is_out_of_month`, `is_disabled`)
/// don't change within a build session — the calendar binds
/// `visible_month` at `Rebuild` level, so cells are regenerated when
/// the visible month moves. Everything reactive (selection fill, the
/// roving-focus ring) flows through `Signal`s so per-click navigation
/// doesn't tear down the 42-cell subtree.
///
/// `label` is passed as a plain string rather than a pre-built widget
/// id so the recipe owns the label's text-colour binding — the label
/// colour depends on the reactive fill state (Selected → `OnAccent`,
/// otherwise `Primary`) which is paint-time data, not widget-construction
/// data.
/// Per-cell input to `CalendarStyle::make_zoom_cell` (used for both
/// `MonthsGrid` and `YearsGrid` cells).
/// Pre-built header components passed to `make_header`. All five slots
/// are pre-built widgets; the recipe lays them out into a horizontal
/// strip. When `show_navigation = false` on the calendar, every arrow
/// slot is `None` and the recipe still returns a row containing just
/// the title.
pub type SharedCalendarStyle = ;