@uniai-fe/uds-primitives 0.1.13 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +2 -2
  2. package/dist/styles.css +1112 -385
  3. package/package.json +12 -15
  4. package/src/components/button/index.scss +1 -0
  5. package/src/components/button/markup/{ButtonRounded.tsx → Rounded.tsx} +1 -1
  6. package/src/components/button/markup/{ButtonText.tsx → Text.tsx} +1 -1
  7. package/src/components/button/markup/index.ts +3 -3
  8. package/src/components/button/styles/button.scss +113 -229
  9. package/src/components/button/styles/round-button.scss +11 -14
  10. package/src/components/button/styles/text-button.scss +23 -23
  11. package/src/components/button/styles/variables.scss +145 -0
  12. package/src/components/dropdown/index.tsx +3 -3
  13. package/src/components/dropdown/markup/Template.tsx +61 -0
  14. package/src/components/dropdown/markup/foundation/Container.tsx +97 -0
  15. package/src/components/dropdown/markup/foundation/MenuItem.tsx +107 -0
  16. package/src/components/dropdown/markup/foundation/MenuList.tsx +27 -0
  17. package/src/components/dropdown/markup/foundation/Provider.tsx +46 -0
  18. package/src/components/dropdown/markup/foundation/Root.tsx +30 -0
  19. package/src/components/dropdown/markup/foundation/Trigger.tsx +34 -0
  20. package/src/components/dropdown/markup/foundation/index.tsx +25 -0
  21. package/src/components/dropdown/markup/index.tsx +8 -2
  22. package/src/components/dropdown/styles/dropdown.scss +166 -0
  23. package/src/components/dropdown/styles/index.scss +2 -0
  24. package/src/components/dropdown/styles/variables.scss +40 -0
  25. package/src/components/dropdown/types/base.ts +18 -0
  26. package/src/components/dropdown/types/index.ts +2 -4
  27. package/src/components/dropdown/types/props.ts +174 -0
  28. package/src/components/dropdown/utils/index.ts +1 -4
  29. package/src/components/dropdown/utils/refs.ts +20 -0
  30. package/src/components/form/index.scss +1 -0
  31. package/src/components/form/index.tsx +18 -2
  32. package/src/components/form/markup/form-field/Body.tsx +18 -0
  33. package/src/components/form/markup/form-field/Container.tsx +58 -0
  34. package/src/components/form/markup/form-field/Footer.tsx +21 -0
  35. package/src/components/form/markup/form-field/Header.tsx +39 -0
  36. package/src/components/form/markup/form-field/Template.tsx +56 -0
  37. package/src/components/form/markup/form-field/index.tsx +22 -0
  38. package/src/components/form/styles/form-field/layout.scss +67 -0
  39. package/src/components/form/styles/form-field/variables.scss +17 -0
  40. package/src/components/form/styles/index.scss +2 -0
  41. package/src/components/form/types/index.ts +1 -0
  42. package/src/components/form/types/props.ts +125 -0
  43. package/src/components/form/utils/form-field.ts +42 -0
  44. package/src/components/input/hooks/index.ts +1 -4
  45. package/src/components/input/hooks/useDigitField.ts +63 -0
  46. package/src/components/input/img/calendar/calendar.svg +7 -0
  47. package/src/components/input/img/calendar/chevron-down.svg +3 -0
  48. package/src/components/input/img/calendar/chevron-left.svg +3 -0
  49. package/src/components/input/img/calendar/chevron-right.svg +3 -0
  50. package/src/components/input/img/calendar/chevron-up.svg +3 -0
  51. package/src/components/input/index.tsx +2 -1
  52. package/src/components/input/markup/calendar/Base.tsx +329 -0
  53. package/src/components/input/markup/calendar/index.tsx +8 -0
  54. package/src/components/input/markup/{text/InputUtilityButton.tsx → foundation/Button.tsx} +5 -15
  55. package/src/components/input/markup/foundation/Input.tsx +245 -0
  56. package/src/components/input/markup/foundation/SideSlot.tsx +30 -0
  57. package/src/components/input/markup/foundation/StatusIcon.tsx +21 -0
  58. package/src/components/input/markup/foundation/Utility.tsx +103 -0
  59. package/src/components/input/markup/foundation/index.tsx +15 -0
  60. package/src/components/input/markup/index.tsx +11 -1
  61. package/src/components/input/markup/text/AuthCode.tsx +41 -59
  62. package/src/components/input/markup/text/Email.tsx +25 -115
  63. package/src/components/input/markup/text/Password.tsx +30 -39
  64. package/src/components/input/markup/text/Phone.tsx +35 -122
  65. package/src/components/input/markup/text/Search.tsx +17 -18
  66. package/src/components/input/markup/text/index.ts +15 -12
  67. package/src/components/input/styles/calendar.scss +110 -0
  68. package/src/components/input/styles/foundation.scss +345 -0
  69. package/src/components/input/styles/index.scss +4 -476
  70. package/src/components/input/styles/text.scss +89 -0
  71. package/src/components/input/styles/variables.scss +41 -0
  72. package/src/components/input/types/calendar.ts +208 -0
  73. package/src/components/input/types/foundation.ts +194 -0
  74. package/src/components/input/types/hooks.ts +43 -0
  75. package/src/components/input/types/index.ts +5 -87
  76. package/src/components/input/types/text.ts +203 -0
  77. package/src/components/input/types/verification.ts +23 -0
  78. package/src/components/input/utils/index.tsx +1 -0
  79. package/src/components/input/utils/verification.tsx +35 -0
  80. package/src/components/select/hooks/index.ts +43 -2
  81. package/src/components/select/img/chevron/primary/large.svg +3 -0
  82. package/src/components/select/img/chevron/primary/medium.svg +3 -0
  83. package/src/components/select/img/chevron/primary/small.svg +3 -0
  84. package/src/components/select/img/chevron/secondary/large.svg +3 -0
  85. package/src/components/select/img/chevron/secondary/medium.svg +3 -0
  86. package/src/components/select/img/chevron/secondary/small.svg +3 -0
  87. package/src/components/select/img/remove.svg +3 -0
  88. package/src/components/select/index.scss +2 -1
  89. package/src/components/select/index.tsx +5 -0
  90. package/src/components/select/markup/Default.tsx +154 -0
  91. package/src/components/select/markup/foundation/Base.tsx +90 -0
  92. package/src/components/select/markup/foundation/Container.tsx +30 -0
  93. package/src/components/select/markup/foundation/Icon.tsx +78 -0
  94. package/src/components/select/markup/foundation/Selected.tsx +34 -0
  95. package/src/components/select/markup/foundation/index.ts +2 -0
  96. package/src/components/select/markup/index.tsx +36 -2
  97. package/src/components/select/markup/multiple/Multiple.tsx +205 -0
  98. package/src/components/select/markup/multiple/SelectedChip.tsx +58 -0
  99. package/src/components/select/markup/multiple/index.ts +2 -0
  100. package/src/components/select/styles/select.scss +316 -0
  101. package/src/components/select/styles/variables.scss +91 -0
  102. package/src/components/select/types/base.ts +34 -0
  103. package/src/components/select/types/icon.ts +45 -0
  104. package/src/components/select/types/index.ts +5 -4
  105. package/src/components/select/types/multiple.ts +57 -0
  106. package/src/components/select/types/props.ts +208 -0
  107. package/src/components/select/types/trigger.ts +196 -0
  108. package/src/index.scss +3 -2
  109. package/src/components/input/markup/text/Base.tsx +0 -454
  110. package/src/components/input/utils/index.ts +0 -60
  111. package/src/components/select/styles/index.scss +0 -0
  112. /package/src/components/button/markup/{ButtonDefault.tsx → Base.tsx} +0 -0
  113. /package/src/components/form/{Provider.tsx → markup/Provider.tsx} +0 -0
@@ -1,74 +1,35 @@
1
+ "use client";
2
+
1
3
  import { maskPhone } from "@uniai-fe/util-functions";
2
- import type { ChangeEvent, ComponentPropsWithoutRef, ReactNode } from "react";
3
- import { forwardRef, useCallback, useMemo, useState } from "react";
4
- import type { InputProps, InputState } from "../../types";
5
- import { Text } from "./Base";
6
- import { AuthCodeInput } from "./AuthCode";
7
- import { InputUtilityButton } from "./InputUtilityButton";
4
+ import type { ChangeEvent } from "react";
5
+ import { forwardRef, useCallback, useMemo } from "react";
6
+ import type { PhoneInputProps } from "../../types";
7
+ import InputBase from "../foundation/Input";
8
+ import { renderVerificationRequestButton } from "../../utils/verification";
9
+ import { useDigitField } from "../../hooks/useDigitField";
8
10
 
9
11
  /**
10
- * PhoneInput 전용 props. Text Input 전화번호 UX에 필요한 필드를 정의한다.
11
- * @property {string} [value] 제어형 포맷팅 값.
12
- * @property {string} [defaultValue] 비제어 초기값(숫자/포맷 모두 허용).
13
- * @property {(value: string, digits: string) => void} [onValueChange] 포맷팅 값/숫자만 값을 함께 전달.
14
- * @property {ComponentPropsWithoutRef<"input">["onChange"]} [onChange] native onChange override.
15
- * @property {() => void} [onRequestCode] 인증 요청 버튼 클릭 시 호출(optional).
16
- * @property {string} [requestButtonLabel="인증번호 요청"] 인증 요청 버튼 라벨(optional).
17
- * @property {boolean} [requestButtonDisabled] 인증 요청 버튼 disabled(optional).
18
- * @property {React.ReactNode} [countdownText] 인증 제한 시간 안내 텍스트(optional).
19
- * @property {React.ReactNode} [countdownActionLabel="시간연장"] 제한 시간 연장 버튼(optional).
20
- * @property {() => void} [onCountdownAction] 제한 시간 연장 핸들러(optional).
21
- * @property {boolean} [countdownActionDisabled] 제한 시간 연장 disabled(optional).
22
- * @property {boolean} [codeVisible] 인증번호 입력 UI 노출 여부(optional).
23
- * @property {number} [codeLength=6] 인증번호 길이(optional).
24
- * @property {React.ReactNode} [codeLabel] 인증번호 label(optional).
25
- * @property {React.ReactNode} [codeHelper] 인증번호 helper 텍스트(optional).
26
- * @property {InputState} [codeState] 인증번호 입력 상태(optional).
27
- * @property {(code: string) => void} [onCodeComplete] 인증번호 입력 완료 콜백(optional).
28
- * @property {string} [codePlaceholder="인증코드 입력"] 인증번호 placeholder(optional).
12
+ * 휴대폰 입력에서 허용할 숫자 자리수. 국내 번호 11자 기준.
29
13
  */
30
- export interface PhoneInputProps extends Omit<
31
- InputProps,
32
- "type" | "inputMode" | "pattern" | "onChange" | "value" | "defaultValue"
33
- > {
34
- value?: string;
35
- defaultValue?: string;
36
- onValueChange?: (value: string, digits: string) => void;
37
- onChange?: ComponentPropsWithoutRef<"input">["onChange"];
38
- onRequestCode?: () => void;
39
- requestButtonLabel?: string;
40
- requestButtonDisabled?: boolean;
41
- countdownText?: ReactNode;
42
- countdownActionLabel?: ReactNode;
43
- onCountdownAction?: () => void;
44
- countdownActionDisabled?: boolean;
45
- codeVisible?: boolean;
46
- codeLength?: number;
47
- codeLabel?: ReactNode;
48
- codeHelper?: ReactNode;
49
- codeState?: InputState;
50
- onCodeComplete?: (code: string) => void;
51
- codePlaceholder?: string;
52
- }
53
-
54
14
  const MAX_DIGITS = 11;
55
15
 
56
- const normalizeDigits = (value?: string) => (value ?? "").replace(/\D/g, "");
57
-
58
- // util-functions의 maskPhone 규칙으로 자리수/패턴을 일원화한다.
16
+ /**
17
+ * util-functions의 maskPhone 규칙으로 자리수/패턴을 일원화한다.
18
+ */
59
19
  const formatPhoneNumber = (digits: string) => maskPhone(digits);
60
20
 
61
21
  /**
62
- * 휴대폰 번호 입력 컴포넌트; 기본은 마스킹만 제공하고 인증 UI는 optional props로 노출한다.
22
+ * 휴대폰 번호 입력 컴포넌트; 마스킹 처리와 인증요청 버튼까지만 담당한다.
63
23
  * @component
64
24
  * @param {PhoneInputProps} props 휴대폰 입력 props
65
25
  * @param {string} [props.value] 제어형 포맷 값
66
26
  * @param {string} [props.defaultValue] 비제어 초기값
67
27
  * @param {(value: string, digits: string) => void} [props.onValueChange] 포맷/숫자 변경 콜백
68
- * @param {ComponentPropsWithoutRef<"input">["onChange"]} [props.onChange] native onChange override
69
- * @param {() => void} [props.onRequestCode] 인증 요청 버튼 클릭 시 호출
70
- * @param {string} [props.requestButtonLabel] 인증 요청 버튼 라벨
28
+ * @param {(event: ChangeEvent<HTMLInputElement>) => void} [props.onChange] native onChange override
29
+ * @param {InputUtilityButtonClickHandler} [props.onRequestCode] 인증 요청 버튼 클릭 시 호출
30
+ * @param {ReactNode} [props.requestButtonLabel] 인증 요청 버튼 라벨
71
31
  * @param {boolean} [props.requestButtonDisabled] 인증 요청 버튼 disabled
32
+ * @param {ReactNode} [props.right] 기본 오른쪽 슬롯 override
72
33
  */
73
34
  const PhoneInput = forwardRef<HTMLInputElement, PhoneInputProps>(
74
35
  (
@@ -80,69 +41,42 @@ const PhoneInput = forwardRef<HTMLInputElement, PhoneInputProps>(
80
41
  onRequestCode,
81
42
  requestButtonLabel = "인증번호 요청",
82
43
  requestButtonDisabled,
83
- countdownText,
84
- countdownActionLabel = "시간연장",
85
- onCountdownAction,
86
- countdownActionDisabled,
87
- codeVisible,
88
- codeLength = 6,
89
- codeLabel,
90
- codeHelper,
91
- codeState,
92
- onCodeComplete,
93
- codePlaceholder = "인증코드 입력",
94
44
  right,
95
45
  ...restProps
96
46
  },
97
47
  forwardedRef,
98
48
  ) => {
99
- const isControlled = value !== undefined;
100
- const [digitsState, setDigitsState] = useState(() =>
101
- normalizeDigits(defaultValue),
102
- );
103
- const digits = isControlled ? normalizeDigits(value) : digitsState;
104
- const formattedValue = useMemo(
105
- () => formatPhoneNumber(digits.slice(0, MAX_DIGITS)),
106
- [digits],
107
- );
49
+ // 제어/비제어 숫자 입력을 통합 관리한다.
50
+ const { digits, handleDigitsChange } = useDigitField({
51
+ value,
52
+ defaultValue,
53
+ maxLength: MAX_DIGITS,
54
+ });
55
+ const formattedValue = useMemo(() => formatPhoneNumber(digits), [digits]);
108
56
 
109
57
  const handleChange = useCallback(
110
58
  (event: ChangeEvent<HTMLInputElement>) => {
111
- const digitsOnly = normalizeDigits(event.currentTarget.value).slice(
112
- 0,
113
- MAX_DIGITS,
114
- );
115
- if (!isControlled) {
116
- setDigitsState(digitsOnly);
117
- }
59
+ const digitsOnly = handleDigitsChange(event);
118
60
  const formatted = formatPhoneNumber(digitsOnly);
119
61
  if (event.currentTarget.value !== formatted) {
120
62
  event.currentTarget.value = formatted;
121
63
  }
64
+ // 포맷팅된 값과 숫자만으로 분리된 값을 모두 호출자에게 전달한다.
122
65
  onValueChange?.(formatted, digitsOnly);
123
66
  onChange?.(event);
124
67
  },
125
- [isControlled, onChange, onValueChange],
68
+ [handleDigitsChange, onChange, onValueChange],
126
69
  );
127
70
 
128
- const actionButton = useMemo(() => {
129
- if (!onRequestCode) {
130
- return null;
131
- }
132
- // 휴대폰 인증 입력은 우측 right 슬롯에 인증 버튼을 둔다.
133
- return (
134
- <InputUtilityButton
135
- priority="primary"
136
- onClick={onRequestCode}
137
- disabled={requestButtonDisabled}
138
- >
139
- {requestButtonLabel}
140
- </InputUtilityButton>
141
- );
142
- }, [onRequestCode, requestButtonDisabled, requestButtonLabel]);
71
+ const actionButton = renderVerificationRequestButton({
72
+ onRequestCode,
73
+ requestButtonDisabled,
74
+ requestButtonLabel,
75
+ });
143
76
 
77
+ // 기본 전화 입력 필드; 인증 UI 노출 여부에 따라 래핑된다.
144
78
  const phoneField = (
145
- <Text
79
+ <InputBase
146
80
  {...restProps}
147
81
  ref={forwardedRef}
148
82
  type="tel"
@@ -154,28 +88,7 @@ const PhoneInput = forwardRef<HTMLInputElement, PhoneInputProps>(
154
88
  />
155
89
  );
156
90
 
157
- // 인증번호 UI가 비활성화된 경우에는 기존 PhoneInput DOM 구조를 그대로 유지한다.
158
- if (!codeVisible) {
159
- return phoneField;
160
- }
161
-
162
- return (
163
- <div className="phone-verification">
164
- {phoneField}
165
- <AuthCodeInput
166
- length={codeLength}
167
- label={codeLabel}
168
- helper={codeHelper}
169
- state={codeState}
170
- placeholder={codePlaceholder}
171
- countdownText={countdownText}
172
- countdownActionLabel={countdownActionLabel}
173
- onCountdownAction={onCountdownAction}
174
- countdownActionDisabled={countdownActionDisabled}
175
- onComplete={onCodeComplete}
176
- />
177
- </div>
178
- );
91
+ return <div className="phone-verification">{phoneField}</div>;
179
92
  },
180
93
  );
181
94
 
@@ -1,29 +1,28 @@
1
- import { forwardRef, useMemo } from "react";
2
- import type { InputProps } from "../../types";
3
- import { Text } from "./Base";
4
- import SearchIcon from "../../img/search.svg";
1
+ "use client";
5
2
 
6
- /**
7
- * SearchInput 전용 props. type search로 강제하고 나머지는 Text 입력과 동일하다.
8
- */
9
- export interface SearchInputProps extends Omit<InputProps, "type"> {}
3
+ import { forwardRef } from "react";
4
+ import type { SearchInputProps } from "../../types";
5
+ import InputBase from "../foundation/Input";
6
+ import SearchIcon from "../../img/search.svg";
10
7
 
11
8
  /**
12
- * SearchInput — 기본 Text 입력에 검색 아이콘 left 슬롯과 type="search"를 제공한다.
13
- * 다른 props(priority/size/helper 등)는 Text Input과 동일하다.
9
+ * SearchInput — 검색 아이콘(left slot)과 type="search"를 적용한 Text 입력.
10
+ * @component
11
+ * @param {SearchInputProps} props
12
+ * @property {ReactNode} [props.left] left 슬롯 override
13
+ * @property {ReactNode} [props.right] right 슬롯 override
14
14
  */
15
15
  const SearchInput = forwardRef<HTMLInputElement, SearchInputProps>(
16
16
  ({ left, ...restProps }, forwardedRef) => {
17
- const leftNode = useMemo(() => {
18
- if (left) {
19
- return left;
20
- }
21
- // 검색 input은 기본적으로 돋보기 아이콘을 left 슬롯에 노출한다.
22
- return <SearchIcon aria-hidden="true" />;
23
- }, [left]);
17
+ const resolvedLeft = left ?? <SearchIcon aria-hidden="true" />;
24
18
 
25
19
  return (
26
- <Text {...restProps} ref={forwardedRef} type="search" left={leftNode} />
20
+ <InputBase
21
+ {...restProps}
22
+ ref={forwardedRef}
23
+ type="search"
24
+ left={resolvedLeft}
25
+ />
27
26
  );
28
27
  },
29
28
  );
@@ -1,12 +1,15 @@
1
- export { Text } from "./Base";
2
- export { Text as Input } from "./Base";
3
- export { PasswordInput } from "./Password";
4
- export { PhoneInput } from "./Phone";
5
- export { EmailInput } from "./Email";
6
- export { SearchInput } from "./Search";
7
- export { AuthCodeInput } from "./AuthCode";
8
- export type { InputPasswordProps } from "./Password";
9
- export type { PhoneInputProps } from "./Phone";
10
- export type { EmailInputProps } from "./Email";
11
- export type { SearchInputProps } from "./Search";
12
- export type { AuthCodeInputProps } from "./AuthCode";
1
+ "use client";
2
+
3
+ import { PasswordInput } from "./Password";
4
+ import { PhoneInput } from "./Phone";
5
+ import { EmailInput } from "./Email";
6
+ import { SearchInput } from "./Search";
7
+ import { AuthCodeInput } from "./AuthCode";
8
+
9
+ export const InputText = {
10
+ Password: PasswordInput,
11
+ Phone: PhoneInput,
12
+ Email: EmailInput,
13
+ Search: SearchInput,
14
+ AuthCode: AuthCodeInput,
15
+ };
@@ -0,0 +1,110 @@
1
+ .input-calendar {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--spacing-gap-6, 20px);
5
+ width: 100%;
6
+
7
+ &[data-disabled="true"] {
8
+ opacity: 0.6;
9
+ }
10
+ }
11
+
12
+ .input-calendar-container {
13
+ background-color: var(--color-common-100, #fff);
14
+ border-radius: var(--theme-radius-large-3, 16px);
15
+ box-shadow:
16
+ 0 4px 20px rgba(0, 0, 0, 0.16),
17
+ 0 0 2px rgba(0, 0, 0, 0.12);
18
+ padding: var(--spacing-padding-10, 32px) var(--spacing-padding-6, 16px)
19
+ var(--spacing-padding-6, 16px);
20
+ display: flex;
21
+ flex-direction: column;
22
+ gap: var(--spacing-gap-5, 16px);
23
+ }
24
+
25
+ .input-calendar-root {
26
+ width: 100%;
27
+ }
28
+
29
+ .input-calendar-panel {
30
+ width: 100%;
31
+ border-radius: var(--theme-radius-large-1, 12px);
32
+ background-color: transparent;
33
+ }
34
+
35
+ .input-calendar-header {
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: space-between;
39
+ padding-inline: var(--spacing-padding-6, 16px);
40
+ margin-bottom: var(--spacing-gap-4, 12px);
41
+ }
42
+
43
+ .input-calendar-header-control {
44
+ width: 24px;
45
+ height: 24px;
46
+ display: inline-flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ border-radius: 999px;
50
+ background: transparent;
51
+ color: var(--color-label-strong, #18191b);
52
+ }
53
+
54
+ .input-calendar-header-level {
55
+ font-size: var(--font-heading-small-size, 19px);
56
+ font-weight: var(--font-heading-small-weight, 600);
57
+ }
58
+
59
+ .input-calendar-weekdays {
60
+ display: grid;
61
+ grid-template-columns: repeat(7, minmax(0, 1fr));
62
+ padding-bottom: var(--spacing-padding-2, 4px);
63
+ }
64
+
65
+ .input-calendar-weekday {
66
+ text-transform: none;
67
+ font-size: var(--font-heading-xxsmall-size, 15px);
68
+ color: var(--color-label-alternative, #afb1b6);
69
+ text-align: center;
70
+ }
71
+
72
+ .input-calendar-day {
73
+ width: 44px;
74
+ height: 44px;
75
+ border-radius: var(--theme-radius-large-1, 12px);
76
+ justify-self: center;
77
+ font-size: var(--font-body-medium-size, 17px);
78
+ color: var(--color-label-strong, #3d3f43);
79
+ }
80
+
81
+ .input-calendar-footer {
82
+ display: flex;
83
+ flex-direction: column;
84
+ gap: var(--spacing-gap-4, 12px);
85
+ width: 100%;
86
+ }
87
+
88
+ .input-calendar-footer-actions {
89
+ display: flex;
90
+ align-items: center;
91
+ justify-content: space-between;
92
+ gap: var(--spacing-gap-3, 8px);
93
+ }
94
+
95
+ .input-calendar-action-button {
96
+ width: 100%;
97
+ }
98
+
99
+ .input-calendar-footer-actions > :first-child {
100
+ flex: 1 1 auto;
101
+ }
102
+
103
+ .input-calendar-footer-actions > :last-child {
104
+ flex: 1 1 auto;
105
+ justify-content: flex-end;
106
+ }
107
+
108
+ .input-calendar-apply {
109
+ width: 100%;
110
+ }