Bases: LayoutControl
A Flet control that wraps the Flutter m3_carousel package.
The carousel layout and animation are delegated to the upstream
package.
Source code in src/flet_m3_carousel/flet_m3_carousel.py
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328 | @control("M3Carousel") # type: ignore[arg-type]
class M3Carousel(LayoutControl):
"""A Flet control that wraps the Flutter ``m3_carousel`` package.
The carousel layout and animation are delegated to the upstream
package.
"""
items: list[M3CarouselItem] = field(default_factory=list)
layout: str = "hero"
axis: str = "horizontal"
hero_alignment: str = "center"
is_extended: bool | None = None
free_scroll: bool | None = None
uncontained_item_extent: float | None = None
uncontained_shrink_extent: float | None = None
child_element_border_radius: float | None = None
large_max_width: float | None = None
item_padding: float | None = None
scroll_animation_duration: int | None = None
fixed_pulse_delta: float = 4.0
single_swipe_gesture_sensitivity_range: int | None = None
haptic: str = "none"
header: str | None = None
show_all: bool = False
on_tap: EventHandler[M3CarouselTapEvent] | None = None
on_change: EventHandler[M3CarouselChangeEvent] | None = None
def __post_init__(self, ref: Any | None = None) -> None:
# Normalize and validate scalar fields.
self.layout = _normalize_layout(self.layout)
self.axis = _normalize_axis(self.axis)
self.hero_alignment = _normalize_alignment(self.hero_alignment)
self.haptic = _normalize_haptic(self.haptic)
self.haptic = _normalize_haptic(self.haptic)
if self.items is None:
self.items = []
if not isinstance(self.items, (list, tuple)):
raise TypeError(f"items must be a list or tuple, got {type(self.items).__name__}")
normalized_items: list[M3CarouselItem] = []
seen_keys: set[str] = set()
for item in self.items:
if not isinstance(item, M3CarouselItem):
raise TypeError(
f"items must contain M3CarouselItem instances, got {type(item).__name__}"
)
if item.key is not None:
if item.key in seen_keys:
raise ValueError(f"duplicate key: {item.key!r}")
seen_keys.add(item.key)
normalized_items.append(item)
self.items = normalized_items
super().__post_init__(ref)
def serialize_items(self) -> list[dict[str, Any]]:
return serialize_items(self.items)
async def scroll_to(self, index: int = 0) -> None:
await self._invoke_method("scroll_to", {"index": index})
async def jump_to_item(self, index: int = 0) -> None:
await self._invoke_method("jump_to_item", {"index": index})
async def animate_to_item(self, index: int = 0) -> None:
await self._invoke_method("animate_to_item", {"index": index})
async def next(self) -> None:
await self._invoke_method("next", {})
async def previous(self) -> None:
await self._invoke_method("previous", {})
async def show_all_items(self) -> None:
await self._invoke_method("show_all", {})
def to_dict(self) -> dict[str, Any]:
result: dict[str, Any] = {
"items": serialize_items(self.items),
"layout": self.layout,
"axis": self.axis,
"hero_alignment": self.hero_alignment,
}
if self.is_extended is not None:
result["is_extended"] = self.is_extended
if self.free_scroll is not None:
result["free_scroll"] = self.free_scroll
if self.uncontained_item_extent is not None:
result["uncontained_item_extent"] = self.uncontained_item_extent
if self.uncontained_shrink_extent is not None:
result["uncontained_shrink_extent"] = self.uncontained_shrink_extent
if self.child_element_border_radius is not None:
result["child_element_border_radius"] = self.child_element_border_radius
if self.large_max_width is not None:
result["large_max_width"] = self.large_max_width
if self.item_padding is not None:
result["item_padding"] = self.item_padding
if self.scroll_animation_duration is not None:
result["scroll_animation_duration"] = self.scroll_animation_duration
if self.fixed_pulse_delta != 4.0:
result["fixed_pulse_delta"] = self.fixed_pulse_delta
if self.single_swipe_gesture_sensitivity_range is not None:
result["single_swipe_gesture_sensitivity_range"] = (
self.single_swipe_gesture_sensitivity_range
)
if self.haptic != "none":
result["haptic"] = self.haptic
if self.header is not None:
result["header"] = self.header
if self.show_all:
result["show_all"] = True
return result
|