Elastic Date Picker
Saatle birlikte kayabilen bir zaman aralığı; bir pano onunla süzülür: "son 15 dakika" bir sonraki yenilemede yine son 15 dakikadır. Elastic UI'ın EuiSuperDatePicker'ı, Pantrix üzerinde yeniden.
import com.pantrixui.components.date.elasticdatepicker.PantrixElasticDatePicker
- Alan. Solda hızlı menünün takvimi, ortada aralığın adı ("Son 15 dakika", "Bugün"), yanında Yenile. Ada basınca iki uç görünür (başlangıç → bitiş) ve başlangıcın paneli açılır. Adı olmayan bir aralık doğrudan iki uçla görünür.
- Hızlı menü. Bir birimin son ya da sonraki miktarı, aralığı kendi uzunluğu kadar kaydıran ‹ ve ›,
commonlyUsed'ın adıyla sunduğu aralıklar (varsayılan Elastic UI'ın sekizi) verecentlyUsed'ın tuttukları. Buradaki seçim hemen verilir. - Bir uç. Üç sekme: Mutlak (takvim, yarım saatlik saatler ve yazılabilen an), Göreli (miktar, birim, düştüğü an, birime yuvarlama), Şimdi. Sekmeye geçmek ucu o sekmenin gösterdiğine çevirir. Mutlak ve Göreli'de anın alanının sonundaki Uygula düzenlemeyi alıp paneli kapatır; Şimdi'nin düğmesi ucu şimdi yapar ve aynısını yapar.
- Bekleyen düzenleme. Alan başarı renginde boyanır, sonunda bir işaret çıkar ve yandaki düğme Güncelle der. Başlangıçtan önceki bir son alanı tehlike renginde boyar ve Güncelle hiçbir şey almaz.
updateButton = Noneile her düzenleme hemen verilir. - Tek basış. Bir panel açıkken öteki uca, Güncelle'ye ya da sayfanın başka bir yerine basmak hem paneli kapatır hem basılanı yapar, Elastic UI'daki gibi. Açık ucun düğmesine basmak panelini kapatır.
- Popover, sheet ya da dialog.
presentationher panelin neyde açılacağını söyler; her platformda aynı. Varsayılan dar bir pencerede sheet, daha genişte popover'dır. Panellerin üstünde başlık yoktur. - Sıkı paneller. Elastic UI'ınkiler gibi: bir ucun paneli takvimi ve yanındaki saatler kadar geniş, hızlı menü 400dp; içlerindeki alanlar, sekmeler ve düğmeler bir formunkinden 8dp alçak.
- Otomatik yenileme.
autoRefreshveonAutoRefreshChange: hızlı menüde "Yenileme aralığı", alanın sonunda ne sıklıkla olduğu;minAutoRefreshen kısası. Her turonRefresh'i bekler, hata verirse yenileme durur. - Zaman penceresi.
timeWindowButtons: ‹ ve › aralığı uzunluğu kadar kaydırır, uzaklaştırma ve istenirse yakınlaştırma onuzoomFactorkadar genişletip daraltır. - Alanın düzeni.
layout: aralık, yalnız hızlı menünün düğmesi ya da yalnız otomatik yenileme. - Hızlı menünün parçaları.
customQuickPanelskendi panelleri,quickMenumenünün kendi sırası. - Saat dilimi ve kapalı yazısı.
utcOffsetanların farkı,timeZoneNamepanellerdeki adı;disabledTextseçim almayan bir seçicinin yazısı. - Zaman. Uçlar
PantrixTimePoint'tir;PantrixTimeRange.resolve()onları şimdiye göre ikiInstantyapar,toDateMath()Elasticsearch'ün tarih matematiğiyle yazar. Ayrıntısı docs/guide/date-time/DATE_TIME_GUIDE.md'de.
Örnekler
Son kullanılanlarla bir pano
Bir panonun son 15 dakikası. Seçilen aralıklar hızlı menünün "Son kullanılanlar"ında birikir; Yenile bir yüklemeyi bir saniye sürdürür ve düğme bu sürede döner. Altında aralığın şimdi düştüğü iki an ve son yenilemenin saati.
var range by remember { mutableStateOf(LAST_QUARTER) }
var refreshed by remember { mutableStateOf<Instant?>(null) }
val report = LocalExampleEvents.current
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixElasticDatePicker(
range = range,
onRangeChange = {
range = it
refreshed = Clock.System.now()
report("Aralık seçildi")
},
recentlyUsed = rememberRecentRanges(),
onRefresh = {
delay(LOADING_MILLIS)
refreshed = Clock.System.now()
report("Yenilendi")
},
tagKey = "dashboard"
)
Resolved(range)
refreshed?.let { PantrixText(text = "Son yenileme: ${moment(it)}", style = PantrixTheme.typography.footnote) }
}
@Composable
private fun Resolved(range: PantrixTimeRange) {
val read = range.resolve()
PantrixText(
text = read?.let { "${moment(it.start)} – ${moment(it.endInclusive)}" } ?: "Son, başlangıçtan önce",
style = PantrixTheme.typography.footnote,
color = PantrixTheme.colors.textSecondary
)
}
@Composable
private fun moment(at: Instant): String {
val strings = PantrixTheme.strings
val day = PantrixDate.of(at)
val time = PantrixTime.of(at)
return "${strings.date(day.day, day.month, day.year)} ${strings.clock(time.hour, time.minute, time.second)}"
}
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
private const val LOADING_MILLIS = 1000L
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Güncelle düğmesi: sözlü, yalnız simge, düğmesiz
Yandaki düğmenin üç hâli. Sözlü düğme bir düzenleme beklerken Güncelle der; yalnız simge aynı işi daha az yerle yapar; düğmesiz seçicide bir uçtaki her düzenleme hemen verilir. Bir ucu değiştirip farkı görün.
var button by remember { mutableStateOf(ElasticDatePickerUpdateButton.Text) }
var range by remember { mutableStateOf(LAST_QUARTER) }
val report = LocalExampleEvents.current
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixSegmentButton(
options = listOf(
SegmentOption(ElasticDatePickerUpdateButton.Text, "Sözlü", tagKey = "text"),
SegmentOption(ElasticDatePickerUpdateButton.Icon, "Yalnız simge", tagKey = "icon"),
SegmentOption(ElasticDatePickerUpdateButton.None, "Düğmesiz", tagKey = "none")
),
selected = button,
onSelect = { button = it },
fullWidth = false,
tagKey = "update_button"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = {
range = it
report("Aralık verildi")
},
updateButton = button,
tagKey = "update"
)
Resolved(range)
}
@Composable
private fun Resolved(range: PantrixTimeRange) {
val read = range.resolve()
PantrixText(
text = read?.let { "${moment(it.start)} – ${moment(it.endInclusive)}" } ?: "Son, başlangıçtan önce",
style = PantrixTheme.typography.footnote,
color = PantrixTheme.colors.textSecondary
)
}
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
@Composable
private fun moment(at: Instant): String {
val strings = PantrixTheme.strings
val day = PantrixDate.of(at)
val time = PantrixTime.of(at)
return "${strings.date(day.day, day.month, day.year)} ${strings.clock(time.hour, time.minute, time.second)}"
}
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Popover, sheet ya da dialog
Panellerin neyde açılacağı her platformda aynıdır: presentation = Popover ile parçanın yanında bir popover, presentation = Sheet ile ekranın kenarından gelen bir sheet, presentation = Dialog ile pencerenin ortasında, panel kadar geniş bir dialog. Varsayılan Adaptive: dar bir pencerede sheet, daha genişte popover; karttaki pencere seçicisinden "Dar" ile "Geniş" arasında geç. Hiçbirinin üstünde başlık yoktur. Hızlı menü, başlangıç ve bitiş üçü de seçilen biçimde açılır.
var presentation by remember { mutableStateOf(DatePickerPresentation.Sheet) }
val today = PantrixQuickRange.commonlyUsed(PantrixTheme.strings).first().range
var range by remember { mutableStateOf(today) }
// Kartın penceresi örnek kadar uzundur: dar bir pencerede açılan sheet'e yer kalsın diye örnek uzun tutulur.
Column(
modifier = Modifier.fillMaxWidth().height(480.dp),
verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)
) {
PantrixSegmentButton(
options = listOf(
SegmentOption(DatePickerPresentation.Popover, "Popover", tagKey = "popover"),
SegmentOption(DatePickerPresentation.Sheet, "Sheet", tagKey = "sheet"),
SegmentOption(DatePickerPresentation.Dialog, "Dialog", tagKey = "dialog"),
SegmentOption(DatePickerPresentation.Adaptive, "Uyarlanır", tagKey = "adaptive")
),
selected = presentation,
onSelect = { presentation = it },
fullWidth = false,
tagKey = "presentation"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
presentation = presentation,
tagKey = "presentation"
)
}
Hızlı menünün kendi aralıkları
Hızlı menünün aralıkları uygulamanındır: burada Elastic UI'ın sekizi yerine son 15 dakikadan son bir yıla yedi aralık. "Son kullanılanlar"ı açıp kapatmak listeyi gösterir ya da gizler; adı olan bir aralık alanda adıyla durur.
val ranges = remember {
listOf(
PantrixQuickRange("Son 15 dakika", last(15, PantrixTimeUnit.Minutes)),
PantrixQuickRange("Son 1 saat", last(1, PantrixTimeUnit.Hours)),
PantrixQuickRange("Son 24 saat", last(24, PantrixTimeUnit.Hours)),
PantrixQuickRange("Son 7 gün", last(7, PantrixTimeUnit.Days)),
PantrixQuickRange("Son 30 gün", last(30, PantrixTimeUnit.Days)),
PantrixQuickRange("Son 90 gün", last(90, PantrixTimeUnit.Days)),
PantrixQuickRange("Son 1 yıl", last(1, PantrixTimeUnit.Years))
)
}
var range by remember { mutableStateOf(ranges[4].range) }
var showRecent by remember { mutableStateOf(true) }
val recent = rememberRecentRanges(max = 5)
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixSwitchButton(
checked = showRecent,
onCheckedChange = { showRecent = it },
label = "Son kullanılanlar",
tagKey = "show_recent"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
commonlyUsed = ranges,
recentlyUsed = recent.takeIf { showRecent },
tagKey = "own_ranges"
)
}
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Genişlik ve boy
Seçici verilen genişliği style'ın maxWidth'ine kadar doldurur (varsayılan 560dp, Elastic UI'ın "restricted"ı). maxWidth = Dp.Infinity tam genişlik verir; dar bir yerde yandaki sözlü düğme yalnız simgesine iner; height ile alan sıkışık olur.
var range by remember { mutableStateOf(SINCE_YESTERDAY) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.md)) {
PantrixText(text = "Varsayılan (560dp'ye kadar)", style = PantrixTheme.typography.footnote)
PantrixElasticDatePicker(range = range, onRangeChange = { range = it }, tagKey = "restricted")
PantrixText(text = "Tam genişlik", style = PantrixTheme.typography.footnote)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
style = ElasticDatePickerStyle(maxWidth = Dp.Infinity),
tagKey = "full"
)
PantrixText(text = "Dar bir yerde (320dp)", style = PantrixTheme.typography.footnote)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
modifier = Modifier.width(NARROW_WIDTH),
tagKey = "narrow"
)
PantrixText(text = "Sıkışık (32dp)", style = PantrixTheme.typography.footnote)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
style = ElasticDatePickerStyle(height = COMPRESSED_HEIGHT),
tagKey = "compressed"
)
}
private val SINCE_YESTERDAY = PantrixTimeRange(
PantrixTimePoint.Relative(-1, PantrixTimeUnit.Days, roundTo = PantrixTimeUnit.Days),
PantrixTimePoint.Now
)
private val NARROW_WIDTH = 320.dp
private val COMPRESSED_HEIGHT = 32.dp
Yükleniyor ve kapalı
Bir yükleme ve seçim almayan bir seçici. Yüklenirken yandaki düğme döner ve basılmaz; kapalı bir seçici soluk çizilir ve hiçbir panel açmaz.
var range by remember { mutableStateOf(LAST_HOUR) }
var loading by remember { mutableStateOf(true) }
var enabled by remember { mutableStateOf(true) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixSwitchButton(
checked = loading,
onCheckedChange = { loading = it },
label = "Yükleniyor",
tagKey = "loading"
)
PantrixSwitchButton(
checked = enabled,
onCheckedChange = { enabled = it },
label = "Etkin",
tagKey = "enabled"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
loading = loading,
enabled = enabled,
tagKey = "states"
)
}
private val LAST_HOUR = last(1, PantrixTimeUnit.Hours)
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Seçilebilen günler
Takvim yalnızca bu ayın günlerini sunar (minDate ve maxDate): bir ucun Mutlak sekmesinde ayın dışındaki günler soluk ve seçilemez. Göreli bir uç sınırlardan etkilenmez.
val today = rememberToday()
val first = PantrixDate(today.year, today.month, 1)
val last = first.plusMonths(1).plusDays(-1)
var range by remember {
mutableStateOf(PantrixTimeRange(PantrixTimePoint.Absolute(first.at(PantrixTime(0, 0))), PantrixTimePoint.Now))
}
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
minDate = first,
maxDate = last,
tagKey = "bounds"
)
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Saat düzeni, haftanın başı ve birimler
Anların yazılışı ve okunuşu: 12 ya da 24 saat (is24Hour), haftanın ilk günü (firstDayOfWeek, /w yuvarlamasını da belirler) ve göreli bir ucun en iyi okunan birime konup konmaması (roundRelativeUnits: 90 dakika "~ 2 saat önce" ya da "90 dakika önce"). Dil, sayfanın dil düğmesinden.
var is24Hour by remember { mutableStateOf(true) }
var mondayFirst by remember { mutableStateOf(true) }
var roundUnits by remember { mutableStateOf(true) }
var range by remember { mutableStateOf(NINETY_TO_THIRTY_AGO) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixSwitchButton(checked = is24Hour, onCheckedChange = { is24Hour = it }, label = "24 saat", tagKey = "clock")
PantrixSwitchButton(
checked = mondayFirst,
onCheckedChange = { mondayFirst = it },
label = "Hafta pazartesi başlar",
tagKey = "monday"
)
PantrixSwitchButton(
checked = roundUnits,
onCheckedChange = { roundUnits = it },
label = "Birimleri yuvarla",
tagKey = "round"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
roundRelativeUnits = roundUnits,
firstDayOfWeek = if (mondayFirst) 1 else SUNDAY,
is24Hour = is24Hour,
tagKey = "clock"
)
}
private val NINETY_TO_THIRTY_AGO = PantrixTimeRange(
PantrixTimePoint.Relative(-90, PantrixTimeUnit.Minutes),
PantrixTimePoint.Relative(-30, PantrixTimeUnit.Minutes)
)
private const val SUNDAY = 7
Adresteki tarih matematiği
Aralık bir adreste tarih matematiği olarak durur: from ve to her seçimde yeniden yazılır. Alanlara bir uç yazılıp Uygula'ya basılınca aralık oradan okunur; okunamayan bir uç alanı hatalı çizer.
var range by remember { mutableStateOf(SINCE_YESTERDAY) }
val written = range.toDateMath()
var from by remember(written) { mutableStateOf(written.first) }
var to by remember(written) { mutableStateOf(written.second) }
val start = PantrixTimePoint.parseDateMath(from)
val end = PantrixTimePoint.parseDateMath(to)
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixElasticDatePicker(range = range, onRangeChange = { range = it }, tagKey = "url")
PantrixText(text = "?from=${written.first}&to=${written.second}", style = PantrixTheme.typography.footnote)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm),
verticalAlignment = Alignment.Bottom
) {
PantrixTextField(
value = from,
onValueChange = { from = it },
modifier = Modifier.weight(1f),
label = "from",
error = start == null,
showCharacterCount = false,
tagKey = "from"
)
PantrixTextField(
value = to,
onValueChange = { to = it },
modifier = Modifier.weight(1f),
label = "to",
error = end == null,
showCharacterCount = false,
tagKey = "to"
)
}
PantrixButton(
text = "Uygula",
onClick = { if (start != null && end != null) range = PantrixTimeRange(start, end) },
variant = ButtonVariant.Outline,
enabled = start != null && end != null,
tagKey = "read"
)
}
private val SINCE_YESTERDAY = PantrixTimeRange(
PantrixTimePoint.Relative(-1, PantrixTimeUnit.Days, roundTo = PantrixTimeUnit.Days),
PantrixTimePoint.Now
)
Kendi renkleri
Alanın kendi renkleri: zemin, kenar, sözler ve ikonlar, açık ucun kenarı, bekleyen düzenlemenin ve sırası bozuk uçların renkleri. Verilmeyen her renk temanınkidir. Bir ucu değiştirip bekleyen renge bakın.
var range by remember { mutableStateOf(LAST_QUARTER) }
val colors = PantrixTheme.colors
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
colors = ElasticDatePickerColors(
container = colors.neutral.container,
border = colors.neutral.color,
active = colors.warning.color,
pendingContainer = colors.info.container,
pendingContent = colors.info.onContainer
),
tagKey = "colors"
)
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Otomatik yenileme
Pano kendini her on saniyede yeniler: alanın sonunda ne sıklıkla olduğu kısaca yazar, ona basmak hızlı menüyü açar. Menünün "Yenileme aralığı" bölümü onu açar, kapatır ve sıklığını değiştirir; beş saniyeden kısası alınmaz (minAutoRefresh). Her turda onRefresh çalışır ve bir sonraki tur onun bitmesini bekler.
var range by remember { mutableStateOf(LAST_QUARTER) }
var refresh by remember { mutableStateOf(PantrixAutoRefresh(every = 10, paused = false)) }
var count by remember { mutableStateOf(0) }
val report = LocalExampleEvents.current
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
onRefresh = {
count++
report("Yenilendi")
},
tagKey = "auto_refresh",
autoRefresh = refresh,
onAutoRefreshChange = {
refresh = it
report(if (it.paused) "Otomatik yenileme durdu" else "Otomatik yenileme değişti")
},
minAutoRefresh = 5.seconds
)
PantrixText(text = "Yenileme sayısı: $count", style = PantrixTheme.typography.footnote)
}
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Yalnız otomatik yenileme
Zaman verisi olmayan bir sayfa için yalnız otomatik yenileme (layout = AutoRefreshOnly): alan "Otomatik yenileme" ve ne sıklıkla ya da kapalı olduğunu söyler, basınca yalnız onu ayarlayan menü açılır. Sıklık burada dakikayla verildi (unit = AutoRefreshUnit.Minutes): dakikada bir.
var refresh by remember { mutableStateOf(PantrixAutoRefresh(every = 1, unit = AutoRefreshUnit.Minutes)) }
var count by remember { mutableStateOf(0) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixElasticDatePicker(
range = LAST_QUARTER,
onRangeChange = { count++ },
tagKey = "auto_refresh_only",
autoRefresh = refresh,
onAutoRefreshChange = { refresh = it },
layout = ElasticDatePickerLayout.AutoRefreshOnly
)
PantrixText(text = "Yenileme sayısı: $count", style = PantrixTheme.typography.footnote)
}
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Yalnız hızlı seçim
Aralığın başka bir yerde gösterildiği bir sayfa için yalnız hızlı menünün düğmesi ve yanındaki düğme (layout = QuickSelectOnly). Seçilen aralık altta yazar.
var range by remember { mutableStateOf(LAST_QUARTER) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
tagKey = "quick_select_only",
layout = ElasticDatePickerLayout.QuickSelectOnly
)
Resolved(range)
}
@Composable
private fun Resolved(range: PantrixTimeRange) {
val read = range.resolve()
PantrixText(
text = read?.let { "${moment(it.start)} – ${moment(it.endInclusive)}" } ?: "Son, başlangıçtan önce",
style = PantrixTheme.typography.footnote,
color = PantrixTheme.colors.textSecondary
)
}
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
@Composable
private fun moment(at: Instant): String {
val strings = PantrixTheme.strings
val day = PantrixDate.of(at)
val time = PantrixTime.of(at)
return "${strings.date(day.day, day.month, day.year)} ${strings.clock(time.hour, time.minute, time.second)}"
}
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Zaman penceresi düğmeleri
Alanın yanında Elastic UI'ın zaman penceresi düğmeleri: ‹ ve › aralığı kendi uzunluğu kadar kaydırır, uzaklaştırma onu uzunluğunun zoomFactor kadarıyla genişletir, yakınlaştırma aynı kadar daraltır; yakınlaştırma istenmedikçe yoktur. Verdikleri aralık anlardan oluşur.
var range by remember { mutableStateOf(LAST_HOUR) }
var zoomIn by remember { mutableStateOf(false) }
var factor by remember { mutableStateOf(HALF) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixSwitchButton(checked = zoomIn, onCheckedChange = { zoomIn = it }, label = "Yakınlaştır", tagKey = "zoom_in")
PantrixSegmentButton(
options = listOf(
SegmentOption(HALF, "Yarısı (0.5)", tagKey = "half"),
SegmentOption(QUARTER, "Çeyreği (0.25)", tagKey = "quarter")
),
selected = factor,
onSelect = { factor = it },
fullWidth = false,
tagKey = "zoom_factor"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
tagKey = "time_window",
timeWindowButtons = ElasticTimeWindowButtons(zoomIn = zoomIn, zoomFactor = factor)
)
Resolved(range)
}
@Composable
private fun Resolved(range: PantrixTimeRange) {
val read = range.resolve()
PantrixText(
text = read?.let { "${moment(it.start)} – ${moment(it.endInclusive)}" } ?: "Son, başlangıçtan önce",
style = PantrixTheme.typography.footnote,
color = PantrixTheme.colors.textSecondary
)
}
private val LAST_HOUR = last(1, PantrixTimeUnit.Hours)
private const val HALF = 0.5
private const val QUARTER = 0.25
@Composable
private fun moment(at: Instant): String {
val strings = PantrixTheme.strings
val day = PantrixDate.of(at)
val time = PantrixTime.of(at)
return "${strings.date(day.day, day.month, day.year)} ${strings.clock(time.hour, time.minute, time.second)}"
}
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
Hızlı menünün kendi panelleri ve sırası
Hızlı menüde uygulamanın kendi paneli (customQuickPanels), varsayılan olarak son kullanılanlardan sonra. "Kendi sıram" menüyü quickMenu ile kurar: önce kayıtlı aralıklar, sonra hızlı seçim; adıyla sunulan aralıklar yok. Menünün parçaları ElasticQuickMenuScope'tadır: quickMenu o kapsamda çağrılır.
var range by remember { mutableStateOf(LAST_QUARTER) }
var own by remember { mutableStateOf(false) }
val saved = remember {
listOf(
"Gece vardiyası" to PantrixTimeRange(
PantrixTimePoint.Relative(-1, PantrixTimeUnit.Days, roundTo = PantrixTimeUnit.Days),
PantrixTimePoint.Relative(-16, PantrixTimeUnit.Hours)
),
"Son dağıtımdan beri" to last(3, PantrixTimeUnit.Hours)
)
}
val panel = ElasticQuickPanel("Kayıtlı aralıklar") {
Column {
saved.forEachIndexed { index, (name, kept) ->
PantrixLink(text = name, onClick = { range = kept }, tagKey = "saved_$index")
}
}
}
val ownMenu: @Composable ElasticQuickMenuScope.() -> Unit = {
CustomPanels()
QuickSelect()
}
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixSegmentButton(
options = listOf(
SegmentOption(false, "Elastic UI'ın sırası", tagKey = "elastic"),
SegmentOption(true, "Kendi sıram", tagKey = "own")
),
selected = own,
onSelect = { own = it },
fullWidth = false,
tagKey = "order"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
tagKey = "quick_panels",
customQuickPanels = listOf(panel),
quickMenu = if (own) ownMenu else null
)
Resolved(range)
}
@Composable
private fun Resolved(range: PantrixTimeRange) {
val read = range.resolve()
PantrixText(
text = read?.let { "${moment(it.start)} – ${moment(it.endInclusive)}" } ?: "Son, başlangıçtan önce",
style = PantrixTheme.typography.footnote,
color = PantrixTheme.colors.textSecondary
)
}
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
@Composable
private fun moment(at: Instant): String {
val strings = PantrixTheme.strings
val day = PantrixDate.of(at)
val time = PantrixTime.of(at)
return "${strings.date(day.day, day.month, day.year)} ${strings.clock(time.hour, time.minute, time.second)}"
}
Saat dilimi
Anlar seçilen saat diliminin farkıyla okunur ve yazılır (utcOffset); uçların panelleri dilimi adıyla ve UTC'den farkıyla söyler (timeZoneName). Ad yalnızca söyler, bir şey değiştirmez.
var range by remember { mutableStateOf(SINCE_YESTERDAY) }
var zone by remember { mutableStateOf(ZONES.first()) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixSegmentButton(
options = ZONES.mapIndexed { index, it -> SegmentOption(it, it.first, tagKey = "zone_$index") },
selected = zone,
onSelect = { zone = it },
fullWidth = false,
tagKey = "zone"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
tagKey = "time_zone",
timeZoneName = zone.first,
utcOffset = { zone.second }
)
}
private val SINCE_YESTERDAY = PantrixTimeRange(
PantrixTimePoint.Relative(-1, PantrixTimeUnit.Days, roundTo = PantrixTimeUnit.Days),
PantrixTimePoint.Now
)
private val ZONES = listOf("Europe/Istanbul" to 3.hours, "Asia/Tokyo" to 9.hours, "UTC" to Duration.ZERO)
Kapalı ve kendi yazısı
Seçim almayan bir seçici aralığı yerine kendi yazısını gösterebilir (disabledText), Elastic UI'ın isDisabled.display'i gibi: burada "Tüm zamanlar".
var words by remember { mutableStateOf(true) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixSwitchButton(checked = words, onCheckedChange = { words = it }, label = "Kendi yazısı", tagKey = "words")
PantrixElasticDatePicker(
range = LAST_QUARTER,
onRangeChange = {},
enabled = false,
tagKey = "disabled_text",
disabledText = if (words) "Tüm zamanlar" else null
)
}
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
KQL deseni
Elastic UI'ın KQL deseni: bir arama alanının yanında seçici. Arama alanı odaktayken seçici hızlı menünün düğmesine küçülür (layout = QuickSelectOnly) ve yer sorguya kalır; odak gidince aralık geri gelir.
var range by remember { mutableStateOf(LAST_QUARTER) }
var query by remember { mutableStateOf("") }
var searching by remember { mutableStateOf(false) }
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm),
verticalAlignment = Alignment.CenterVertically
) {
PantrixTextField(
value = query,
onValueChange = { query = it },
modifier = Modifier.weight(1f).onFocusChanged { searching = it.hasFocus },
placeholder = "KQL ile ara",
showCharacterCount = false,
contentDescription = "Arama sorgusu",
tagKey = "query"
)
PantrixElasticDatePicker(
range = range,
onRangeChange = { range = it },
modifier = if (searching) Modifier else Modifier.weight(PICKER_SHARE),
updateButton = ElasticDatePickerUpdateButton.Icon,
tagKey = "query_range",
layout = if (searching) ElasticDatePickerLayout.QuickSelectOnly else ElasticDatePickerLayout.Full
)
}
private val LAST_QUARTER = last(15, PantrixTimeUnit.Minutes)
private const val PICKER_SHARE = 1.4f
private fun last(
amount: Int,
unit: PantrixTimeUnit
): PantrixTimeRange = PantrixTimeRange(PantrixTimePoint.Relative(-amount, unit), PantrixTimePoint.Now)
API
range
Saatle birlikte kayabilen bir zaman aralığı; bir pano onunla süzülür: "son 15 dakika" bir sonraki yenilemede yine son 15 dakikadır. Elastic UI'ın EuiSuperDatePicker'ı, Pantrix üzerinde yeniden.
| Parametre | Tür | Varsayılan | Ne olduğu |
|---|---|---|---|
range | PantrixTimeRange | gösterilen aralık. Uçları şimdiye göre olabilir. | |
onRangeChange | (PantrixTimeRange) -> Unit | okurun hızlı menüden seçtiği ya da bir düzenlemeden sonra güncellediği aralığı, onRefresh yokken bir yenilemede aynı aralığı alır. | |
modifier | Modifier | Modifier | seçicinin modifier'ı. Seçici verilen genişliği style'ın maxWidth'ine kadar doldurur. |
commonlyUsed | List<PantrixQuickRange> | PantrixQuickRange.commonlyUsed(PantrixTheme.strings) | hızlı menünün adıyla sunduğu aralıklar: varsayılan Elastic UI'ın sekizi, temanın dilinde. Gösterilen aralık bunlardan biriyse adıyla anılır. |
recentlyUsed | PantrixRecentRanges? | null | okurun son seçtiği aralıklar; hızlı menü onları listeler ve okurun uyguladığı her aralık onlara kaydedilir; hiçbiri için null. rememberRecentRanges() onları bir yapılandırma değişikliğinde korur. |
updateButton | ElasticDatePickerUpdateButton | ElasticDatePickerUpdateButton.Text | alanın yanındaki düğme: sözü ve simgesi, yalnız simgesi ya da hiç; o zaman her düzenleme hemen verilir. |
presentation | DatePickerPresentation | DatePickerPresentation.Adaptive | panellerin neyde açıldığı: varsayılan dar bir pencerede bir sheet, daha geniş pencerede basılan parçanın yanında bir popover, bir panel açılırken seçilir; ya da her zaman bir popover, bir sheet ya da bir dialog. Her platformda aynı. |
loading | Boolean | false | aralığın süzdüğünün yüklenip yüklenmediği: alanın yanındaki düğme döner ve basılmaz. |
enabled | Boolean | true | seçicinin bir seçim alıp almadığı. Almayan soluk çizilir ve hiçbir şey açmaz. |
minDate | PantrixDate? | null | bir ucun takviminin sunduğu ilk gün; o kadar erken bir sınır yoksa null. |
maxDate | PantrixDate? | null | sunduğu son gün; o kadar geç bir sınır yoksa null. |
onRefresh | (suspend () -> Unit)? | null | bir düzenleme beklemezken Yenile'nin yaptığı; bu sürerken düğme döner; aynı aralığı onRangeChange'e vermek için null. |
roundRelativeUnits | Boolean | true | şimdiden bir süre olan bir ucun en iyi okunan birime konup konmadığı, 90 dakika için "~ 2 saat önce", ya da kendi birimini koruyup korumadığı. |
firstDayOfWeek | Int? | null | takvimin haftalarının başladığı ve bir haftanın yuvarlandığı gün; günleri ISO 8601 sayar: 1 pazartesidir. Null dilinkidir, PantrixLocale.firstDayOfWeek. |
is24Hour | Boolean | true | bir anın 24 saatlik bir saatle mi, 22:00, yoksa 12 saatlikle mi, 10:00 PM, yazılıp seçildiği. |
style | ElasticDatePickerStyle? | null | alanın bu çağrıya ait stili: kapsayan her stilin üstünde, yoğunluğun altında. |
colors | ElasticDatePickerColors? | null | alanın kendi renkleri: verdikleri, kalanı için temanınkiler. |
tagKey | String? | null | seçicinin otomasyon anahtarı: ElasticDatePicker_<tagKey> olur, parçaları .Button_quick_menu, .Button_name, .Button_start, .Button_end, .Button_auto_refresh, zaman penceresi düğmeleri .Button_window_previous, .Button_window_zoom_in, .Button_window_zoom_out ve .Button_window_next, alanın yanındaki düğme Button_<tagKey>_update. |
autoRefresh | PantrixAutoRefresh? | null | aralığın kendiliğinden ne sıklıkla yeniden okunduğu; hiç için null. Duraklatılmamışken alan ne sıklıkla olduğunu kısaca yazarak biter ve her turda Yenile yapılır: bir sonraki tur sayılmadan önce bitmesi beklenen onRefresh, o yoksa aynı aralıkla onRangeChange. Başarısız olan bir onRefresh onu duraklatır ve bunu onAutoRefreshChange ile söyler. |
onAutoRefreshChange | ((PantrixAutoRefresh) -> Unit)? | null | okur hızlı menüde ayarladıkça otomatik yenilemeyi alır; menüde bunun için kendi bölümü olur; böyle bir bölüm olmaması için null. |
minAutoRefresh | Duration | Duration.ZERO | okurun ayarlayabileceği en kısa otomatik yenileme: daha kısası miktarını yanlış çizer. |
layout | ElasticDatePickerLayout | ElasticDatePickerLayout.Full | alanın ne gösterdiği: aralığı, yalnız hızlı menünün düğmesini ya da yalnız otomatik yenilemeyi. |
timeWindowButtons | ElasticTimeWindowButtons? | null | Elastic UI'ın alanın yanındaki, aralığı uzunluğu kadar kaydıran ve yakınlaştırıp uzaklaştıran düğmeleri; hiçbiri için null. |
customQuickPanels | List<ElasticQuickPanel> | emptyList() | hızlı menüde çağıranın kendi panelleri, son kullanılan aralıklardan sonra. |
quickMenu | (@Composable ElasticQuickMenuScope.() -> Unit)? | null | hızlı menünün parçaları çağıranın kendi sırasında, bazıları dışarıda bırakılmış ya da aralarına kendi panelleri konmuş; Elastic UI'ın sırası için null. |
timeZoneName | String? | null | anların bulunduğu saat dilimi; uçların panellerinde UTC'den farkıyla adlandırılır: "Saat dilimi: Europe/Istanbul (UTC+03:00)". Yalnızca adlandırır, bir şey değiştirmez; böyle bir satır olmaması için null. |
utcOffset | ((Instant) -> Duration)? | null | anların bir anda okunup yazıldığı UTC farkı; ekranın saatininki (LocalPantrixClock) için null, bir test ya da önizleme başkasını vermedikçe cihazınki. |
disabledText | String? | null | seçim almayan bir seçicinin aralığının yerinde gösterdiği yazı; aralık için null. |
ElasticDatePickerStyle
PantrixElasticDatePicker'ın alanı: ne kadar yüksek olduğu, köşeleri, içindeki boşluk, yanındaki düğmeyle arası ve ne kadar genişlediği.
| Parametre | Tür | Varsayılan | Ne olduğu |
|---|---|---|---|
height | Dp | Dp.Unspecified | Alanın yüksekliği. |
shape | ShapeSpec | ShapeSpec.Unspecified | Alanın köşeleri. |
padding | Dp | Dp.Unspecified | Alanın kenarı ile içindekiler arasındaki boşluk, iki uçta da. |
gap | Dp | Dp.Unspecified | Alan ile yanındaki düğme arasındaki ve alanın içindeki parçalar arasındaki ara. |
maxWidth | Dp | Dp.Unspecified | Alanın ve düğmesinin en geniş hâli; verildiği kadar geniş olması için Dp.Infinity. |
ElasticDatePickerColors
Bir PantrixElasticDatePicker'ın alanının temanın renkleri yerine boyandığı renkler: verilen renk kullanılır, verilmeyen temanın kalır. Alanın açtıkları bir popover'ın, bir sheet'in, bir takvimin ve sekmelerin renkleriyle boyanır.
| Parametre | Tür | Varsayılan | Ne olduğu |
|---|---|---|---|
container | Color | Color.Unspecified | Alanın zemini. Bir metin alanınınki gibi temanın surface'ı. |
border | Color | Color.Unspecified | Alanın kenarı ve hızlı menünün düğmesi ile aralık arasındaki çizgi. Temanın border'ı. |
content | Color | Color.Unspecified | Aralığın ve uçlarının sözleri. Temanın textPrimary'si. |
icon | Color | Color.Unspecified | Alanın simgeleri: hızlı menünün takvimi ve uçlar arasındaki ok. Temanın textSecondary'si. |
active | Color | Color.Unspecified | Paneli açık olan ucun çevresine çizilen kenar. Birincil rolün color'ı. |
pendingContainer | Color | Color.Unspecified | Bir düzenleme Güncelle'yi beklerken alanın zemini. Başarı rolünün container'ı. |
pendingContent | Color | Color.Unspecified | Üstündeki sözler, ok ve işaret. Başarı rolünün onContainer'ı. |
invalidContainer | Color | Color.Unspecified | Sonu başlangıcından önce geldiğinde alanın zemini. Tehlike rolünün container'ı. |
invalidContent | Color | Color.Unspecified | Üstündeki sözler, ok ve işaret. Tehlike rolünün onContainer'ı. |
disabled | Color | Color.Unspecified | Seçim almayan bir alanın sözleri ve simgeleri. Temanın textDisabled'ı. |
Erişilebilirlik
- Ekran okuyucu. Her uç adı ve sözüyle bir düğmedir ("Başlangıç tarihi, ~ 15 dakika önce"); bekleyen bir düzenleme kibarca duyurulur.