Merge pull request 'sprint-1' (#1) from sprint-1 into master

Reviewed-on: #1
This commit is contained in:
user5 2025-05-26 14:30:12 +00:00
commit 053cbfec6c
77 changed files with 3010 additions and 133 deletions

View File

@ -56,4 +56,6 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
implementation(project(":core"))
}

View File

@ -1,47 +1,413 @@
package com.example.uikit
import android.annotation.SuppressLint
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.uikit.ui.theme.UikitTheme
import androidx.compose.ui.unit.dp
import com.example.core.component.button.AppButton
import com.example.core.component.button.BubbleButton
import com.example.core.component.button.BubbleButtonState
import com.example.core.component.button.ButtonState
import com.example.core.component.button.CartButton
import com.example.core.component.button.LoginButton
import com.example.core.component.button.OutlinedAppButton
import com.example.core.component.button.SecondaryAppButton
import com.example.core.component.card.CartCard
import com.example.core.component.card.PrimaryCard
import com.example.core.component.card.ProjectCard
import com.example.core.component.header.BigHeader
import com.example.core.component.header.SmallHeader
import com.example.core.component.input.EnterInputField
import com.example.core.component.search.AppSearchField
import com.example.core.component.select.AppSelector
import com.example.core.component.select.Option
import com.example.core.component.tabbar.BottomTabBar
import com.example.core.component.tabbar.Catalog
import com.example.core.component.tabbar.Home
import com.example.core.component.tabbar.Profile
import com.example.core.component.tabbar.Projects
import com.example.core.theme.CustomIcons
import com.example.core.theme.CustomTheme
class MainActivity : ComponentActivity() {
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
UikitTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
CustomTheme {
Scaffold { tabPadding ->
var currentDestination by rememberSaveable { mutableStateOf("com.example.core.component.tabbar.Home") }
Scaffold(
bottomBar = {
BottomTabBar(
tabs = listOf(Home, Catalog, Projects, Profile),
hierarchy = sequenceOf(currentDestination),
onTabClick = {
currentDestination = it::class.qualifiedName.toString()
},
bottomPadding = tabPadding.calculateBottomPadding()
)
},
containerColor = CustomTheme.colors.white
) {
Column(
modifier = Modifier
.safeDrawingPadding()
.fillMaxSize()
.padding(horizontal = 16.dp)
.background(CustomTheme.colors.white)
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(
15.dp,
alignment = Alignment.CenterVertically
),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Инпуты", style = CustomTheme.typography.title1ExtraBold)
var fieldValue1 by rememberSaveable { mutableStateOf("") }
var errorMessage1 by rememberSaveable { mutableStateOf("") }
EnterInputField(
value = fieldValue1,
onValueChange = {
fieldValue1 = it
errorMessage1 = ""
},
errorMessage = errorMessage1,
label = "",
hint = "Введите имя"
)
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
var fieldValue2 by rememberSaveable { mutableStateOf("Иван") }
var errorMessage2 by rememberSaveable { mutableStateOf("") }
EnterInputField(
value = fieldValue2,
onValueChange = {
fieldValue2 = it
errorMessage2 = ""
},
errorMessage = errorMessage2,
label = "",
hint = "Введите имя"
)
var fieldValue3 by rememberSaveable { mutableStateOf("") }
var errorMessage3 by rememberSaveable { mutableStateOf("") }
EnterInputField(
value = fieldValue3,
onValueChange = {
fieldValue3 = it
errorMessage3 = ""
},
errorMessage = errorMessage3,
label = "Имя",
hint = "Введите имя"
)
var fieldValue4 by rememberSaveable { mutableStateOf("") }
var errorMessage4 by rememberSaveable { mutableStateOf("Введите ваше имя") }
EnterInputField(
value = fieldValue4,
onValueChange = {
fieldValue4 = it
errorMessage4 = ""
},
errorMessage = errorMessage4,
label = "Имя",
hint = "Введите имя"
)
var fieldValue5 by rememberSaveable { mutableStateOf("") }
var errorMessage5 by rememberSaveable { mutableStateOf("") }
EnterInputField(
value = fieldValue5,
onValueChange = {
fieldValue5 = it
errorMessage5 = ""
},
errorMessage = errorMessage5,
label = "Имя",
hint = "Введите имя"
)
var fieldValue6 by rememberSaveable { mutableStateOf("Введите имя") }
var errorMessage6 by rememberSaveable { mutableStateOf("") }
EnterInputField(
value = fieldValue6,
onValueChange = {
fieldValue6 = it
errorMessage6 = ""
},
errorMessage = errorMessage6,
label = "Имя",
hint = "Введите имя"
)
var fieldValue7 by rememberSaveable { mutableStateOf("123456789") }
var errorMessage7 by rememberSaveable { mutableStateOf("") }
EnterInputField(
value = fieldValue7,
onValueChange = {
fieldValue7 = it
errorMessage7 = ""
},
errorMessage = errorMessage7,
label = "",
isPassword = true,
hint = "Введите имя"
)
var fieldValue8 by rememberSaveable { mutableStateOf("") }
var errorMessage8 by rememberSaveable { mutableStateOf("") }
EnterInputField(
value = fieldValue8,
onValueChange = {
fieldValue8 = it
errorMessage8 = ""
},
errorMessage = errorMessage8,
label = "",
hint = "--.--.----"
)
/*
* F6.user5@local.ru
* Pa$$w0rd
* */
Text(text = "Селекты", style = CustomTheme.typography.title1ExtraBold)
var selectedOption1 by remember { mutableStateOf<Option?>(null) }
AppSelector(
selectedOption = selectedOption1,
options = listOf(
Option(label = "Мужской"),
Option(label = "Женский")
),
onOptionSelect = { selectedOption1 = it },
hint = "Пол"
)
var selectedOption2 by remember { mutableStateOf<Option?>(Option("Мужской")) }
AppSelector(
selectedOption = selectedOption2,
options = listOf(
Option(label = "Мужской"),
Option(label = "Женский")
),
onOptionSelect = { selectedOption2 = it },
hint = "Пол"
)
Text(text = "Поиск", style = CustomTheme.typography.title1ExtraBold)
var searchFieldValue by rememberSaveable { mutableStateOf("") }
AppSearchField(
value = searchFieldValue,
onValueChange = { searchFieldValue = it },
hint = "Искать описание"
)
Text(text = "Кнопки", style = CustomTheme.typography.title1ExtraBold)
AppButton(
label = "Подтвердить",
onClick = {},
state = ButtonState.Big
)
AppButton(
label = "Подтвердить",
onClick = {},
state = ButtonState.Big,
enabled = false
)
OutlinedAppButton(
label = "Подтвердить",
onClick = {},
state = ButtonState.Big
)
SecondaryAppButton(
label = "Подтвердить",
onClick = {},
state = ButtonState.Big
)
AppButton(
label = "Добавить",
onClick = {},
state = ButtonState.Small
)
OutlinedAppButton(
label = "Убрать",
onClick = {},
state = ButtonState.Small
)
AppButton(
label = "Добавить",
onClick = {},
state = ButtonState.Small,
enabled = false
)
SecondaryAppButton(
label = "Подтвердить",
onClick = {},
state = ButtonState.Small
)
AppButton(
label = "Популярное",
onClick = {},
state = ButtonState.Chips
)
AppButton(
label = "Популярное",
onClick = {},
state = ButtonState.Chips,
enabled = false
)
CartButton(
onClick = {},
totalPrice = 500
)
LoginButton(
icon = CustomIcons.vk,
label = "Войти с VK",
onClick = {}
)
LoginButton(
icon = CustomIcons.yandex,
label = "Войти с Yandex",
onClick = {}
)
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
BubbleButton(
state = BubbleButtonState.Small,
icon = CustomIcons.back
)
BubbleButton(
state = BubbleButtonState.Big,
icon = CustomIcons.filter
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
UikitTheme {
Greeting("Android")
var inCartFirst by rememberSaveable { mutableStateOf(false) }
Text(text = "Карточки", style = CustomTheme.typography.title1ExtraBold)
PrimaryCard(
title = "Рубашка Воскресенье для машинного \n" +
"вязания",
category = "Мужская одежда",
price = 300,
inCart = inCartFirst,
onAddToCartClick = { inCartFirst = true },
onRemoveFromCartClick = { inCartFirst = false },
)
var inCartSecond by rememberSaveable { mutableStateOf(true) }
PrimaryCard(
title = "Рубашка Воскресенье для машинного \n" +
"вязания",
category = "Мужская одежда",
price = 300,
inCart = inCartSecond,
onAddToCartClick = { inCartSecond = true },
onRemoveFromCartClick = { inCartSecond = false },
)
var currentQuantity by rememberSaveable { mutableIntStateOf(1) }
CartCard(
title = "Рубашка воскресенье для машинного вязания",
price = 300,
currentQuantity = currentQuantity,
onChangeQuantity = { currentQuantity = it }
)
ProjectCard(
title = "Мой первый проект",
dayElapsed = 2,
onOpenClick = {}
)
Text(text = "Хэдэр", style = CustomTheme.typography.title1ExtraBold)
BigHeader(
title = "Корзина",
startContent = {
BubbleButton(
state = BubbleButtonState.Small,
icon = CustomIcons.back
)
},
endContent = {
Icon(
painter = CustomIcons.delete,
contentDescription = null,
tint = CustomTheme.colors.inputIcon
)
}
)
SmallHeader(
title = "Корзина",
startContent = {
BubbleButton(
state = BubbleButtonState.Small,
icon = CustomIcons.back
)
},
endContent = {
Icon(
painter = CustomIcons.delete,
contentDescription = null,
tint = CustomTheme.colors.inputIcon
)
}
)
Spacer(Modifier.height(100.dp))
}
}
}
}
}
}
}

View File

@ -1,11 +0,0 @@
package com.example.uikit.ui.theme
import androidx.compose.ui.graphics.Color
val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)

View File

@ -1,58 +0,0 @@
package com.example.uikit.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun UikitTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}

View File

@ -1,34 +0,0 @@
package com.example.uikit.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)

View File

@ -3,4 +3,6 @@ plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.serialization) apply false
}

1
core/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

63
core/build.gradle.kts Normal file
View File

@ -0,0 +1,63 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
}
android {
namespace = "com.example.core"
compileSdk = 35
defaultConfig {
minSdk = 33
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
}
dependencies {
implementation(libs.kotlinx.serialization.json)
debugImplementation(libs.ui.tooling)
debugImplementation(libs.androidx.ui.tooling.preview)
api(platform(libs.androidx.compose.bom))
api(libs.androidx.activity.compose)
api(libs.androidx.ui)
api(libs.androidx.ui.graphics)
api(libs.androidx.ui.tooling.preview)
api(libs.androidx.material3)
api(libs.material)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}

0
core/consumer-rules.pro Normal file
View File

21
core/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,65 @@
package com.example.core
import androidx.activity.ComponentActivity
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.core.component.button.AppButton
import com.example.core.component.button.ButtonState
import com.example.core.component.select.AppSelector
import com.example.core.component.select.Option
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ComponentsTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
@Test
fun test_input_error() {
}
@Test
fun test_app_selector() {
composeTestRule.setContent {
var selectedOption1 by remember { mutableStateOf<Option?>(null) }
AppSelector(
selectedOption = selectedOption1,
options = listOf(
Option(label = "Мужской"),
Option(label = "Женский")
),
onOptionSelect = { selectedOption1 = it },
hint = "Пол"
)
}
composeTestRule.onNodeWithText("Пол").performClick()
composeTestRule.onNodeWithTag("AppBottomSheet").assertIsDisplayed()
}
@Test
fun test_chips_button() {
composeTestRule.setContent {
AppButton(
label = "Популярное",
onClick = {},
state = ButtonState.Chips,
enabled = false
)
}
composeTestRule.onNodeWithText("Популярное").assertIsDisplayed()
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@ -0,0 +1,60 @@
package com.example.core.component.button
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun AppButton(
label: String, // Текст кнопки
onClick: () -> Unit, // Действие на клик
state: ButtonState, // Состояние
modifier: Modifier = Modifier,
enabled: Boolean = true
) {
Box(contentAlignment = Alignment.Center, modifier = modifier) {
val commonCondition = state is ButtonState.Chips
Button(
modifier = modifier
.then(state.width())
.height(state.height()),
onClick = onClick,
shape = RoundedCornerShape(10.dp),
enabled = enabled,
colors = ButtonDefaults.buttonColors().copy(
containerColor = CustomTheme.colors.accent,
disabledContainerColor = if (commonCondition) CustomTheme.colors.inputBg else CustomTheme.colors.accentInactive
)
) {
}
Text(
text = label,
style = state.typography()
.copy(
color = if (commonCondition && !enabled) CustomTheme.colors.description else CustomTheme.colors.white,
textAlign = TextAlign.Center
),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.then(state.width())
.padding(horizontal = state.padding()),
)
}
}

View File

@ -0,0 +1,35 @@
package com.example.core.component.button
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.painter.Painter
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun BubbleButton(
state: BubbleButtonState, // cостояние
icon: Painter,
modifier: Modifier = Modifier
) {
Box(
contentAlignment = Alignment.Center,
modifier = modifier
.size(state.size())
.clip(RoundedCornerShape(state.roundness()))
.background(CustomTheme.colors.inputBg)
) {
Icon(painter = icon, contentDescription = null, tint = CustomTheme.colors.description)
}
}

View File

@ -0,0 +1,39 @@
package com.example.core.component.button
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
interface BubbleButtonState {
@Composable
fun roundness(): Dp // радиус скругления
@Composable
fun size(): Dp // размер
object Small : BubbleButtonState {
@Composable
override fun roundness(): Dp = CustomTheme.elevation.spacing8dp
@Composable
override fun size(): Dp = CustomTheme.elevation.spacing32dp
}
object Big : BubbleButtonState {
@Composable
override fun roundness(): Dp = 10.dp
@Composable
override fun size(): Dp = CustomTheme.elevation.spacing48dp
}
}

View File

@ -0,0 +1,77 @@
package com.example.core.component.button
import android.annotation.SuppressLint
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@SuppressLint("ModifierFactoryExtensionFunction")
interface ButtonState {
fun width(): Modifier // т.к fillmaxWith не является конкретной шириной, то возвращаемый тип modifier
fun height(): Dp // высота
fun padding(): Dp // отступы основного текста кнопки от контейнера
@Composable
fun typography(): TextStyle
object Big : ButtonState {
override fun width(): Modifier = Modifier.fillMaxWidth()
override fun height(): Dp = 56.dp
override fun padding(): Dp = 0.dp
@Composable
override fun typography(): TextStyle = CustomTheme.typography.title3Semibold
}
object Small : ButtonState {
override fun width(): Modifier = Modifier.width(98.dp)
override fun height(): Dp = 40.dp
override fun padding(): Dp = 13.5.dp
@Composable
override fun typography(): TextStyle = CustomTheme.typography.captionSemibold
}
object Chips : ButtonState {
override fun width(): Modifier = Modifier.width(129.dp)
override fun height(): Dp = 48.dp
override fun padding(): Dp = 20.dp
@Composable
override fun typography(): TextStyle = CustomTheme.typography.textMedium
}
object Login : ButtonState {
override fun width(): Modifier = Modifier.fillMaxWidth()
override fun height(): Dp = 60.dp
override fun padding(): Dp = 0.dp
@Composable
override fun typography(): TextStyle = CustomTheme.typography.title3Medium
}
}

View File

@ -0,0 +1,73 @@
package com.example.core.component.button
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.example.core.R
import com.example.core.theme.CustomIcons
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun CartButton(
onClick: () -> Unit,
totalPrice: Int, // цена на кнопке
modifier: Modifier = Modifier
) {
val state = ButtonState.Big
Box(contentAlignment = Alignment.CenterStart, modifier = modifier) {
Button(
modifier = modifier
.then(state.width())
.height(state.height()),
onClick = onClick,
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors().copy(
containerColor = CustomTheme.colors.accent,
disabledContentColor = CustomTheme.colors.accentInactive
)
) {
}
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) {
Icon(
painter = CustomIcons.cart,
contentDescription = null,
tint = CustomTheme.colors.white,
modifier = Modifier.padding(horizontal = CustomTheme.elevation.spacing16dp)
)
Text(
text = stringResource(R.string.in_cart),
style = state.typography().copy(color = CustomTheme.colors.white)
)
Spacer(Modifier.weight(1f))
Text(
text = stringResource(R.string.total_price, totalPrice),
style = state.typography().copy(color = CustomTheme.colors.white)
)
Spacer(Modifier.width(CustomTheme.elevation.spacing16dp))
}
}
}

View File

@ -0,0 +1,97 @@
package com.example.core.component.button
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomIcons
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
/**
* для установки цвета и обработки крайних случаев изменения по значению
* в кнопке есть параметр количества */
@Composable
fun ChangeQuantityButton(
currentQuantity: Int,
onIncrementClick: () -> Unit, // обработка увеличения количества
onDecrementClick: () -> Unit, // обработка уменьшения количества
modifier: Modifier = Modifier
) {
Box(
contentAlignment = Alignment.Center,
modifier = modifier
.width(CustomTheme.elevation.spacing64dp)
.height(CustomTheme.elevation.spacing32dp)
.clip(RoundedCornerShape(8.dp))
.background(CustomTheme.colors.inputBg)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 6.dp)
) {
val minusCondition = currentQuantity > 1
val minusTint by animateColorAsState(if (minusCondition) CustomTheme.colors.placeholder else CustomTheme.colors.inputIcon)
Icon(
painter = CustomIcons.minus,
contentDescription = null,
tint = minusTint,
modifier = Modifier.then(
if (minusCondition) {
Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
null,
onClick = onDecrementClick
)
} else Modifier
)
)
VerticalDivider(
thickness = 1.dp,
color = CustomTheme.colors.inputStroke,
modifier = Modifier.padding(
horizontal = 6.dp,
vertical = CustomTheme.elevation.spacing8dp
)
)
val plusCondition = currentQuantity < 100
val plusTint by animateColorAsState(if (plusCondition) CustomTheme.colors.placeholder else CustomTheme.colors.inputIcon)
Icon(
painter = CustomIcons.plus,
contentDescription = null,
tint = plusTint,
modifier = Modifier.then(
if (plusCondition) {
Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
null,
onClick = onIncrementClick
)
} else Modifier
)
)
}
}
}

View File

@ -0,0 +1,47 @@
package com.example.core.component.button
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun LoginButton(
icon: Painter,
label: String,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
val state = ButtonState.Login
OutlinedButton(
modifier = modifier
.then(state.width())
.height(state.height()),
onClick = onClick,
shape = RoundedCornerShape(10.dp),
border = BorderStroke(width = 1.dp, color = CustomTheme.colors.inputStroke)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Image(painter = icon, contentDescription = null)
Spacer(Modifier.width(CustomTheme.elevation.spacing16dp))
Text(text = label, style = state.typography())
}
}
}

View File

@ -0,0 +1,49 @@
package com.example.core.component.button
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun OutlinedAppButton(
label: String,
onClick: () -> Unit,
state: ButtonState,
modifier: Modifier = Modifier
) {
Box(contentAlignment = Alignment.Center, modifier = modifier) {
OutlinedButton(
modifier = modifier
.then(state.width())
.height(state.height()),
onClick = onClick,
shape = RoundedCornerShape(10.dp),
border = BorderStroke(width = 1.dp, color = CustomTheme.colors.accent)
) {
}
Text(
text = label,
style = state.typography()
.copy(color = CustomTheme.colors.accent, textAlign = TextAlign.Center),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.then(state.width()).padding(horizontal = state.padding())
)
}
}

View File

@ -0,0 +1,56 @@
package com.example.core.component.button
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun SecondaryAppButton(
label: String,
onClick: () -> Unit,
state: ButtonState,
modifier: Modifier = Modifier,
enabled: Boolean = true
) {
Box(contentAlignment = Alignment.Center, modifier = modifier) {
Button(
modifier = modifier
.then(state.width())
.height(state.height()),
onClick = onClick,
shape = RoundedCornerShape(10.dp),
enabled = enabled,
colors = ButtonDefaults.buttonColors().copy(
containerColor = CustomTheme.colors.inputBg,
disabledContentColor = CustomTheme.colors.accentInactive
)
) {
}
Text(
text = label,
style = state.typography()
.copy(color = CustomTheme.colors.black, textAlign = TextAlign.Center),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.then(state.width())
.padding(horizontal = state.padding())
)
}
}

View File

@ -0,0 +1,45 @@
package com.example.core.component.card
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
/**
* общий фон для карточек */
@Composable
fun AppCardBackground(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Column(
modifier = modifier
.fillMaxWidth()
.shadow(
elevation = 20.dp,
shape = RoundedCornerShape(CustomTheme.elevation.spacing12dp),
clip = false,
spotColor = Color(0xFFE4E8F5).copy(alpha = 0.6f)
)
.clip(RoundedCornerShape(CustomTheme.elevation.spacing12dp))
.background(CustomTheme.colors.white)
) {
Box(modifier = Modifier.padding(CustomTheme.elevation.spacing16dp)) {
content()
}
}
}

View File

@ -0,0 +1,76 @@
package com.example.core.component.card
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.example.core.R
import com.example.core.component.button.ChangeQuantityButton
import com.example.core.theme.CustomIcons
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun CartCard(
title: String,
price: Int,
currentQuantity: Int,
onChangeQuantity: (Int) -> Unit,
modifier: Modifier = Modifier
) {
AppCardBackground(modifier = modifier) {
Column {
Row {
Text(
text = title,
style = CustomTheme.typography.headlineMedium,
modifier = Modifier.weight(2f)
)
Row(horizontalArrangement = Arrangement.End, modifier = Modifier.weight(1f)) {
Icon(
painter = CustomIcons.close,
contentDescription = null,
tint = CustomTheme.colors.description
)
}
}
Spacer(Modifier.height(34.dp))
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = stringResource(R.string.total_price, price),
style = CustomTheme.typography.title3Medium,
modifier = Modifier.weight(1.7f)
)
Text(
text = stringResource(R.string.cart_card_quantity, currentQuantity),
style = CustomTheme.typography.textRegular
)
Row(modifier = Modifier.weight(1f), horizontalArrangement = Arrangement.End) {
/**
* обработка количества уже без дополнительных проверок */
ChangeQuantityButton(
currentQuantity = currentQuantity,
onIncrementClick = { onChangeQuantity(currentQuantity.inc()) },
onDecrementClick = { onChangeQuantity(currentQuantity.dec()) }
)
}
}
}
}
}

View File

@ -0,0 +1,69 @@
package com.example.core.component.card
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.example.core.R
import com.example.core.component.button.AppButton
import com.example.core.component.button.ButtonState
import com.example.core.component.button.OutlinedAppButton
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun PrimaryCard(
title: String,
category: String,
price: Int,
inCart: Boolean,
onAddToCartClick: () -> Unit,
onRemoveFromCartClick: () -> Unit,
modifier: Modifier = Modifier
) {
AppCardBackground(modifier = modifier) {
Column {
Text(text = title, style = CustomTheme.typography.headlineMedium)
Spacer(Modifier.height(CustomTheme.elevation.spacing16dp))
Row(verticalAlignment = Alignment.CenterVertically) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = category,
style = CustomTheme.typography.captionSemibold.copy(
color = CustomTheme.colors.placeholder
)
)
Spacer(Modifier.height(CustomTheme.elevation.spacing4dp))
Text(
text = stringResource(R.string.total_price, price),
style = CustomTheme.typography.title3Semibold
)
}
if (inCart) {
OutlinedAppButton(
label = stringResource(R.string.drop),
onClick = onRemoveFromCartClick,
state = ButtonState.Small
)
} else {
AppButton(
label = stringResource(R.string.add),
onClick = onAddToCartClick,
state = ButtonState.Small
)
}
}
}
}
}

View File

@ -0,0 +1,52 @@
package com.example.core.component.card
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.example.core.R
import com.example.core.component.button.AppButton
import com.example.core.component.button.ButtonState
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun ProjectCard(
title: String,
dayElapsed: Int,
onOpenClick: () -> Unit,
modifier: Modifier = Modifier
) {
AppCardBackground(modifier = modifier) {
Column {
Text(text = title, style = CustomTheme.typography.headlineMedium)
Spacer(Modifier.height(44.dp))
Row(verticalAlignment = Alignment.Bottom) {
Text(
text = pluralStringResource(R.plurals.elapsed_days, dayElapsed, dayElapsed),
style = CustomTheme.typography.captionSemibold.copy(
color = CustomTheme.colors.placeholder
),
modifier = Modifier.weight(1f)
)
AppButton(
label = stringResource(R.string.open),
onClick = onOpenClick,
state = ButtonState.Small
)
}
}
}
}

View File

@ -0,0 +1,37 @@
package com.example.core.component.header
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun BigHeader(
title: String,
modifier: Modifier = Modifier,
startContent: @Composable () -> Unit = {},
endContent: @Composable () -> Unit = {}
) {
Column(modifier = modifier) {
Box(contentAlignment = Alignment.CenterEnd, modifier = modifier.fillMaxWidth()) {
Box(modifier = Modifier.align(Alignment.CenterStart)) {
startContent()
}
endContent()
}
Spacer(Modifier.height(CustomTheme.elevation.spacing24dp))
Text(text = title, style = CustomTheme.typography.title1ExtraBold)
}
}

View File

@ -0,0 +1,35 @@
package com.example.core.component.header
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun SmallHeader(
title: String,
modifier: Modifier = Modifier,
startContent: @Composable () -> Unit,
endContent: @Composable () -> Unit
) {
Box(modifier = modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
Box(modifier = Modifier.align(Alignment.CenterStart)) {
startContent()
}
Text(text = title, style = CustomTheme.typography.title1SemiBold)
Box(modifier = Modifier.align(Alignment.CenterEnd)) {
endContent()
}
}
}

View File

@ -0,0 +1,177 @@
package com.example.core.component.input
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomIcons
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun EnterInputField(
value: String,
onValueChange: (String) -> Unit,
label: String, // названия поля (надпись над полем)
hint: String, // подсказка
errorMessage: String, // сообщенме об ошибке
modifier: Modifier = Modifier,
isPassword: Boolean = false, // являяется ли паролем (для отображения и скрытия)
keyboardOptions: KeyboardOptions = KeyboardOptions.Default // смена типа клавиатуры (только цифры и тд)
) {
/**
* отслеживание состояния фокуса для обводки активного поля
* */
val focusRequester = remember { FocusRequester() }
var hasFocus by rememberSaveable { mutableStateOf(false) }
var showPassword by rememberSaveable { mutableStateOf(false) }
/**
* Установка цвета рамки в зависимости от состояния
* */
val borderColor by animateColorAsState(
when {
errorMessage.isNotBlank() -> CustomTheme.colors.error
errorMessage.isBlank() && hasFocus -> CustomTheme.colors.accent
value.isEmpty() || (value.isNotEmpty() && label.isNotEmpty()) || isPassword -> CustomTheme.colors.inputStroke
else -> CustomTheme.colors.inputIcon
}
)
/**
* установка цвета поверх конентка в случае ошибки
* */
val overlayErrorColor by animateColorAsState(
if (errorMessage.isNotBlank()) CustomTheme.colors.error.copy(alpha = 0.1f) else Color.Transparent
)
Column(modifier = modifier) {
if (label.isNotBlank()) {
Text(
text = label,
style = CustomTheme.typography.captionRegular.copy(
color = CustomTheme.colors.description
)
)
Spacer(Modifier.height(CustomTheme.elevation.spacing8dp))
}
Box(
contentAlignment = Alignment.CenterStart,
modifier = Modifier
.fillMaxWidth()
.height(CustomTheme.elevation.spacing48dp)
.clip(RoundedCornerShape(10.dp))
.background(CustomTheme.colors.inputBg)
.border(width = 1.dp, color = borderColor, shape = RoundedCornerShape(10.dp))
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(overlayErrorColor)
)
Row(modifier = Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) {
Spacer(Modifier.width(14.dp))
Box(contentAlignment = Alignment.CenterStart, modifier = Modifier.weight(1f)) {
if (value.isEmpty()) {
Text(
text = hint,
style = CustomTheme.typography.textRegular.copy(
color = CustomTheme.colors.placeholder
)
)
}
BasicTextField(
value = value,
onValueChange = onValueChange,
singleLine = true,
cursorBrush = SolidColor(CustomTheme.colors.accent),
textStyle = CustomTheme.typography.textRegular,
keyboardOptions = keyboardOptions,
visualTransformation = if (isPassword && !showPassword) {
PasswordVisualTransformation()
} else VisualTransformation.None,
modifier = Modifier
.focusRequester(focusRequester)
.onFocusChanged { focusState ->
hasFocus = focusState.hasFocus
}
)
}
if (isPassword) {
val icon =
if (showPassword) CustomIcons.showPassword else CustomIcons.hidePassword
Icon(
painter = icon,
contentDescription = null,
modifier = Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) { showPassword = !showPassword }
)
Spacer(Modifier.width(15.dp))
}
}
}
/**
* отображение текста ошибки в случае ее наличия
* */
AnimatedVisibility(visible = errorMessage.isNotBlank()) {
Column {
Spacer(Modifier.height(CustomTheme.elevation.spacing8dp))
Text(
text = errorMessage,
style = CustomTheme.typography.captionRegular.copy(
color = CustomTheme.colors.error
)
)
}
}
}
}

View File

@ -0,0 +1,116 @@
package com.example.core.component.search
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomIcons
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun AppSearchField(
value: String,
onValueChange: (String) -> Unit,
hint: String,
modifier: Modifier = Modifier
) {
val focusRequester = remember { FocusRequester() }
var hasFocus by rememberSaveable { mutableStateOf(false) }
Box(
contentAlignment = Alignment.CenterStart,
modifier = Modifier
.fillMaxWidth()
.height(CustomTheme.elevation.spacing48dp)
.clip(RoundedCornerShape(10.dp))
.background(CustomTheme.colors.inputBg)
.border(
width = 1.dp,
color = CustomTheme.colors.inputStroke,
shape = RoundedCornerShape(10.dp)
)
) {
Column(modifier = modifier) {
Row(modifier = Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) {
Spacer(Modifier.width(14.dp))
Icon(
painter = CustomIcons.search,
tint = CustomTheme.colors.description,
contentDescription = null
)
Spacer(Modifier.width(CustomTheme.elevation.spacing8dp))
Box(contentAlignment = Alignment.CenterStart, modifier = Modifier.weight(1f)) {
if (value.isEmpty()) {
Text(
text = hint,
style = CustomTheme.typography.textRegular.copy(
color = CustomTheme.colors.placeholder
)
)
}
BasicTextField(
value = value,
onValueChange = onValueChange,
singleLine = true,
cursorBrush = SolidColor(CustomTheme.colors.accent),
textStyle = CustomTheme.typography.textRegular,
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester)
.onFocusChanged { focusState ->
hasFocus = focusState.hasFocus
}
)
}
if (hasFocus) {
Icon(
painter = CustomIcons.close,
contentDescription = null,
tint = CustomTheme.colors.description,
modifier = Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) { onValueChange("") }
)
Spacer(Modifier.width(14.dp))
}
}
}
}
}

View File

@ -0,0 +1,61 @@
package com.example.core.component.select
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomIcons
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
/**
* общее диалоговое окно
* */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppBottomSheet(
sheetState: SheetState, // состояние, для управлением отображения
onDismissRequest: () -> Unit, // обработка запроса на закрытие
modifier: Modifier = Modifier,
content: @Composable () -> Unit // контент
) {
ModalBottomSheet(
sheetState = sheetState,
onDismissRequest = onDismissRequest,
dragHandle = null,
containerColor = CustomTheme.colors.white,
modifier = modifier
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
) {
Spacer(Modifier.height(CustomTheme.elevation.spacing24dp))
Box {
Image(
painter = CustomIcons.closeSheet,
contentDescription = null,
modifier = Modifier.align(Alignment.TopEnd)
)
content()
}
Spacer(Modifier.height(84.dp))
}
}
}

View File

@ -0,0 +1,143 @@
package com.example.core.component.select
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomIcons
import com.example.core.theme.CustomTheme
import kotlinx.coroutines.launch
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppSelector(
selectedOption: Option?, // выбранная опция, если null то отображается подсказка
options: List<Option>, // список опций
onOptionSelect: (Option) -> Unit, // обработка нажатия
hint: String, // подсказка
modifier: Modifier = Modifier
) {
var showSheet by rememberSaveable { mutableStateOf(false) }
val sheetState = rememberModalBottomSheetState()
val scope = rememberCoroutineScope()
if (showSheet) {
AppBottomSheet(
sheetState = sheetState,
onDismissRequest = { showSheet = false },
modifier = Modifier.testTag("AppBottomSheet")
) {
Column(verticalArrangement = Arrangement.Center) {
options.forEach { option ->
Row(
modifier = Modifier
.heightIn(min = 40.dp)
.fillMaxWidth()
.clickable(
remember { MutableInteractionSource() },
null
) {
scope.launch {
onOptionSelect(option)
sheetState.hide()
}.invokeOnCompletion {
if (!sheetState.isVisible) {
showSheet = false
}
}
}
) {
Text(
text = option.label,
style = CustomTheme.typography.title2ExtraBold
)
}
}
}
}
}
Column(modifier = modifier) {
Box(
contentAlignment = Alignment.CenterStart,
modifier = Modifier
.fillMaxWidth()
.height(CustomTheme.elevation.spacing48dp)
.clip(RoundedCornerShape(10.dp))
.background(CustomTheme.colors.inputBg)
.border(
width = 1.dp,
color = CustomTheme.colors.inputStroke,
shape = RoundedCornerShape(10.dp)
)
) {
Row(
modifier = Modifier
.fillMaxSize()
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) { showSheet = true },
verticalAlignment = Alignment.CenterVertically
)
{
Spacer(Modifier.width(14.dp))
Box(contentAlignment = Alignment.CenterStart, modifier = Modifier.weight(1f)) {
selectedOption?.let {
Text(
text = selectedOption.label,
style = CustomTheme.typography.headlineRegular
)
} ?: run {
Text(
text = hint,
style = CustomTheme.typography.textRegular.copy(
color = CustomTheme.colors.placeholder
)
)
}
}
Icon(
painter = CustomIcons.more,
tint = CustomTheme.colors.description,
contentDescription = null
)
Spacer(Modifier.width(14.dp))
}
}
}
}

View File

@ -0,0 +1,9 @@
package com.example.core.component.select
/**
* класс опции, есть возможность установик эмоджи
* */
data class Option(
val label: String,
val iconId: Int? = null
)

View File

@ -0,0 +1,64 @@
package com.example.core.component.tabbar
import androidx.annotation.Keep
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
import com.example.core.R
import com.example.core.theme.CustomIcons
import kotlinx.serialization.Serializable
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
/**
* Общий интерфейс для всех вкладок меню навигации
* */
interface BottomTab {
@Composable
fun icon(): Painter
fun labelResId(): Int
}
@Keep
@Serializable
object Home : BottomTab {
@Composable
override fun icon(): Painter = CustomIcons.home
override fun labelResId(): Int = R.string.home
}
@Keep
@Serializable
object Catalog : BottomTab {
@Composable
override fun icon(): Painter = CustomIcons.catalog
override fun labelResId(): Int = R.string.catalog
}
@Keep
@Serializable
object Projects : BottomTab {
@Composable
override fun icon(): Painter = CustomIcons.projects
override fun labelResId(): Int = R.string.projects
}
@Keep
@Serializable
object Profile : BottomTab {
@Composable
override fun icon(): Painter = CustomIcons.profile
override fun labelResId(): Int = R.string.profile
}

View File

@ -0,0 +1,70 @@
package com.example.core.component.tabbar
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.HorizontalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun BottomTabBar(
tabs: List<BottomTab>,
hierarchy: Sequence<String?>?,
onTabClick: (BottomTab) -> Unit,
bottomPadding: Dp,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.background(CustomTheme.colors.white)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.height(67.dp)
.offset(y = -bottomPadding)
.background(CustomTheme.colors.white)
.clickable(interactionSource = remember { MutableInteractionSource() }, null) { }
) {
HorizontalDivider(thickness = 1.dp, color = Color(0xFFA0A0A0).copy(alpha = 0.3f))
Row(
horizontalArrangement = Arrangement.SpaceAround,
modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)
) {
tabs.forEach { tab ->
BottomTabBarItem(
bottomTab = tab,
selected = hierarchy?.any { it == tab::class.qualifiedName } ?: false,
modifier = Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) {
onTabClick(tab)
}
)
}
}
}
}
}

View File

@ -0,0 +1,39 @@
package com.example.core.component.tabbar
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.example.core.theme.CustomTheme
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Composable
fun BottomTabBarItem(
bottomTab: BottomTab,
selected: Boolean,
modifier: Modifier = Modifier
) {
val tintColor by animateColorAsState(if (selected) CustomTheme.colors.accent else CustomTheme.colors.inputIcon)
Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
Icon(
painter = bottomTab.icon(),
contentDescription = null,
tint = tintColor,
modifier = Modifier.weight(1f)
)
Text(
text = stringResource(bottomTab.labelResId()),
style = CustomTheme.typography.caption2Regular.copy(color = tintColor)
)
}
}

View File

@ -0,0 +1,21 @@
package com.example.core.theme
import androidx.compose.ui.graphics.Color
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
val Accent = Color(0xFF2074F2)
val AccentInactive = Color(0xFFC9D4FB)
val Black = Color(0xFF000000)
val White = Color(0xFFFFFFFF)
val Error = Color(0xFFFD3535)
val Success = Color(0xFF00B412)
val InputBg = Color(0xFFF5F5F9)
val InputStroke = Color(0xFFEBEBEB)
val InputIcon = Color(0xFFB8C1CC)
val Placeholder = Color(0xFF939396)
val Description = Color(0xFF8787A1)
val CardStroke = Color(0xFFF2F2F2)

View File

@ -0,0 +1,67 @@
package com.example.core.theme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import com.example.core.R
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
object CustomIcons {
val showPassword: Painter
@Composable get() = painterResource(R.drawable.icon_eye_show)
val hidePassword: Painter
@Composable get() = painterResource(R.drawable.icon_eye_close)
val closeSheet: Painter
@Composable get() = painterResource(R.drawable.icon_close_sheet)
val more: Painter
@Composable get() = painterResource(R.drawable.icon_chevron_down)
val close: Painter
@Composable get() = painterResource(R.drawable.icon_close)
val search: Painter
@Composable get() = painterResource(R.drawable.icon_search)
val cart: Painter
@Composable get() = painterResource(R.drawable.icon_shopping_cart)
val vk: Painter
@Composable get() = painterResource(R.drawable.icon_vk)
val yandex: Painter
@Composable get() = painterResource(R.drawable.icon_yandex)
val back: Painter
@Composable get() = painterResource(R.drawable.icon_chevron_left)
val filter: Painter
@Composable get() = painterResource(R.drawable.icon_filter)
val home: Painter
@Composable get() = painterResource(R.drawable.icon_home)
val catalog: Painter
@Composable get() = painterResource(R.drawable.icon_catalog)
val projects: Painter
@Composable get() = painterResource(R.drawable.icon_projects)
val profile: Painter
@Composable get() = painterResource(R.drawable.icon_profile)
val minus: Painter
@Composable get() = painterResource(R.drawable.icon_minus)
val plus: Painter
@Composable get() = painterResource(R.drawable.icon_plus)
val delete: Painter
@Composable get() = painterResource(R.drawable.icon_delete)
}

View File

@ -0,0 +1,191 @@
package com.example.core.theme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
@Immutable
data class CustomColors(
val accent: Color,
val accentInactive: Color,
val black: Color,
val white: Color,
val error: Color,
val success: Color,
val inputBg: Color,
val inputStroke: Color,
val inputIcon: Color,
val placeholder: Color,
val description: Color,
val cardStroke: Color
)
@Immutable
data class CustomTypography(
val title1SemiBold: TextStyle,
val title1ExtraBold: TextStyle,
val title2Regular: TextStyle,
val title2SemiBold: TextStyle,
val title2ExtraBold: TextStyle,
val title3Regular: TextStyle,
val title3Medium: TextStyle,
val title3Semibold: TextStyle,
val headlineRegular: TextStyle,
val headlineMedium: TextStyle,
val textRegular: TextStyle,
val textMedium: TextStyle,
val captionRegular: TextStyle,
val captionSemibold: TextStyle,
val caption2Regular: TextStyle,
val caption2Bold: TextStyle
)
@Immutable
data class CustomElevation(
val spacing4dp: Dp,
val spacing8dp: Dp,
val spacing12dp: Dp,
val spacing16dp: Dp,
val spacing20dp: Dp,
val spacing24dp: Dp,
val spacing32dp: Dp,
val spacing40dp: Dp,
val spacing48dp: Dp,
val spacing56dp: Dp,
val spacing64dp: Dp
)
val LocalCustomColors = staticCompositionLocalOf {
CustomColors(
accent = Color.Unspecified,
accentInactive = Color.Unspecified,
black = Color.Unspecified,
white = Color.Unspecified,
error = Color.Unspecified,
success = Color.Unspecified,
inputBg = Color.Unspecified,
inputStroke = Color.Unspecified,
inputIcon = Color.Unspecified,
placeholder = Color.Unspecified,
description = Color.Unspecified,
cardStroke = Color.Unspecified
)
}
val LocalCustomTypography = staticCompositionLocalOf {
CustomTypography(
title1SemiBold = TextStyle.Default,
title1ExtraBold = TextStyle.Default,
title2Regular = TextStyle.Default,
title2SemiBold = TextStyle.Default,
title2ExtraBold = TextStyle.Default,
title3Regular = TextStyle.Default,
title3Medium = TextStyle.Default,
title3Semibold = TextStyle.Default,
headlineRegular = TextStyle.Default,
headlineMedium = TextStyle.Default,
textRegular = TextStyle.Default,
textMedium = TextStyle.Default,
captionRegular = TextStyle.Default,
captionSemibold = TextStyle.Default,
caption2Regular = TextStyle.Default,
caption2Bold = TextStyle.Default
)
}
val LocalCustomElevation = staticCompositionLocalOf {
CustomElevation(
spacing4dp = Dp.Unspecified,
spacing8dp = Dp.Unspecified,
spacing12dp = Dp.Unspecified,
spacing16dp = Dp.Unspecified,
spacing20dp = Dp.Unspecified,
spacing24dp = Dp.Unspecified,
spacing32dp = Dp.Unspecified,
spacing40dp = Dp.Unspecified,
spacing48dp = Dp.Unspecified,
spacing56dp = Dp.Unspecified,
spacing64dp = Dp.Unspecified
)
}
@Composable
fun CustomTheme(content: @Composable () -> Unit) {
val customColors = CustomColors(
accent = Accent,
accentInactive = AccentInactive,
black = Black,
white = White,
error = Error,
success = Success,
inputBg = InputBg,
inputStroke = InputStroke,
inputIcon = InputIcon,
placeholder = Placeholder,
description = Description,
cardStroke = CardStroke
)
val customTypography = CustomTypography(
title1SemiBold = Title1SemiBold,
title1ExtraBold = Title1ExtraBold,
title2Regular = Title2Regular,
title2SemiBold = Title2SemiBold,
title2ExtraBold = Title2ExtraBold,
title3Regular = Title3Regular,
title3Medium = Title3Medium,
title3Semibold = Title3Semibold,
headlineRegular = HeadlineRegular,
headlineMedium = HeadlineMedium,
textRegular = TextRegular,
textMedium = TextMedium,
captionRegular = CaptionRegular,
captionSemibold = CaptionSemibold,
caption2Regular = Caption2Regular,
caption2Bold = Caption2Bold
)
val customElevation = CustomElevation(
spacing4dp = 4.dp,
spacing8dp = 8.dp,
spacing12dp = 12.dp,
spacing16dp = 16.dp,
spacing20dp = 20.dp,
spacing24dp = 24.dp,
spacing32dp = 32.dp,
spacing40dp = 40.dp,
spacing48dp = 48.dp,
spacing56dp = 56.dp,
spacing64dp = 64.dp
)
CompositionLocalProvider(
LocalCustomColors provides customColors,
LocalCustomTypography provides customTypography,
LocalCustomElevation provides customElevation,
content = content
)
}
object CustomTheme {
val colors: CustomColors
@Composable get() = LocalCustomColors.current
val typography: CustomTypography
@Composable get() = LocalCustomTypography.current
val elevation: CustomElevation
@Composable get() = LocalCustomElevation.current
}

View File

@ -0,0 +1,19 @@
package com.example.core.theme
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import com.example.core.R
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
val RobotoFontFamily = FontFamily(
Font(resId = R.font.roboto_extra_bold, weight = FontWeight.ExtraBold),
Font(resId = R.font.roboto_semibold, weight = FontWeight.SemiBold),
Font(resId = R.font.roboto_regular, weight = FontWeight.Normal),
Font(resId = R.font.roboto_medium, weight = FontWeight.Medium),
Font(resId = R.font.roboto_bold, weight = FontWeight.Bold)
)

View File

@ -0,0 +1,155 @@
package com.example.core.theme
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
/**
* Автор: Манякин Дмитрий (user5)
* Дата создания: 26.05.2025
* */
val Title1SemiBold = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 24.sp,
lineHeight = 28.sp,
letterSpacing = 0.0033.em,
color = Black
)
val Title1ExtraBold = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.ExtraBold,
fontSize = 24.sp,
lineHeight = 28.sp,
letterSpacing = 0.0033.em,
color = Black
)
val Title2Regular = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 20.sp,
lineHeight = 28.sp,
letterSpacing = 0.0038.em,
color = Black
)
val Title2SemiBold = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 20.sp,
lineHeight = 28.sp,
letterSpacing = 0.0038.em,
color = Black
)
val Title2ExtraBold = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.ExtraBold,
fontSize = 20.sp,
lineHeight = 28.sp,
letterSpacing = 0.0038.em,
color = Black
)
val Title3Regular = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 17.sp,
lineHeight = 24.sp,
letterSpacing = 0.em,
color = Black
)
val Title3Medium = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Medium,
fontSize = 17.sp,
lineHeight = 24.sp,
letterSpacing = 0.em,
color = Black
)
val Title3Semibold = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 17.sp,
lineHeight = 24.sp,
letterSpacing = 0.em,
color = Black
)
val HeadlineRegular = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 20.sp,
letterSpacing = (-0.0032).em,
color = Black
)
val HeadlineMedium = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Medium,
fontSize = 16.sp,
lineHeight = 20.sp,
letterSpacing = (-0.0032).em,
color = Black
)
val TextRegular = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 15.sp,
lineHeight = 20.sp,
letterSpacing = 0.em,
color = Black
)
val TextMedium = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Medium,
fontSize = 15.sp,
lineHeight = 20.sp,
letterSpacing = 0.em,
color = Black
)
val CaptionRegular = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.em,
color = Black
)
val CaptionSemibold = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.em,
color = Black
)
val Caption2Regular = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.em,
color = Black
)
val Caption2Bold = TextStyle(
fontFamily = RobotoFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.em,
color = Black
)

View File

@ -0,0 +1,35 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M7,23.479V8.521C7,7.129 8.129,6 9.521,6H22.479C23.871,6 25,7.129 25,8.521V23.479C25,24.871 23.871,26 22.479,26H9.521C8.129,26 7,24.871 7,23.479Z"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#B8C1CC"/>
<path
android:pathData="M11,16V11H16V16H11Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#B8C1CC"/>
<path
android:pathData="M20,11H21"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#B8C1CC"
android:strokeLineCap="round"/>
<path
android:pathData="M20,16H21"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#B8C1CC"
android:strokeLineCap="round"/>
<path
android:pathData="M11,21L21,21"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#B8C1CC"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M16.666,4A1,1 0,0 0,15.959 4.293L7.5,12.752 4.041,9.293a1,1 0,0 0,-1.414 0,1 1,0 0,0 0,1.414l4.166,4.166a1,1 0,0 0,1.414 0L17.373,5.707a1,1 0,0 0,0 -1.414A1,1 0,0 0,16.666 4Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m5,7.5a1,1 0,0 0,-0.707 0.293,1 1,0 0,0 0,1.414l5,5a1,1 0,0 0,1.414 0l5,-5a1,1 0,0 0,0 -1.414,1 1,0 0,0 -1.414,0L10,12.086 5.707,7.793A1,1 0,0 0,5 7.5Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m11.5,4a1,1 0,0 0,-0.707 0.293l-5,5a1,1 0,0 0,0 1.414l5,5a1,1 0,0 0,1.414 0,1 1,0 0,0 0,-1.414L7.914,10 12.207,5.707a1,1 0,0 0,0 -1.414A1,1 0,0 0,11.5 4Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m7.5,4a1,1 0,0 0,-0.707 0.293,1 1,0 0,0 0,1.414L11.086,10 6.793,14.293a1,1 0,0 0,0 1.414,1 1,0 0,0 1.414,0l5,-5a1,1 0,0 0,0 -1.414l-5,-5A1,1 0,0 0,7.5 4Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m5,4a1,1 0,0 0,-0.707 0.293,1 1,0 0,0 0,1.414L8.586,10 4.293,14.293a1,1 0,0 0,0 1.414,1 1,0 0,0 1.414,0L10,11.414l4.293,4.293a1,1 0,0 0,1.414 0,1 1,0 0,0 0,-1.414L11.414,10 15.707,5.707a1,1 0,0 0,0 -1.414A1,1 0,0 0,15 4,1 1,0 0,0 14.293,4.293L10,8.586 5.707,4.293A1,1 0,0 0,5 4Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,24C18.627,24 24,18.627 24,12C24,5.373 18.627,0 12,0C5.373,0 0,5.373 0,12C0,18.627 5.373,24 12,24Z"
android:strokeAlpha="0.12"
android:fillColor="#B8C1CC"
android:fillAlpha="0.12"/>
<path
android:pathData="M16.736,7.264C17.088,7.615 17.088,8.185 16.736,8.536L13.273,12L16.736,15.464C17.059,15.786 17.085,16.292 16.817,16.644L16.736,16.736C16.385,17.088 15.815,17.088 15.464,16.736L12,13.273L8.536,16.736C8.185,17.088 7.615,17.088 7.264,16.736C6.912,16.385 6.912,15.815 7.264,15.464L10.727,12L7.264,8.536C6.941,8.214 6.915,7.709 7.183,7.356L7.264,7.264C7.615,6.912 8.185,6.912 8.536,7.264L12,10.727L15.464,7.264C15.815,6.912 16.385,6.912 16.736,7.264Z"
android:fillColor="#7E7E9A"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m8.334,0.666c-0.707,0 -1.387,0.281 -1.887,0.781 -0.5,0.5 -0.781,1.18 -0.781,1.887L5.666,4h-1.5L2.5,4a1,1 0,0 0,-1 1,1 1,0 0,0 1,1h0.666v10.666c0,0.707 0.281,1.387 0.781,1.887 0.5,0.5 1.18,0.781 1.887,0.781h8.332c0.707,0 1.387,-0.282 1.887,-0.781 0.5,-0.5 0.781,-1.18 0.781,-1.887L16.834,6L17.5,6a1,1 0,0 0,1 -1,1 1,0 0,0 -1,-1h-1.666,-1.5L14.334,3.334c0,-0.707 -0.282,-1.387 -0.781,-1.887 -0.5,-0.5 -1.18,-0.781 -1.887,-0.781zM8.334,2.666h3.332c0.177,0 0.347,0.07 0.473,0.195 0.125,0.125 0.195,0.295 0.195,0.473L12.334,4L7.666,4L7.666,3.334c0,-0.177 0.07,-0.347 0.195,-0.473C7.987,2.736 8.157,2.666 8.334,2.666ZM5.166,6h9.668v10.666c0,0.177 -0.07,0.347 -0.195,0.473 -0.125,0.125 -0.295,0.195 -0.473,0.195L5.834,17.334c-0.177,0 -0.347,-0.07 -0.473,-0.195C5.236,17.013 5.166,16.843 5.166,16.666ZM8.334,8.166a1,1 0,0 0,-1 1v5a1,1 0,0 0,1 1,1 1,0 0,0 1,-1L9.334,9.166a1,1 0,0 0,-1 -1zM11.666,8.166a1,1 0,0 0,-1 1v5a1,1 0,0 0,1 1,1 1,0 0,0 1,-1L12.666,9.166a1,1 0,0 0,-1 -1z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m10,1.5a1,1 0,0 0,-1 1v7.586L6.541,7.627A1,1 0,0 0,5.834 7.334,1 1,0 0,0 5.127,7.627a1,1 0,0 0,0 1.414L9.293,13.207A1,1 0,0 0,10 13.5,1 1,0 0,0 10.707,13.207l4.166,-4.166a1,1 0,0 0,0 -1.414,1 1,0 0,0 -1.414,0L11,10.086L11,2.5a1,1 0,0 0,-1 -1zM2.5,11.5a1,1 0,0 0,-1 1v3.334c0,0.707 0.281,1.385 0.781,1.885C2.781,18.219 3.459,18.5 4.166,18.5L15.834,18.5c0.707,0 1.385,-0.281 1.885,-0.781C18.219,17.219 18.5,16.541 18.5,15.834L18.5,12.5a1,1 0,0 0,-1 -1,1 1,0 0,0 -1,1v3.334c0,0.177 -0.07,0.345 -0.195,0.471C16.179,16.43 16.011,16.5 15.834,16.5L4.166,16.5C3.989,16.5 3.821,16.43 3.695,16.305 3.57,16.179 3.5,16.011 3.5,15.834L3.5,12.5a1,1 0,0 0,-1 -1z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<clip-path
android:pathData="M0,0h20v20h-20z"/>
<path
android:pathData="M0.818,0.14C0.632,-0.047 0.33,-0.047 0.144,0.14C-0.042,0.326 -0.042,0.628 0.144,0.814L4.255,4.925C2.555,6.245 1.131,7.887 0.066,9.757C-0.022,9.907 -0.022,10.093 0.066,10.243C2.235,13.906 4.999,16.215 8.064,16.921C8.7,17.068 9.35,17.142 10.002,17.142C11.763,17.118 13.481,16.592 14.954,15.627L19.185,19.86V19.86C19.372,20.046 19.673,20.046 19.86,19.86C20.046,19.674 20.046,19.372 19.86,19.186L0.818,0.14ZM8.019,8.689L11.313,11.984H11.314C10.699,12.386 9.933,12.481 9.239,12.243C8.545,12.004 7.999,11.458 7.761,10.764C7.523,10.07 7.618,9.304 8.019,8.689L8.019,8.689ZM8.281,15.993C5.544,15.362 3.044,13.292 1.036,10H1.036C2.034,8.293 3.357,6.798 4.931,5.601L7.344,8.014C6.694,8.873 6.501,9.994 6.827,11.02C7.153,12.047 7.957,12.851 8.983,13.177C10.009,13.503 11.13,13.31 11.989,12.66L14.266,14.938H14.266C12.488,16.065 10.337,16.444 8.281,15.993L8.281,15.993ZM10.35,7.655L9.421,6.726C9.613,6.687 9.807,6.668 10.002,6.667C10.886,6.667 11.734,7.018 12.359,7.643C12.984,8.268 13.335,9.116 13.335,10C13.334,10.195 13.315,10.39 13.276,10.581L12.347,9.652H12.348C12.273,9.149 12.038,8.683 11.679,8.324C11.319,7.964 10.853,7.729 10.35,7.655ZM19.934,9.757V9.757C20.022,9.907 20.022,10.093 19.934,10.243C19.096,11.686 18.057,13.003 16.849,14.155L16.174,13.479V13.479C17.26,12.452 18.2,11.281 18.969,10C16.532,6.006 13.356,3.81 10.002,3.81C9.005,3.82 8.019,4.021 7.097,4.401L6.359,3.663C7.503,3.141 8.745,2.867 10.002,2.858C13.774,2.858 17.301,5.308 19.934,9.757L19.934,9.757Z"
android:fillColor="#000000"/>
</group>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<clip-path
android:pathData="M0,0h20v20h-20z"/>
<path
android:pathData="M10,6.955C9.216,6.955 8.464,7.266 7.909,7.82C7.355,8.374 7.043,9.126 7.043,9.91C7.042,10.694 7.353,11.446 7.908,12C8.462,12.555 9.214,12.867 9.998,12.867C10.782,12.867 11.534,12.556 12.088,12.001C12.642,11.447 12.954,10.695 12.954,9.911C12.953,9.128 12.642,8.376 12.088,7.822C11.535,7.268 10.783,6.956 10,6.955L10,6.955ZM10,11.225C9.651,11.225 9.316,11.087 9.069,10.84C8.822,10.594 8.683,10.259 8.682,9.91C8.682,9.561 8.821,9.226 9.068,8.979C9.315,8.732 9.65,8.593 9.999,8.594C10.348,8.594 10.683,8.733 10.929,8.98C11.176,9.227 11.314,9.562 11.314,9.911C11.313,10.259 11.175,10.593 10.929,10.84C10.682,11.086 10.348,11.225 10,11.225L10,11.225Z"
android:fillColor="#000000"/>
<path
android:pathData="M17.471,7.507L18.226,6.666C18.421,6.447 18.485,6.141 18.393,5.863C18.302,5.584 18.069,5.376 17.782,5.316C17.495,5.256 17.198,5.354 17.003,5.572L16.274,6.381V6.381C15.722,5.933 15.124,5.544 14.49,5.222L14.982,4.311V4.311C15.087,4.059 15.06,3.771 14.91,3.543C14.759,3.315 14.505,3.177 14.231,3.175C13.958,3.173 13.702,3.307 13.548,3.533L12.967,4.605C12.268,4.393 11.548,4.258 10.82,4.204V3.169C10.82,2.876 10.664,2.605 10.41,2.459C10.156,2.312 9.844,2.312 9.59,2.459C9.336,2.605 9.18,2.876 9.18,3.169V4.202C8.452,4.256 7.732,4.391 7.034,4.603L6.452,3.533C6.313,3.275 6.047,3.112 5.754,3.103C5.461,3.095 5.186,3.244 5.032,3.493C4.879,3.743 4.87,4.055 5.009,4.313L5.501,5.224C4.867,5.546 4.269,5.935 3.717,6.383L2.988,5.574V5.574C2.793,5.356 2.496,5.258 2.209,5.318C1.922,5.378 1.689,5.586 1.598,5.865C1.506,6.143 1.57,6.449 1.765,6.667L2.529,7.507C1.959,8.123 1.469,8.808 1.071,9.546C0.958,9.776 0.958,10.046 1.071,10.275C1.182,10.496 3.83,15.649 10,15.649C16.17,15.649 18.824,10.496 18.929,10.275C19.043,10.046 19.043,9.776 18.929,9.546C18.531,8.808 18.041,8.123 17.471,7.507L17.471,7.507ZM10,14.009C5.683,14.009 3.416,10.988 2.746,9.911C3.418,8.847 5.712,5.809 10,5.809C11.033,5.802 12.059,5.988 13.025,6.356L13.098,6.385H13.098C14.068,6.775 14.957,7.341 15.72,8.056C15.745,8.085 15.771,8.116 15.8,8.144C15.829,8.171 15.84,8.173 15.858,8.187L15.858,8.187C16.392,8.704 16.86,9.282 17.254,9.911C16.582,10.974 14.288,14.009 10,14.009L10,14.009Z"
android:fillColor="#000000"/>
</group>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M5,0.916C4.359,0.916 3.744,1.172 3.291,1.625 2.838,2.078 2.584,2.693 2.584,3.334L2.584,16.666c0,0.641 0.254,1.256 0.707,1.709C3.744,18.828 4.359,19.084 5,19.084h10c0.641,0 1.256,-0.256 1.709,-0.709 0.453,-0.453 0.707,-1.068 0.707,-1.709L17.416,6.666A0.75,0.75 0,0 0,17.359 6.379,0.75 0.75,0 0,0 17.197,6.137v-0.002a0.75,0.75 0,0 0,-0.018 -0.016l-4.977,-4.977 -0.006,-0.006A0.75,0.75 0,0 0,11.98 0.99,0.75 0.75,0 0,0 11.92,0.967 0.75,0.75 0,0 0,11.666 0.916ZM5,2.416h5.916v4.25a0.75,0.75 0,0 0,0.75 0.75h4.25v9.25c0,0.243 -0.095,0.476 -0.268,0.648C15.476,17.486 15.243,17.584 15,17.584L5,17.584c-0.243,0 -0.476,-0.097 -0.648,-0.27C4.179,17.142 4.084,16.909 4.084,16.666L4.084,3.334c0,-0.243 0.095,-0.476 0.268,-0.648C4.524,2.513 4.757,2.416 5,2.416ZM12.416,3.477 L14.855,5.916L12.416,5.916ZM6.666,6.75a0.75,0.75 0,0 0,-0.75 0.75,0.75 0.75,0 0,0 0.75,0.75L7.5,8.25 8.334,8.25a0.75,0.75 0,0 0,0.75 -0.75,0.75 0.75,0 0,0 -0.75,-0.75L7.5,6.75ZM6.666,10.084a0.75,0.75 0,0 0,-0.75 0.75,0.75 0.75,0 0,0 0.75,0.75h6.668a0.75,0.75 0,0 0,0.75 -0.75,0.75 0.75,0 0,0 -0.75,-0.75zM6.666,13.416a0.75,0.75 0,0 0,-0.75 0.75,0.75 0.75,0 0,0 0.75,0.75h6.668a0.75,0.75 0,0 0,0.75 -0.75,0.75 0.75,0 0,0 -0.75,-0.75z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M1.666,1.5A1,1 0,0 0,0.902 3.146L7.334,10.75v5.084a1,1 0,0 0,0.553 0.895L11.219,18.395A1,1 0,0 0,12.666 17.5v-6.75l6.432,-7.604A1,1 0,0 0,18.334 1.5ZM3.822,3.5L16.178,3.5l-5.275,6.238a1,1 0,0 0,-0.236 0.645v5.498L9.334,15.215L9.334,10.383A1,1 0,0 0,9.098 9.738Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M27.481,15.773L23.809,12.624V8.373C23.809,8.112 23.598,7.901 23.337,7.901H20.878C20.617,7.901 20.405,8.112 20.405,8.373V9.702L16.315,6.195C16.136,6.034 15.865,6.034 15.685,6.195L4.52,15.773C4.368,15.903 4.314,16.113 4.385,16.3C4.455,16.486 4.635,16.608 4.835,16.605H8.191V25.446C8.191,25.707 8.403,25.919 8.663,25.919H10.307C10.568,25.919 10.78,25.707 10.78,25.446C10.78,25.186 10.568,24.974 10.307,24.974H9.136V16.132C9.136,15.872 8.924,15.66 8.663,15.66H6.104L16,7.184L25.897,15.66H23.337C23.076,15.66 22.865,15.872 22.865,16.132V24.974H21.69C21.43,24.974 21.218,25.186 21.218,25.446C21.218,25.707 21.43,25.919 21.69,25.919H23.337C23.598,25.919 23.809,25.707 23.809,25.446V16.605H27.176C27.375,16.608 27.555,16.486 27.625,16.3C27.696,16.113 27.642,15.903 27.491,15.773L27.481,15.773ZM21.353,8.846H22.865V11.815L21.353,10.518V8.846ZM20.408,17.732H11.592C11.331,17.732 11.119,17.943 11.119,18.204V26.391C11.119,26.652 11.331,26.864 11.592,26.864H20.408C20.669,26.864 20.881,26.652 20.881,26.391V18.204C20.881,17.943 20.669,17.732 20.408,17.732ZM16.671,18.677V20.859L16.561,20.792L16.56,20.793C16.374,20.68 16.135,20.71 15.981,20.865L15.553,21.296L15.333,21.044V18.677L16.671,18.677ZM19.939,25.919H12.068V18.677H14.391V21.221C14.39,21.337 14.432,21.449 14.508,21.536L15.178,22.298C15.265,22.396 15.388,22.454 15.519,22.458C15.645,22.459 15.766,22.409 15.855,22.32L16.378,21.791L16.885,22.106C17.031,22.193 17.212,22.195 17.36,22.112C17.507,22.028 17.599,21.872 17.6,21.703V18.677H19.936L19.939,25.919Z"
android:fillColor="#B8C1CC"/>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<clip-path
android:pathData="M0,0h20v20h-20z"/>
<path
android:pathData="m13.334,4a1,1 0,0 0,-1 1v13.334a1,1 0,0 0,1 1,1 1,0 0,0 1,-1V5a1,1 0,0 0,-1 -1zM6.666,0.666a1,1 0,0 0,-1 1V15a1,1 0,0 0,1 1,1 1,0 0,0 1,-1V1.666a1,1 0,0 0,-1 -1zM7.113,0.771A1,1 0,0 0,6.17 0.799L0.338,4.131A1,1 0,0 0,-0.166 5v13.334a1,1 0,0 0,1.496 0.867l5.367,-3.068 6.189,3.096a1,1 0,0 0,0.943 -0.027l5.832,-3.332A1,1 0,0 0,20.166 15V1.666A1,1 0,0 0,18.67 0.799L13.303,3.867ZM6.697,2.801 L12.887,5.895a1,1 0,0 0,0.943 -0.025L18.166,3.391v11.029l-4.863,2.779 -6.189,-3.094a1,1 0,0 0,-0.943 0.025L1.834,16.609V5.582Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</group>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M10.416,1.5C9.161,1.497 7.923,1.79 6.803,2.355 5.46,3.026 4.33,4.058 3.541,5.334 2.752,6.61 2.335,8.081 2.334,9.582 2.331,10.648 2.652,11.672 3.063,12.652l-1.512,4.531a1,1 0,0 0,1.266 1.266l4.531,-1.512c0.981,0.41 2.005,0.731 3.072,0.729 1.5,-0.001 2.97,-0.418 4.246,-1.207 1.275,-0.789 2.306,-1.917 2.977,-3.258v-0.002C18.209,12.077 18.503,10.837 18.5,9.58L18.5,9.166a1,1 0,0 0,-0.002 -0.055C18.389,7.129 17.552,5.256 16.148,3.852 14.745,2.448 12.871,1.611 10.889,1.502A1,1 0,0 0,10.834 1.5h-0.414zM10.414,3.5a1,1 0,0 0,0.002 0h0.369c1.488,0.084 2.895,0.711 3.949,1.766C15.789,6.32 16.416,7.726 16.5,9.215v0.369a1,1 0,0 0,0 0.002c0.002,0.942 -0.218,1.872 -0.643,2.713a1,1 0,0 0,-0.002 0.004c-0.505,1.01 -1.282,1.861 -2.242,2.455 -0.961,0.594 -2.068,0.908 -3.197,0.908a1,1 0,0 0,-0.002 0C9.472,15.668 8.542,15.448 7.701,15.023A1,1 0,0 0,6.934 14.969L4.082,15.918 5.031,13.066A1,1 0,0 0,4.977 12.299C4.552,11.458 4.332,10.528 4.334,9.586a1,1 0,0 0,0 -0.002C4.334,8.454 4.648,7.347 5.242,6.387 5.836,5.426 6.687,4.65 7.697,4.145a1,1 0,0 0,0.004 -0.002C8.542,3.718 9.472,3.498 10.414,3.5Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<clip-path
android:pathData="M0,0h20v20h-20z"/>
<path
android:pathData="m6.666,18.166a1,1 0,0 0,-1 1,1 1,0 0,0 1,1h6.668a1,1 0,0 0,1 -1,1 1,0 0,0 -1,-1zM10,14.834a1,1 0,0 0,-1 1v3.332a1,1 0,0 0,1 1,1 1,0 0,0 1,-1v-3.332a1,1 0,0 0,-1 -1zM4.166,7.334a1,1 0,0 0,-1 1L3.166,10c0,1.812 0.721,3.551 2.002,4.832C6.449,16.113 8.188,16.834 10,16.834c1.812,0 3.551,-0.721 4.832,-2.002C16.113,13.551 16.834,11.812 16.834,10L16.834,8.334a1,1 0,0 0,-1 -1,1 1,0 0,0 -1,1L14.834,10c0,1.282 -0.509,2.511 -1.416,3.418 -0.907,0.907 -2.136,1.416 -3.418,1.416 -1.282,0 -2.511,-0.509 -3.418,-1.416C5.675,12.511 5.166,11.282 5.166,10L5.166,8.334a1,1 0,0 0,-1 -1zM10,-0.166c-0.928,0 -1.819,0.369 -2.475,1.025C6.869,1.515 6.5,2.406 6.5,3.334L6.5,10c0,0.928 0.369,1.819 1.025,2.475C8.181,13.131 9.072,13.5 10,13.5c0.928,0 1.818,-0.369 2.475,-1.025C13.131,11.819 13.5,10.928 13.5,10L13.5,3.334C13.5,2.406 13.131,1.515 12.475,0.859 11.818,0.203 10.928,-0.166 10,-0.166ZM10,1.834c0.398,0 0.779,0.158 1.061,0.439C11.342,2.555 11.5,2.936 11.5,3.334L11.5,10c0,0.398 -0.158,0.779 -0.439,1.061C10.779,11.342 10.398,11.5 10,11.5 9.602,11.5 9.221,11.342 8.939,11.061 8.658,10.779 8.5,10.398 8.5,10L8.5,3.334C8.5,2.936 8.658,2.555 8.939,2.273 9.221,1.992 9.602,1.834 10,1.834Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</group>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m4.166,9a1,1 0,0 0,-1 1,1 1,0 0,0 1,1H15.834a1,1 0,0 0,1 -1,1 1,0 0,0 -1,-1z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M10,10.833C10.46,10.833 10.833,10.46 10.833,10C10.833,9.54 10.46,9.167 10,9.167C9.54,9.167 9.167,9.54 9.167,10C9.167,10.46 9.54,10.833 10,10.833Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#B8C1CC"
android:strokeColor="#B8C1CC"
android:strokeLineCap="round"/>
<path
android:pathData="M15.833,10.833C16.294,10.833 16.667,10.46 16.667,10C16.667,9.54 16.294,9.167 15.833,9.167C15.373,9.167 15,9.54 15,10C15,10.46 15.373,10.833 15.833,10.833Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#B8C1CC"
android:strokeColor="#B8C1CC"
android:strokeLineCap="round"/>
<path
android:pathData="M4.167,10.833C4.627,10.833 5,10.46 5,10C5,9.54 4.627,9.167 4.167,9.167C3.706,9.167 3.333,9.54 3.333,10C3.333,10.46 3.706,10.833 4.167,10.833Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#B8C1CC"
android:strokeColor="#B8C1CC"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m13.15,0.156c-1.149,0 -2.254,0.457 -3.066,1.27L2.426,9.084C1.3,10.209 0.668,11.738 0.668,13.33c0,1.592 0.632,3.119 1.758,4.244 1.125,1.125 2.652,1.758 4.244,1.758 1.592,0 3.121,-0.632 4.246,-1.758l7.658,-7.658a1,1 0,0 0,0 -1.414,1 1,0 0,0 -1.414,0L9.502,16.16c-0.751,0.751 -1.77,1.172 -2.832,1.172 -1.062,0 -2.079,-0.421 -2.83,-1.172 -0.751,-0.751 -1.172,-1.768 -1.172,-2.83 0,-1.062 0.421,-2.081 1.172,-2.832L11.498,2.84C11.936,2.402 12.531,2.156 13.15,2.156c0.62,0 1.212,0.245 1.65,0.684 0.438,0.438 0.684,1.033 0.684,1.652 0,0.62 -0.245,1.212 -0.684,1.65L7.135,13.801c-0.125,0.125 -0.295,0.195 -0.473,0.195 -0.177,0 -0.345,-0.07 -0.471,-0.195a1,1 0,0 0,-0.002 0C6.064,13.675 5.994,13.508 5.994,13.33c0,-0.177 0.07,-0.347 0.195,-0.473L13.266,5.791a1,1 0,0 0,0 -1.414A1,1 0,0 0,11.852 4.375l-7.074,7.068a1,1 0,0 0,-0.002 0c-0.5,0.5 -0.781,1.18 -0.781,1.887 0,0.707 0.281,1.385 0.781,1.885 0.5,0.5 1.18,0.781 1.887,0.781 0.707,0 1.387,-0.281 1.887,-0.781L16.215,7.557c0.813,-0.813 1.27,-1.915 1.27,-3.064 0,-1.149 -0.457,-2.254 -1.27,-3.066C15.402,0.613 14.3,0.156 13.15,0.156Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="m10,3.166a1,1 0,0 0,-1 1V9H4.166a1,1 0,0 0,-1 1,1 1,0 0,0 1,1H9v4.834a1,1 0,0 0,1 1,1 1,0 0,0 1,-1V11h4.834a1,1 0,0 0,1 -1,1 1,0 0,0 -1,-1H11V4.166a1,1 0,0 0,-1 -1z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M16,10m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#B8C1CC"/>
<path
android:pathData="M16,17C20.502,17 24,20.326 24,24.25V24.251C24,24.251 24,24.253 23.999,24.256C23.997,24.262 23.99,24.277 23.974,24.304C23.937,24.361 23.858,24.454 23.7,24.57C23.376,24.809 22.841,25.061 22.081,25.285C20.573,25.731 18.425,26 16,26C13.575,26 11.427,25.731 9.919,25.285C9.159,25.061 8.624,24.809 8.3,24.57C8.142,24.454 8.063,24.361 8.026,24.304C8.01,24.277 8.003,24.262 8.001,24.256C8,24.253 8,24.251 8,24.251V24.25C8,20.326 11.498,17 16,17Z"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#B8C1CC"/>
</vector>

View File

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M7.369,1.837H2.683C2.456,1.837 2.305,1.987 2.305,2.212V6.825C2.305,7.05 2.456,7.2 2.683,7.2H7.331C7.558,7.2 7.709,7.049 7.709,6.825V2.212C7.746,1.987 7.557,1.837 7.369,1.837ZM6.991,6.45H3.061V2.587H6.953V6.45H6.991Z"
android:fillColor="#B8C1CC"/>
<path
android:pathData="M7.369,9.3H2.683C2.456,9.3 2.305,9.45 2.305,9.675V14.287C2.305,14.512 2.456,14.662 2.683,14.662H7.331C7.558,14.662 7.709,14.512 7.709,14.287V9.675C7.746,9.487 7.557,9.3 7.369,9.3ZM6.991,13.95H3.061V10.05H6.953V13.95H6.991Z"
android:fillColor="#B8C1CC"/>
<path
android:pathData="M7.369,16.8H2.683C2.456,16.8 2.305,16.95 2.305,17.175V21.787C2.305,22.012 2.456,22.162 2.683,22.162H7.331C7.558,22.162 7.709,22.012 7.709,21.787V17.175C7.746,16.987 7.557,16.8 7.369,16.8ZM6.991,21.412H3.061V17.55H6.953V21.412H6.991Z"
android:fillColor="#B8C1CC"/>
<path
android:pathData="M4.194,5.662C4.269,5.737 4.383,5.774 4.458,5.774C4.572,5.774 4.647,5.737 4.723,5.662L6.537,3.862C6.688,3.712 6.688,3.487 6.537,3.337C6.386,3.187 6.159,3.187 6.008,3.337L4.458,4.874L4.043,4.462C3.891,4.312 3.665,4.312 3.514,4.462C3.362,4.612 3.362,4.837 3.514,4.987L4.194,5.662Z"
android:fillColor="#B8C1CC"/>
<path
android:pathData="M4.194,13.162C4.269,13.237 4.345,13.274 4.458,13.274C4.572,13.274 4.647,13.237 4.723,13.162L6.537,11.362C6.688,11.212 6.688,10.987 6.537,10.837C6.386,10.687 6.159,10.687 6.008,10.837L4.458,12.374L4.043,11.962C3.891,11.812 3.665,11.812 3.514,11.962C3.362,12.112 3.362,12.337 3.514,12.487L4.194,13.162Z"
android:fillColor="#B8C1CC"/>
<path
android:pathData="M4.194,20.662C4.269,20.737 4.383,20.774 4.458,20.774C4.572,20.774 4.647,20.737 4.723,20.662L6.537,18.862C6.688,18.712 6.688,18.487 6.537,18.337C6.386,18.187 6.159,18.187 6.008,18.337L4.458,19.874L4.043,19.462C3.891,19.312 3.665,19.312 3.514,19.462C3.362,19.612 3.362,19.837 3.514,19.987L4.194,20.662Z"
android:fillColor="#B8C1CC"/>
<path
android:pathData="M23.655,13.462H19.423C19.196,13.462 19.045,13.612 19.045,13.837C18.289,13.575 18.553,13.725 18.175,13.537L18.176,5.887C18.176,5.775 18.138,5.7 18.062,5.625L12.508,0.112C12.432,0.038 12.319,0 12.243,0H0.378C0.151,0 0,0.15 0,0.375V23.625C0,23.85 0.151,24 0.378,24H17.76C17.987,24 18.138,23.85 18.138,23.625V21.45H19.007C19.045,21.638 19.196,21.75 19.385,21.75H23.617C23.844,21.75 23.995,21.6 23.995,21.375V13.838C24.033,13.613 23.844,13.463 23.655,13.463L23.655,13.462ZM19.045,14.587V20.7H11.752C11.223,20.7 11.185,20.287 11.185,20.175C11.185,20.024 11.223,19.912 11.299,19.8C11.374,19.687 11.525,19.65 11.676,19.65C11.903,19.65 12.054,19.5 12.054,19.275C12.054,19.049 11.903,18.9 11.676,18.9H11.147C10.618,18.9 10.58,18.487 10.58,18.375C10.58,18.187 10.694,17.85 11.11,17.85C11.299,17.85 11.45,17.699 11.487,17.512C11.487,17.324 11.374,17.137 11.185,17.099H10.921C10.316,17.137 10.089,17.024 10.014,16.725C9.976,16.574 10.014,16.387 10.089,16.274C10.203,16.162 10.354,16.087 10.505,16.087C10.732,16.087 10.883,15.937 10.883,15.712C10.883,15.487 10.732,15.337 10.505,15.337H9.938C9.523,15.337 9.409,15 9.409,14.812C9.409,14.737 9.447,14.287 9.976,14.287H12.621C13.226,14.287 13.717,14.024 13.944,13.612C14.133,13.199 14.208,12.487 13.339,11.362C13.037,10.987 12.923,10.499 13.075,10.124C13.264,9.599 13.793,9.374 14.133,9.337C14.095,12.074 16.816,13.687 18.025,14.249C18.062,14.325 19.045,14.587 19.045,14.587L19.045,14.587ZM12.621,1.274L16.891,5.512H12.621V1.274ZM17.42,23.249H0.793V0.749H11.865V5.887C11.865,6.112 12.016,6.262 12.243,6.262H17.42V13.087C16.286,12.374 14.888,11.099 14.926,9.337C14.926,9.149 14.85,8.924 14.699,8.812C14.548,8.662 14.321,8.624 14.132,8.624C13.263,8.737 12.658,9.224 12.394,9.899C12.167,10.537 12.318,11.249 12.772,11.849C13.263,12.449 13.452,13.012 13.301,13.274C13.188,13.499 12.81,13.537 12.658,13.537H10.013C9.144,13.537 8.691,14.174 8.691,14.812C8.691,15.262 8.955,15.749 9.409,15.974C9.258,16.274 9.22,16.574 9.295,16.912C9.409,17.362 9.711,17.624 10.013,17.737C9.9,17.924 9.862,18.149 9.862,18.374C9.862,18.824 10.127,19.312 10.58,19.537C10.467,19.724 10.429,19.949 10.429,20.174C10.429,20.812 10.882,21.449 11.752,21.449H17.42L17.42,23.249ZM23.277,21.037H19.8V14.212H23.277V21.037Z"
android:fillColor="#B8C1CC"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M9.166,1.5C4.944,1.5 1.5,4.944 1.5,9.166c0,4.222 3.444,7.668 7.666,7.668 1.752,0 3.368,-0.596 4.662,-1.592l2.965,2.965a1,1 0,0 0,1.414 0,1 1,0 0,0 0,-1.414L15.242,13.828C16.238,12.534 16.834,10.918 16.834,9.166 16.834,4.944 13.388,1.5 9.166,1.5ZM9.166,3.5c3.141,0 5.668,2.525 5.668,5.666 0,1.529 -0.6,2.911 -1.576,3.928a1,1 0,0 0,-0.09 0.074,1 1,0 0,0 -0.063,0.078c-1.018,0.983 -2.405,1.588 -3.939,1.588C6.025,14.834 3.5,12.308 3.5,9.166 3.5,6.025 6.025,3.5 9.166,3.5Z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<clip-path
android:pathData="M0,0h20v20h-20z"/>
<path
android:pathData="M18.004,0.723 L1.336,6.557a1,1 0,0 0,-0.076 1.857l7.148,3.178 3.178,7.148a1,1 0,0 0,1.857 -0.076L19.277,1.996A1,1 0,0 0,18.004 0.723ZM16.703,3.297 L12.389,15.623 10.08,10.428A1,1 0,0 0,9.572 9.92L4.377,7.611ZM17.627,0.959 L8.459,10.127a1,1 0,0 0,0 1.414,1 1,0 0,0 1.414,0L19.041,2.373a1,1 0,0 0,0 -1.414,1 1,0 0,0 -1.414,0z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</group>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<clip-path
android:pathData="M0,0h20v20h-20z"/>
<path
android:pathData="m0.834,-0.166a1,1 0,0 0,-1 1,1 1,0 0,0 1,1L3.348,1.834L5.42,12.188c0.122,0.614 0.456,1.164 0.943,1.557 0.487,0.392 1.097,0.602 1.723,0.59h8.061c0.626,0.012 1.237,-0.198 1.725,-0.59 0.487,-0.392 0.821,-0.943 0.943,-1.557a1,1 0,0 0,0.002 -0.008L20.148,5.188A1,1 0,0 0,19.166 4L5.82,4L5.146,0.637A1,1 0,0 0,4.166 -0.166ZM6.221,6L17.957,6l-1.105,5.805v-0.008c-0.031,0.154 -0.112,0.29 -0.234,0.389 -0.122,0.098 -0.275,0.151 -0.432,0.148a1,1 0,0 0,-0.02 0L8.066,12.334a1,1 0,0 0,-0.02 0C7.89,12.337 7.739,12.284 7.617,12.186 7.495,12.087 7.411,11.95 7.381,11.797a1,1 0,0 0,0 -0.002zM16.666,15.666c-1.001,0 -1.832,0.833 -1.832,1.834 0,1.001 0.831,1.834 1.832,1.834 1.001,0 1.834,-0.833 1.834,-1.834 0,-1.001 -0.833,-1.834 -1.834,-1.834zM16.666,17.334c0.08,0 0.168,0.086 0.168,0.166 0,0.08 -0.088,0.166 -0.168,0.166C16.586,17.666 16.5,17.58 16.5,17.5c0,-0.08 0.086,-0.166 0.166,-0.166zM7.5,15.666c-1.001,0 -1.834,0.833 -1.834,1.834 0,1.001 0.833,1.834 1.834,1.834 1.001,0 1.834,-0.833 1.834,-1.834 0,-1.001 -0.833,-1.834 -1.834,-1.834zM7.5,17.334c0.08,0 0.166,0.086 0.166,0.166 0,0.08 -0.086,0.166 -0.166,0.166 -0.08,0 -0.166,-0.086 -0.166,-0.166 0,-0.08 0.086,-0.166 0.166,-0.166z"
android:strokeLineJoin="round"
android:fillColor="#b8c1cc"
android:strokeLineCap="round"/>
</group>
</vector>

View File

@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="33dp"
android:height="32dp"
android:viewportWidth="33"
android:viewportHeight="32">
<group>
<clip-path
android:pathData="M0.5,0h32v32h-32z"/>
<path
android:pathData="M0.5,0H32.5V32H0.5V0Z"
android:fillColor="#0077FF"/>
<path
android:pathData="M8.571,8.622C7.611,9.76 7.611,11.467 7.611,14.915V17.067C7.611,20.498 7.611,22.222 8.571,23.36C8.731,23.573 8.927,23.751 9.105,23.911C10.26,24.871 11.985,24.871 15.416,24.871H17.567C20.998,24.871 22.722,24.871 23.86,23.911C24.074,23.751 24.251,23.556 24.411,23.378C25.371,22.222 25.371,20.498 25.371,17.067V14.933C25.371,11.502 25.371,9.778 24.411,8.64C24.251,8.427 24.056,8.249 23.878,8.071C22.722,7.111 20.998,7.111 17.567,7.111H15.434C12.002,7.111 10.278,7.111 9.14,8.053C8.927,8.231 8.749,8.409 8.589,8.622H8.571ZM10.634,13.298C10.722,14.524 11.131,15.858 11.7,16.764C12.749,18.489 14.349,19.378 16.678,19.502L17.069,19.538V16.978L17.354,17.013C18.473,17.156 19.611,18.044 20.091,19.182L20.234,19.538H20.589C21.176,19.538 22.278,19.573 22.278,19.538C22.06,18.797 21.696,18.107 21.208,17.508C20.719,16.91 20.116,16.415 19.434,16.053L19.291,15.964L19.522,15.787C20.666,15.063 21.493,13.932 21.834,12.622V12.444H19.967L19.825,12.8C19.469,13.689 18.634,14.649 17.905,15.004C17.638,15.129 17.371,15.2 17.069,15.236V12.444H15.345V17.369L15.078,17.28C14.367,17.013 13.691,16.355 13.282,15.573C12.927,14.915 12.678,13.867 12.607,12.942L12.589,12.444H10.58L10.651,13.298H10.634Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
</group>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="33dp"
android:height="32dp"
android:viewportWidth="33"
android:viewportHeight="32">
<path
android:pathData="M6.17,0C3.029,0 0.5,2.529 0.5,5.67V26.33C0.5,29.471 3.029,32 6.17,32H21.376L32.5,16.004L21.376,0H6.17V0ZM14.685,5.842H18.298C18.52,5.842 18.647,5.923 18.647,6.114V26.026C18.647,26.162 18.583,26.243 18.393,26.243H16.428C16.302,26.243 16.207,26.134 16.207,26.053V18.681H14.621L10.216,26.053C10.153,26.189 10.026,26.243 9.836,26.243H7.586C7.333,26.243 7.175,26.053 7.333,25.808L12.181,18.3C9.583,17.321 8.125,15.335 8.125,12.642C8.125,8.154 11.136,5.842 14.685,5.842L14.685,5.842ZM14.59,7.582C12.657,7.582 10.755,8.969 10.755,12.37C10.755,15.634 12.783,16.94 14.875,16.94H16.207V7.582H14.59Z"
android:fillColor="#FFC107"/>
</vector>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="in_cart">В корзину</string>
<string name="total_price">%1$s ₽</string>
<string name="home">Главная</string>
<string name="catalog">Каталог</string>
<string name="projects">Проекты</string>
<string name="profile">Профиль</string>
<string name="drop">Убрать</string>
<string name="add">Добавить</string>
<string name="cart_card_quantity">%1$s штук</string>
<string name="open">Открыть</string>
<plurals name="elapsed_days">
<item quantity="one">Прошел %1$s день</item>
<item quantity="few">Прошло %1$s дня</item>
<item quantity="many">Прошло %1$s дней</item>
</plurals>
</resources>

View File

@ -0,0 +1,17 @@
package com.example.core
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@ -1,15 +1,52 @@
[versions]
agp = "8.9.2"
kotlin = "2.0.21"
androidPdfViewer = "3.2.0-beta.3"
kotlin = "2.1.20"
coreKtx = "1.16.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
lifecycleRuntimeKtx = "2.9.0"
lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.10.1"
composeBom = "2024.09.00"
composeBom = "2025.04.01"
appcompat = "1.7.0"
material = "1.12.0"
jetbrainsKotlinJvm = "2.1.20"
retrofit = "2.11.0"
okhttp3 = "4.12.0"
kotlinxSerializationConverter = "1.0.0"
kotlinxSerializationJson = "1.8.0"
navigationCompose = "2.9.0"
dagger = "2.55"
hiltNavigationCompose = "1.2.0"
datastorePreferences = "1.1.6"
javaxInject = "1"
kotlinxCoroutinesTest = "1.10.2"
uiTooling = "1.8.2"
coil = "3.1.0"
materialIconsExtended = "1.7.8"
[libraries]
androidx-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended", version.ref = "materialIconsExtended" }
coil-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" }
coil-network-http = { group = "io.coil-kt.coil3", name = "coil-network-okhttp", version.ref = "coil" }
mockwebserver = { group = "com.squareup.okhttp3", name = "mockwebserver", version.ref = "okhttp3" }
kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesTest" }
javax-inject = { group = "javax.inject", name = "javax.inject", version.ref = "javaxInject" }
android-pdf-viewer = { group = "com.github.mhiew", name = "android-pdf-viewer", version.ref = "androidPdfViewer" }
androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastorePreferences" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "dagger" }
hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "dagger" }
hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" }
navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
retrofit2-kotlinx-serialization-converter = { group = "com.jakewharton.retrofit", name = "retrofit2-kotlinx-serialization-converter", version.ref = "kotlinxSerializationConverter" }
logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp3" }
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp3" }
retrofit2 = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
@ -24,9 +61,16 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "uiTooling" }
[plugins]
dagger-hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "dagger" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
android-library = { id = "com.android.library", version.ref = "agp" }
jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "jetbrainsKotlinJvm" }

View File

@ -21,4 +21,4 @@ dependencyResolutionManagement {
rootProject.name = "uikit"
include(":app")
include(":core")