4 Commits

Author SHA1 Message Date
3aa4ceada5 feat(components): let picker content own its scrolling
CollapsingScaffold always wrapped its content in a verticalScroll Column,
which composes every row up front. That suits the short lists these
surfaces normally hold, but it rules out a LazyColumn entirely: nesting a
same-axis scrollable inside it throws, so a caller with a few hundred
options had no way to render them.

Add `scrollable` (default true, so every existing caller is unchanged).
When false the content gets a plain column to fill and brings its own
scrolling container, keeping the insets, IME padding and top-bar collapse
as they were. FullScreenPicker forwards the flag for pickers that need it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 15:31:18 +02:00
a50878a7ac release: floret-kit 0.2.0
Adds core-locale's formatting half (currentLocale, localizedDateFormatter) and
components' CustomAmountEditor. The root version was already 0.2.0 — 2124227
bumped it without a changelog entry, so this cut backfills that alongside
core-locale's AppLanguage, which shipped in 0.1.0 undocumented.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 14:56:18 +02:00
a1884fc5fa Merge branch 'feat/locale-date-formatting' into main 2026-07-17 14:54:38 +02:00
60dd4eea71 Merge pull request 'feat(components): add CustomAmountEditor, bump to 0.2.0' (#1) from feat/custom-snooze-duration into main
Reviewed-on: #1
2026-07-12 10:31:02 +00:00
4 changed files with 43 additions and 3 deletions

View File

@@ -6,12 +6,17 @@ All notable changes to floret-kit are documented here. The format follows
floret-kit is consumed **from source** — each app embeds it as a git submodule floret-kit is consumed **from source** — each app embeds it as a git submodule
and builds it through a Gradle composite build, pinning a specific commit. There and builds it through a Gradle composite build, pinning a specific commit. There
are no binary releases; "version" tracks the shared `version` in the root build are no binary releases; "version" tracks the shared `version` in the root build
(currently `0.1.0`). Entries are grouped by module. (currently `0.2.0`). Entries are grouped by module.
## [Unreleased] ## [Unreleased]
## [0.2.0] - 2026-07-17
### Added ### Added
- **`components`** — `CustomAmountEditor`, the amount + unit editor behind an
"Custom…" picker option (Calendula's custom snooze duration). Consumed by
Calendula since 2.15.0.
- **`core-locale`** — the locale-aware formatting half of the module, so apps - **`core-locale`** — the locale-aware formatting half of the module, so apps
stop hand-rolling `"$day. $month $year"` templates that bake one language's stop hand-rolling `"$day. $month $year"` templates that bake one language's
field order (and its separators, and its ordinal dot) into every language they field order (and its separators, and its ordinal dot) into every language they
@@ -46,6 +51,12 @@ are no binary releases; "version" tracks the shared `version` in the root build
### Added ### Added
- **`core-locale`** (Android library) — per-app language plumbing (`AppLanguage`):
read the shipped languages from the app's `res/xml/locales_config.xml`, get/set
the applied language via `AppCompatDelegate`, render each language's autonym.
The app passes its own `locales_config` resource id; the system-default choice
is `null`. _(Shipped in 0.1.0 but omitted from this changelog at the time;
recorded here retroactively.)_
- **`core-time`** (JVM library) — pure-Kotlin date/time helpers, no Android and - **`core-time`** (JVM library) — pure-Kotlin date/time helpers, no Android and
no third-party dependencies: no third-party dependencies:
- `DayWindow.today()` — local-day boundaries for smart-list logic. - `DayWindow.today()` — local-day boundaries for smart-list logic.

View File

@@ -46,6 +46,16 @@ import de.jeanlucmakiola.floret.identity.predictiveBack
* unchanged: [actions] adds trailing app-bar items; [snackbarHost] hosts * unchanged: [actions] adds trailing app-bar items; [snackbarHost] hosts
* transient messages; [predictiveBack] (off by default) wires the gesture * transient messages; [predictiveBack] (off by default) wires the gesture
* preview to [onBack] for full-screen surfaces that want it. * preview to [onBack] for full-screen surfaces that want it.
*
* Set [scrollable] to false when [content] brings its own scrolling container.
* The default column scrolls as a whole, which composes every row up front —
* fine for the short lists these surfaces normally hold, but a list long enough
* to need a [androidx.compose.foundation.lazy.LazyColumn] can neither nest one
* inside it (same-axis scrolling throws) nor afford the eager pass. Opting out
* hands [content] a plain, unscrolled column to fill instead; the insets, IME
* padding and bar behaviour are unchanged, so a lazy list simply takes over the
* scrolling and gets the top bar's collapse for free through the shared
* nested-scroll connection.
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@@ -55,6 +65,7 @@ fun CollapsingScaffold(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
largeTopBar: Boolean = true, largeTopBar: Boolean = true,
predictiveBack: Boolean = false, predictiveBack: Boolean = false,
scrollable: Boolean = true,
actions: @Composable RowScope.() -> Unit = {}, actions: @Composable RowScope.() -> Unit = {},
snackbarHost: @Composable () -> Unit = {}, snackbarHost: @Composable () -> Unit = {},
content: @Composable ColumnScope.() -> Unit, content: @Composable ColumnScope.() -> Unit,
@@ -112,8 +123,19 @@ fun CollapsingScaffold(
.fillMaxSize() .fillMaxSize()
.background(MaterialTheme.colorScheme.surface) .background(MaterialTheme.colorScheme.surface)
.imePadding() .imePadding()
.then(
if (scrollable) {
Modifier
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.padding(top = 8.dp, bottom = 24.dp), .padding(top = 8.dp, bottom = 24.dp)
} else {
// The content scrolls itself, so it also owns the edge
// spacing — a lazy list wants it as contentPadding, or
// the first and last rows clip instead of scrolling
// under the bars.
Modifier
},
),
content = content, content = content,
) )
} }

View File

@@ -20,12 +20,17 @@ import androidx.compose.ui.window.DialogWindowProvider
* width without a tall header — it's a short selection list, so the large * width without a tall header — it's a short selection list, so the large
* collapsing header would only be empty space to scroll past. [content] places * collapsing header would only be empty space to scroll past. [content] places
* the connected grouped rows; selecting one calls [onDismiss]. * the connected grouped rows; selecting one calls [onDismiss].
*
* [scrollable] forwards to [CollapsingScaffold]: leave it on unless [content]
* scrolls itself, which a picker only needs for an option list long enough to
* warrant a lazy container.
*/ */
@Composable @Composable
fun FullScreenPicker( fun FullScreenPicker(
title: String, title: String,
onDismiss: () -> Unit, onDismiss: () -> Unit,
predictiveBack: Boolean = false, predictiveBack: Boolean = false,
scrollable: Boolean = true,
actions: @Composable RowScope.() -> Unit = {}, actions: @Composable RowScope.() -> Unit = {},
content: @Composable ColumnScope.() -> Unit, content: @Composable ColumnScope.() -> Unit,
) { ) {
@@ -50,6 +55,7 @@ fun FullScreenPicker(
onBack = onDismiss, onBack = onDismiss,
largeTopBar = false, largeTopBar = false,
predictiveBack = predictiveBack, predictiveBack = predictiveBack,
scrollable = scrollable,
actions = actions, actions = actions,
content = content, content = content,
) )

View File

@@ -13,6 +13,7 @@ divergent or app-specific code where it lives.
|---|---|---| |---|---|---|
| `core-time` | JVM | Agendula (and Calendula's pending branch) | | `core-time` | JVM | Agendula (and Calendula's pending branch) |
| `core-reminders` | JVM | Agendula (and Calendula's pending branch) | | `core-reminders` | JVM | Agendula (and Calendula's pending branch) |
| `core-locale` | Android | Agendula, Calendula |
| `core-crash` | Android | Agendula | | `core-crash` | Android | Agendula |
| `identity` | Android | Agendula | | `identity` | Android | Agendula |
| `components` | Android | Agendula | | `components` | Android | Agendula |