@proj-airi/ui 0.4.23

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 (58) hide show
  1. package/LICENSE +21 -0
  2. package/build.config.ts +11 -0
  3. package/dist/components/Animations/TransitionVertical.vue +95 -0
  4. package/dist/components/Animations/index.d.ts +1 -0
  5. package/dist/components/Animations/index.mjs +1 -0
  6. package/dist/components/Form/Checkbox/Checkbox.vue +26 -0
  7. package/dist/components/Form/Checkbox/index.d.ts +1 -0
  8. package/dist/components/Form/Checkbox/index.mjs +1 -0
  9. package/dist/components/Form/Field/FieldCheckbox.vue +24 -0
  10. package/dist/components/Form/Field/FieldInput.vue +34 -0
  11. package/dist/components/Form/Field/FieldKeyValues.vue +54 -0
  12. package/dist/components/Form/Field/FieldRange.vue +37 -0
  13. package/dist/components/Form/Field/index.d.ts +4 -0
  14. package/dist/components/Form/Field/index.mjs +4 -0
  15. package/dist/components/Form/Input/Input.vue +20 -0
  16. package/dist/components/Form/Input/InputFile.vue +65 -0
  17. package/dist/components/Form/Input/InputKeyValue.vue +17 -0
  18. package/dist/components/Form/Input/index.d.ts +3 -0
  19. package/dist/components/Form/Input/index.mjs +3 -0
  20. package/dist/components/Form/Radio/Radio.vue +103 -0
  21. package/dist/components/Form/Radio/index.d.ts +1 -0
  22. package/dist/components/Form/Radio/index.mjs +1 -0
  23. package/dist/components/Form/Range/Range.vue +313 -0
  24. package/dist/components/Form/Range/index.d.ts +1 -0
  25. package/dist/components/Form/Range/index.mjs +1 -0
  26. package/dist/components/Form/Textarea/Basic.vue +32 -0
  27. package/dist/components/Form/Textarea/Textarea.vue +14 -0
  28. package/dist/components/Form/Textarea/index.d.ts +2 -0
  29. package/dist/components/Form/Textarea/index.mjs +2 -0
  30. package/dist/components/Form/index.d.ts +6 -0
  31. package/dist/components/Form/index.mjs +6 -0
  32. package/dist/index.d.ts +2 -0
  33. package/dist/index.mjs +2 -0
  34. package/package.json +46 -0
  35. package/src/components/Animations/TransitionVertical.vue +134 -0
  36. package/src/components/Animations/index.ts +1 -0
  37. package/src/components/Form/Checkbox/Checkbox.vue +27 -0
  38. package/src/components/Form/Checkbox/index.ts +1 -0
  39. package/src/components/Form/Field/FieldCheckbox.vue +26 -0
  40. package/src/components/Form/Field/FieldInput.vue +36 -0
  41. package/src/components/Form/Field/FieldKeyValues.vue +62 -0
  42. package/src/components/Form/Field/FieldRange.vue +39 -0
  43. package/src/components/Form/Field/index.ts +4 -0
  44. package/src/components/Form/Input/Input.vue +21 -0
  45. package/src/components/Form/Input/InputFile.vue +71 -0
  46. package/src/components/Form/Input/InputKeyValue.vue +19 -0
  47. package/src/components/Form/Input/index.ts +3 -0
  48. package/src/components/Form/Radio/Radio.vue +106 -0
  49. package/src/components/Form/Radio/index.ts +1 -0
  50. package/src/components/Form/Range/Range.vue +328 -0
  51. package/src/components/Form/Range/index.ts +1 -0
  52. package/src/components/Form/Textarea/Basic.vue +42 -0
  53. package/src/components/Form/Textarea/Textarea.vue +15 -0
  54. package/src/components/Form/Textarea/index.ts +2 -0
  55. package/src/components/Form/index.ts +6 -0
  56. package/src/index.ts +2 -0
  57. package/tsconfig.json +42 -0
  58. package/uno.config.ts +8 -0
@@ -0,0 +1,313 @@
1
+ <script setup>
2
+ import { computed, onMounted, ref } from "vue";
3
+ const props = defineProps({
4
+ min: { type: Number, required: false, default: 0 },
5
+ max: { type: Number, required: false, default: 100 },
6
+ step: { type: Number, required: false, default: 1 },
7
+ disabled: { type: Boolean, required: false, default: false },
8
+ thumbColor: { type: String, required: false, default: "#9090906e" },
9
+ trackColor: { type: String, required: false, default: "gray" },
10
+ trackValueColor: { type: String, required: false, default: "red" }
11
+ });
12
+ const modelValue = defineModel("modelValue", { type: Number, ...{ required: true } });
13
+ const scaledMin = computed(() => props.min * 1e4);
14
+ const scaledMax = computed(() => props.max * 1e4);
15
+ const scaledStep = computed(() => props.step * 1e4);
16
+ const sliderRef = ref();
17
+ const sliderValue = computed({
18
+ get: () => modelValue.value * 1e4,
19
+ set: (value) => {
20
+ modelValue.value = value / 1e4;
21
+ updateTrackColor();
22
+ }
23
+ });
24
+ onMounted(() => {
25
+ updateTrackColor();
26
+ });
27
+ function updateTrackColor() {
28
+ if (!sliderRef.value)
29
+ return;
30
+ sliderRef.value.style.setProperty("--value", sliderRef.value.value);
31
+ sliderRef.value.style.setProperty("--min", !sliderRef.value.min ? props.min.toString() : sliderRef.value.min);
32
+ sliderRef.value.style.setProperty("--max", !sliderRef.value.max ? props.max.toString() : sliderRef.value.max);
33
+ }
34
+ </script>
35
+
36
+ <template>
37
+ <input
38
+ ref="sliderRef"
39
+ v-model.number="sliderValue"
40
+ type="range"
41
+ :min="scaledMin"
42
+ :max="scaledMax"
43
+ :step="scaledStep"
44
+ class="slider-progress form_input-range"
45
+ @input="(e) => {
46
+ (e.target as HTMLInputElement).style.setProperty('--value', (e.target as HTMLInputElement).value)
47
+ }"
48
+ >
49
+ </template>
50
+
51
+ <style scoped>
52
+ /*generated with Input range slider CSS style generator (version 20211225)
53
+ https://toughengineer.github.io/demo/slider-styler*/
54
+ .form_input-range {
55
+ --height: 2em;
56
+
57
+ min-height: var(--height);
58
+ appearance: none;
59
+ background: transparent;
60
+ border-radius: 4px;
61
+ transition: background-color 0.2s ease;
62
+
63
+ --thumb-width: 4px;
64
+ --thumb-height: var(--height);
65
+ --thumb-box-shadow: 0 0 0px #e6e6e6;
66
+ --thumb-border: none;
67
+ --thumb-border-radius: 999px;
68
+ --thumb-background: oklch(80% var(--theme-colors-chroma-200) calc(var(--theme-colors-hue) + 0));
69
+ --thumb-background-hover: oklch(90% var(--theme-colors-chroma-200) calc(var(--theme-colors-hue) + 0));
70
+ --thumb-background-active: oklch(70% var(--theme-colors-chroma-200) calc(var(--theme-colors-hue) + 0));
71
+
72
+ --track-height: calc(var(--height) - var(--track-value-padding) * 2);
73
+ --track-box-shadow: none;
74
+ --track-border: solid 2px rgb(238, 238, 238);
75
+ --track-border-radius: 6px;
76
+ --track-background: rgb(238, 238, 238);
77
+ --track-background-hover: rgb(238, 238, 238);
78
+ --track-background-active: rgb(238, 238, 238);
79
+
80
+ --track-value-background: rgb(255, 255, 255);
81
+ --track-value-background-hover: rgb(255, 255, 255);
82
+ --track-value-background-active: rgb(255, 255, 255);
83
+ --track-value-padding: 2px;
84
+ }
85
+
86
+ .dark .form_input-range {
87
+ --thumb-background: oklch(70% var(--theme-colors-chroma-200) calc(var(--theme-colors-hue) + 0));
88
+ --thumb-background-hover: oklch(90% var(--theme-colors-chroma-200) calc(var(--theme-colors-hue) + 0));
89
+ --thumb-background-active: oklch(80% var(--theme-colors-chroma-200) calc(var(--theme-colors-hue) + 0));
90
+
91
+ --track-border: solid 2px rgb(44, 44, 44);
92
+ --track-background: rgb(44, 44, 44);
93
+ --track-background-hover: rgb(44, 44, 44);
94
+ --track-background-active: rgb(44, 44, 44);
95
+
96
+ --track-value-background: rgb(164, 164, 164);
97
+ --track-value-background-hover: rgb(164, 164, 164);
98
+ --track-value-background-active: rgb(164, 164, 164);
99
+ }
100
+
101
+ /*progress support*/
102
+ .form_input-range.slider-progress {
103
+ --range: calc(var(--max) - var(--min));
104
+ --ratio: calc((var(--value) - var(--min)) / var(--range));
105
+ --sx: calc(0.5 * 0em + var(--ratio) * (100% - 0em));
106
+ }
107
+
108
+ .form_input-range:focus {
109
+ outline: none;
110
+ }
111
+
112
+ /*webkit*/
113
+ .form_input-range::-webkit-slider-thumb {
114
+ appearance: none;
115
+ width: var(--thumb-width);
116
+ height: var(--thumb-height);
117
+ border-radius: var(--thumb-border-radius);
118
+ background: var(--thumb-background);
119
+ border: var(--thumb-border);
120
+ box-shadow: var(--thumb-box-shadow);
121
+ margin-top: calc(var(--track-height) * 0.5 - var(--thumb-height) * 0.5 - 2px);
122
+ margin-left: calc(0 - var(--track-value-padding));
123
+ cursor: col-resize;
124
+ transition:
125
+ background 0.2s ease-in-out,
126
+ box-shadow 0.2s ease-in-out,
127
+ border-color 0.2s ease-in-out,
128
+ transform 0.2s ease-in-out;
129
+ }
130
+
131
+ .form_input-range::-webkit-slider-runnable-track {
132
+ height: var(--track-height);
133
+ border: var(--track-border);
134
+ border-radius: var(--track-border-radius);
135
+ background: var(--track-background);
136
+ box-shadow: var(--track-box-shadow);
137
+ position: relative;
138
+ cursor: col-resize;
139
+ transition:
140
+ box-shadow 0.2s ease-in-out,
141
+ border-color 0.2s ease-in-out;
142
+ }
143
+
144
+ .form_input-range::-webkit-slider-thumb:hover {
145
+ background: var(--thumb-background-hover);
146
+ }
147
+
148
+ .form_input-range:hover::-webkit-slider-runnable-track {
149
+ background: var(--track-background-hover);
150
+ }
151
+
152
+ .form_input-range::-webkit-slider-thumb:active {
153
+ background: var(--thumb-background-active);
154
+ }
155
+
156
+ .form_input-range:active::-webkit-slider-runnable-track {
157
+ background: var(--track-background-active);
158
+ }
159
+
160
+ .form_input-range.slider-progress::-webkit-slider-runnable-track {
161
+ /* margin-left: var(--track-value-padding); */
162
+ margin-right: calc(0 - var(--track-value-padding));
163
+ background:
164
+ linear-gradient(var(--track-value-background), var(--track-value-background)) 0 / var(--sx) 100% no-repeat,
165
+ var(--track-background);
166
+ }
167
+
168
+ .form_input-range.slider-progress:hover::-webkit-slider-runnable-track {
169
+ background:
170
+ linear-gradient(var(--track-value-background-hover), var(--track-value-background-hover)) 0 / var(--sx) 100%
171
+ no-repeat,
172
+ var(--track-background-hover);
173
+ }
174
+
175
+ .form_input-range.slider-progress:active::-webkit-slider-runnable-track {
176
+ background:
177
+ linear-gradient(var(--track-value-background-active), var(--track-value-background-active)) 0 / var(--sx) 100%
178
+ no-repeat,
179
+ var(--track-background-active);
180
+ }
181
+
182
+ /*mozilla*/
183
+ .form_input-range::-moz-range-thumb {
184
+ width: var(--thumb-width);
185
+ height: var(--thumb-height);
186
+ border-radius: var(--thumb-border-radius);
187
+ background: var(--thumb-background);
188
+ border: none;
189
+ box-shadow: var(--thumb-box-shadow);
190
+ cursor: col-resize;
191
+ margin-left: calc(0 - var(--track-value-padding));
192
+ }
193
+
194
+ .form_input-range::-moz-range-track {
195
+ height: var(--track-height);
196
+ border: var(--track-border);
197
+ border-radius: var(--track-border-radius);
198
+ background: var(--track-background);
199
+ box-shadow: var(--track-box-shadow);
200
+ cursor: col-resize;
201
+ /* Trim left and right paddings of track */
202
+ width: calc(100% - var(--track-value-padding) * 2);
203
+ }
204
+
205
+ .form_input-range::-moz-range-thumb:hover {
206
+ background: var(--thumb-background-hover);
207
+ }
208
+
209
+ .form_input-range:hover::-moz-range-track {
210
+ background: var(--track-background-hover);
211
+ }
212
+
213
+ .form_input-range::-moz-range-thumb:active {
214
+ background: var(--thumb-background-active);
215
+ }
216
+
217
+ .form_input-range:active::-moz-range-track {
218
+ background: var(--track-background-active);
219
+ }
220
+
221
+ .form_input-range.slider-progress::-moz-range-track {
222
+ background:
223
+ linear-gradient(var(--track-value-background), var(--track-value-background)) 0 / var(--sx) 100% no-repeat,
224
+ var(--track-background);
225
+ }
226
+
227
+ .form_input-range.slider-progress:hover::-moz-range-track {
228
+ background:
229
+ linear-gradient(var(--track-value-background-hover), var(--track-value-background-hover)) 0 / var(--sx) 100%
230
+ no-repeat,
231
+ var(--track-background-hover);
232
+ }
233
+
234
+ .form_input-range.slider-progress:active::-moz-range-track {
235
+ background:
236
+ linear-gradient(var(--track-value-background-active), var(--track-value-background-active)) 0 / var(--sx) 100%
237
+ no-repeat,
238
+ var(--track-background-active);
239
+ }
240
+
241
+ /*ms*/
242
+ .form_input-range::-ms-fill-upper {
243
+ background: transparent;
244
+ border-color: transparent;
245
+ }
246
+
247
+ .form_input-range::-ms-fill-lower {
248
+ background: transparent;
249
+ border-color: transparent;
250
+ }
251
+
252
+ .form_input-range::-ms-thumb {
253
+ width: var(--thumb-width);
254
+ height: var(--thumb-height);
255
+ border-radius: var(--thumb-border-radius);
256
+ background: var(--thumb-background);
257
+ border: var(--thumb-border);
258
+ box-shadow: var(--thumb-box-shadow);
259
+ /** Center thumb */
260
+ margin-top: 0;
261
+ /** Shift left thumb */
262
+ margin-left: calc(0 - var(--track-value-padding));
263
+ box-sizing: border-box;
264
+ cursor: col-resize;
265
+ }
266
+
267
+ .form_input-range::-ms-track {
268
+ height: var(--track-height);
269
+ border-radius: var(--track-border-radius);
270
+ background: var(--track-background);
271
+ border: var(--track-border);
272
+ box-shadow: var(--track-box-shadow);
273
+ box-sizing: border-box;
274
+ cursor: col-resize;
275
+ }
276
+
277
+ .form_input-range::-ms-thumb:hover {
278
+ background: var(--thumb-background-hover);
279
+ }
280
+
281
+ .form_input-range:hover::-ms-track {
282
+ background: var(--track-background-hover);
283
+ }
284
+
285
+ .form_input-range::-ms-thumb:active {
286
+ background: var(--thumb-background-active);
287
+ }
288
+
289
+ .form_input-range:active::-ms-track {
290
+ background: var(--track-background-active);
291
+ }
292
+
293
+ .form_input-range.slider-progress::-ms-fill-lower {
294
+ height: var(--track-height);
295
+ border-radius: var(--track-border-radius) 0 0 var(--track-border-radius);
296
+ margin: 0;
297
+ background: var(--track-value-background);
298
+ border: none;
299
+ border-right-width: 0;
300
+ /** Shift left thumb */
301
+ margin-left: calc(var(--track-value-padding));
302
+ /** Shift right thumb */
303
+ margin-right: calc(0 - var(--track-value-padding));
304
+ }
305
+
306
+ .form_input-range.slider-progress:hover::-ms-fill-lower {
307
+ background: var(--track-value-background-hover);
308
+ }
309
+
310
+ .form_input-range.slider-progress:active::-ms-fill-lower {
311
+ background: var(--track-value-background-active);
312
+ }
313
+ </style>
@@ -0,0 +1 @@
1
+ export { default as Range } from './Range.vue';
@@ -0,0 +1 @@
1
+ export { default as Range } from "./Range.vue";
@@ -0,0 +1,32 @@
1
+ <script setup>
2
+ import { ref, watch } from "vue";
3
+ const events = defineEmits(["submit"]);
4
+ const input = defineModel({ type: String, ...{
5
+ default: ""
6
+ } });
7
+ const textareaRef = ref();
8
+ const textareaHeight = ref("auto");
9
+ function onKeyDown(e) {
10
+ if (e.code === "Enter" && !e.shiftKey) {
11
+ e.preventDefault();
12
+ events("submit", input.value);
13
+ }
14
+ }
15
+ watch(input, () => {
16
+ textareaHeight.value = "auto";
17
+ requestAnimationFrame(() => {
18
+ if (!textareaRef.value)
19
+ return;
20
+ textareaHeight.value = `${textareaRef.value.scrollHeight}px`;
21
+ });
22
+ }, { immediate: true });
23
+ </script>
24
+
25
+ <template>
26
+ <textarea
27
+ ref="textareaRef"
28
+ v-model="input"
29
+ :style="{ height: textareaHeight }"
30
+ @keydown="onKeyDown"
31
+ />
32
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup>
2
+ import BasicTextarea from "./Basic.vue";
3
+ const modelValue = defineModel({ type: String, ...{ default: "" } });
4
+ </script>
5
+
6
+ <template>
7
+ <BasicTextarea
8
+ v-model="modelValue"
9
+ border="neutral-100 dark:neutral-800 solid 2 focus:neutral-200 dark:focus:neutral-700"
10
+ transition="all duration-250 ease-in-out"
11
+ bg="neutral-100 dark:neutral-800 focus:neutral-50 dark:focus:neutral-900"
12
+ rounded-lg px-3 py-2 text-sm outline-none
13
+ />
14
+ </template>
@@ -0,0 +1,2 @@
1
+ export { default as BasicTextarea } from './Basic.vue';
2
+ export { default as Textarea } from './Textarea.vue';
@@ -0,0 +1,2 @@
1
+ export { default as BasicTextarea } from "./Basic.vue";
2
+ export { default as Textarea } from "./Textarea.vue";
@@ -0,0 +1,6 @@
1
+ export * from './Checkbox';
2
+ export * from './Field';
3
+ export * from './Input';
4
+ export * from './Radio';
5
+ export * from './Range';
6
+ export * from './Textarea';
@@ -0,0 +1,6 @@
1
+ export * from "./Checkbox/index.mjs";
2
+ export * from "./Field/index.mjs";
3
+ export * from "./Input/index.mjs";
4
+ export * from "./Radio/index.mjs";
5
+ export * from "./Range/index.mjs";
6
+ export * from "./Textarea/index.mjs";
@@ -0,0 +1,2 @@
1
+ export * from './components/Animations';
2
+ export * from './components/Form';
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./components/Animations/index.mjs";
2
+ export * from "./components/Form/index.mjs";
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@proj-airi/ui",
3
+ "type": "module",
4
+ "version": "0.4.23",
5
+ "description": "A collection of UI components that used by Project AIRI",
6
+ "author": {
7
+ "name": "Neko Ayaka",
8
+ "email": "neko@ayaka.moe",
9
+ "url": "https://github.com/nekomeowww"
10
+ },
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/moeru-ai/airi.git",
15
+ "directory": "packages/ui"
16
+ },
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.mjs"
21
+ },
22
+ "./components/animations": {
23
+ "types": "./dist/components/Animations/index.d.ts",
24
+ "import": "./dist/components/Animations/index.mjs"
25
+ },
26
+ "./components/form": {
27
+ "types": "./dist/components/Form/index.d.ts",
28
+ "import": "./dist/components/Form/index.mjs"
29
+ }
30
+ },
31
+ "dependencies": {
32
+ "@vueuse/core": "^13.1.0",
33
+ "reka-ui": "^2.2.0",
34
+ "vue": "^3.5.13"
35
+ },
36
+ "devDependencies": {
37
+ "@vue-macros/volar": "3.0.0-beta.8",
38
+ "vue-tsc": "^3.0.0-alpha.4"
39
+ },
40
+ "scripts": {
41
+ "dev": "pnpm run stub",
42
+ "stub": "unbuild --stub",
43
+ "build": "unbuild",
44
+ "typecheck": "vue-tsc --noEmit"
45
+ }
46
+ }
@@ -0,0 +1,134 @@
1
+ <script setup lang="ts">
2
+ // From: https://stackoverflow.com/a/71426342/22392721
3
+ interface Props {
4
+ duration?: number
5
+ easingEnter?: string
6
+ easingLeave?: string
7
+ opacityClosed?: number
8
+ opacityOpened?: number
9
+ }
10
+
11
+ const props = withDefaults(defineProps<Props>(), {
12
+ duration: 250,
13
+ easingEnter: 'ease-in-out',
14
+ easingLeave: 'ease-in-out',
15
+ opacityClosed: 0,
16
+ opacityOpened: 1,
17
+ })
18
+
19
+ const closed = '0px'
20
+
21
+ interface initialStyle {
22
+ height: string
23
+ width: string
24
+ position: string
25
+ visibility: string
26
+ overflow: string
27
+ paddingTop: string
28
+ paddingBottom: string
29
+ borderTopWidth: string
30
+ borderBottomWidth: string
31
+ marginTop: string
32
+ marginBottom: string
33
+ }
34
+
35
+ function getElementStyle(element: HTMLElement) {
36
+ return {
37
+ height: element.style.height,
38
+ width: element.style.width,
39
+ position: element.style.position,
40
+ visibility: element.style.visibility,
41
+ overflow: element.style.overflow,
42
+ paddingTop: element.style.paddingTop,
43
+ paddingBottom: element.style.paddingBottom,
44
+ borderTopWidth: element.style.borderTopWidth,
45
+ borderBottomWidth: element.style.borderBottomWidth,
46
+ marginTop: element.style.marginTop,
47
+ marginBottom: element.style.marginBottom,
48
+ }
49
+ }
50
+
51
+ function prepareElement(element: HTMLElement, initialStyle: initialStyle) {
52
+ const { width } = getComputedStyle(element)
53
+ element.style.width = width
54
+ element.style.position = 'absolute'
55
+ element.style.visibility = 'hidden'
56
+ element.style.height = ''
57
+ const { height } = getComputedStyle(element)
58
+ element.style.width = initialStyle.width
59
+ element.style.position = initialStyle.position
60
+ element.style.visibility = initialStyle.visibility
61
+ element.style.height = closed
62
+ element.style.overflow = 'hidden'
63
+ return initialStyle.height && initialStyle.height !== closed
64
+ ? initialStyle.height
65
+ : height
66
+ }
67
+
68
+ function animateTransition(
69
+ element: HTMLElement,
70
+ initialStyle: initialStyle,
71
+ done: () => void,
72
+ keyframes: Keyframe[] | PropertyIndexedKeyframes | null,
73
+ options?: number | KeyframeAnimationOptions,
74
+ ) {
75
+ const animation = element.animate(keyframes, options)
76
+ // Set height to 'auto' to restore it after animation
77
+ element.style.height = initialStyle.height
78
+ animation.onfinish = () => {
79
+ element.style.overflow = initialStyle.overflow
80
+ done()
81
+ }
82
+ }
83
+
84
+ function getEnterKeyframes(height: string, initialStyle: initialStyle) {
85
+ return [
86
+ {
87
+ height: closed,
88
+ opacity: props.opacityClosed,
89
+ paddingTop: closed,
90
+ paddingBottom: closed,
91
+ borderTopWidth: closed,
92
+ borderBottomWidth: closed,
93
+ marginTop: closed,
94
+ marginBottom: closed,
95
+ },
96
+ {
97
+ height,
98
+ opacity: props.opacityOpened,
99
+ paddingTop: initialStyle.paddingTop,
100
+ paddingBottom: initialStyle.paddingBottom,
101
+ borderTopWidth: initialStyle.borderTopWidth,
102
+ borderBottomWidth: initialStyle.borderBottomWidth,
103
+ marginTop: initialStyle.marginTop,
104
+ marginBottom: initialStyle.marginBottom,
105
+ },
106
+ ]
107
+ }
108
+
109
+ function enterTransition(element: Element, done: () => void) {
110
+ const HTMLElement = element as HTMLElement
111
+ const initialStyle = getElementStyle(HTMLElement)
112
+ const height = prepareElement(HTMLElement, initialStyle)
113
+ const keyframes = getEnterKeyframes(height, initialStyle)
114
+ const options = { duration: props.duration, easing: props.easingEnter }
115
+ animateTransition(HTMLElement, initialStyle, done, keyframes, options)
116
+ }
117
+
118
+ function leaveTransition(element: Element, done: () => void) {
119
+ const HTMLElement = element as HTMLElement
120
+ const initialStyle = getElementStyle(HTMLElement)
121
+ const { height } = getComputedStyle(HTMLElement)
122
+ HTMLElement.style.height = height
123
+ HTMLElement.style.overflow = 'hidden'
124
+ const keyframes = getEnterKeyframes(height, initialStyle).reverse()
125
+ const options = { duration: props.duration, easing: props.easingLeave }
126
+ animateTransition(HTMLElement, initialStyle, done, keyframes, options)
127
+ }
128
+ </script>
129
+
130
+ <template>
131
+ <Transition :css="false" @enter="enterTransition" @leave="leaveTransition">
132
+ <slot />
133
+ </Transition>
134
+ </template>
@@ -0,0 +1 @@
1
+ export { default as TransitionVertical } from './TransitionVertical.vue'
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import { SwitchRoot, SwitchThumb } from 'reka-ui'
3
+
4
+ const modelValue = defineModel<boolean>({ required: true })
5
+ </script>
6
+
7
+ <template>
8
+ <SwitchRoot
9
+ v-model="modelValue"
10
+ transition="background duration-250 ease-in-out"
11
+ outline="focus-within:none"
12
+ flex="~"
13
+ border="neutral-300 dark:neutral-700 data-[state=checked]:primary-200 data-[state=unchecked]:neutral-300 focus-within:neutral-800"
14
+ bg="data-[state=checked]:primary-400 data-[state=unchecked]:neutral-300 data-[state=checked]:dark:primary-400/80 dark:data-[state=unchecked]:neutral-800"
15
+ relative h-7 w="12.5" rounded-full
16
+ shadow="sm focus-within:shadow-neutral-800 focus-within:[0_0_0_1px] "
17
+ >
18
+ <SwitchThumb
19
+ my-auto size-6
20
+ flex items-center justify-center
21
+ translate-x="0.5 data-[state=checked]:full"
22
+ rounded-full bg-white text-xs shadow-xl
23
+ transition="transform duration-250 ease-in-out"
24
+ will-change-transform
25
+ />
26
+ </SwitchRoot>
27
+ </template>
@@ -0,0 +1 @@
1
+ export { default as Checkbox } from './Checkbox.vue'
@@ -0,0 +1,26 @@
1
+ <script setup lang="ts">
2
+ import Checkbox from '../Checkbox/Checkbox.vue'
3
+
4
+ const props = defineProps<{
5
+ label?: string
6
+ description?: string
7
+ }>()
8
+
9
+ const modelValue = defineModel<boolean>({ required: true })
10
+ </script>
11
+
12
+ <template>
13
+ <label flex="~ col gap-4">
14
+ <div flex="~ row" items-center gap-2>
15
+ <div flex="1">
16
+ <div class="flex items-center gap-1 text-sm font-medium">
17
+ {{ props.label }}
18
+ </div>
19
+ <div class="text-xs text-neutral-500 dark:text-neutral-400">
20
+ {{ props.description }}
21
+ </div>
22
+ </div>
23
+ <Checkbox v-model="modelValue" />
24
+ </div>
25
+ </label>
26
+ </template>
@@ -0,0 +1,36 @@
1
+ <script setup lang="ts">
2
+ import Input from '../Input/Input.vue'
3
+
4
+ const props = defineProps<{
5
+ label?: string
6
+ description?: string
7
+ placeholder?: string
8
+ required?: boolean
9
+ type?: string
10
+ inputClass?: string
11
+ }>()
12
+
13
+ const modelValue = defineModel<string>({ required: true })
14
+ </script>
15
+
16
+ <template>
17
+ <div max-w-full>
18
+ <label flex="~ col gap-4">
19
+ <div>
20
+ <div class="flex items-center gap-1 text-sm font-medium">
21
+ {{ props.label }}
22
+ <span v-if="props.required !== false" class="text-red-500">*</span>
23
+ </div>
24
+ <div class="text-xs text-neutral-500 dark:text-neutral-400" text-nowrap>
25
+ {{ props.description }}
26
+ </div>
27
+ </div>
28
+ <Input
29
+ v-model="modelValue"
30
+ :type="props.type"
31
+ :placeholder="props.placeholder"
32
+ :class="props.inputClass"
33
+ />
34
+ </label>
35
+ </div>
36
+ </template>