@youcan/celeste 0.6.21 → 0.6.22

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 (32) hide show
  1. package/dist/celeste.css +346 -351
  2. package/dist/cjs/color-picker.js +1 -2
  3. package/dist/cjs/combobox-input.js +4 -8
  4. package/dist/cjs/combobox.js +29 -23
  5. package/dist/cjs/index.js +0 -3
  6. package/dist/cjs/text-input-affix.js +1 -2
  7. package/dist/cjs/text-input-button.js +2 -3
  8. package/dist/cjs/text-input.js +81 -4
  9. package/dist/components/combobox/combobox.d.ts +1 -0
  10. package/dist/components/dropdown/dropdown.d.ts +1 -1
  11. package/dist/components/text-input/index.d.ts +0 -2
  12. package/dist/components/text-input/text-input-affix.d.ts +1 -4
  13. package/dist/components/text-input/text-input.d.ts +6 -1
  14. package/dist/es/color-picker.js +1 -2
  15. package/dist/es/combobox-input.js +5 -9
  16. package/dist/es/combobox.js +30 -24
  17. package/dist/es/index.js +3 -6
  18. package/dist/es/text-input-affix.js +1 -2
  19. package/dist/es/text-input-button.js +2 -3
  20. package/dist/es/text-input.js +82 -5
  21. package/package.json +3 -3
  22. package/src/components/combobox/combobox-input.vue +3 -2
  23. package/src/components/combobox/combobox.vue +9 -4
  24. package/src/components/text-input/index.ts +0 -3
  25. package/src/components/text-input/stories/text-input.stories.ts +142 -45
  26. package/src/components/text-input/text-input-affix.vue +5 -12
  27. package/src/components/text-input/text-input-button.vue +8 -3
  28. package/src/components/text-input/text-input.vue +129 -64
  29. package/dist/cjs/text-input-icon.js +0 -29
  30. package/dist/components/text-input/text-input-icon.d.ts +0 -10
  31. package/dist/es/text-input-icon.js +0 -30
  32. package/src/components/text-input/text-input-icon.vue +0 -37
@@ -1,6 +1,9 @@
1
1
  <script setup lang="ts">
2
- import type { InputHTMLAttributes } from 'vue';
2
+ import { uid } from '@/utils/crypto';
3
3
  import clsx from 'clsx';
4
+ import { Primitive } from 'radix-vue';
5
+ import { computed, type InputHTMLAttributes } from 'vue';
6
+ import TextInputButton from './text-input-button.vue';
4
7
 
5
8
  const props = withDefaults(defineProps<TextInputProps>(), {
6
9
  type: 'text',
@@ -8,7 +11,17 @@ const props = withDefaults(defineProps<TextInputProps>(), {
8
11
  hasError: false,
9
12
  });
10
13
 
14
+ const id = computed(() => props.id || uid());
15
+
11
16
  const modelValue = defineModel<string | number>();
17
+
18
+ const showClearButton = computed(() => {
19
+ return props.type === 'search' && modelValue.value && String(modelValue.value).length > 0;
20
+ });
21
+
22
+ function clearInput() {
23
+ modelValue.value = '';
24
+ }
12
25
  </script>
13
26
 
14
27
  <script lang="ts">
@@ -21,24 +34,73 @@ export interface TextInputProps extends /* @vue-ignore */ InputHTMLAttributes {
21
34
 
22
35
  <template>
23
36
  <label
37
+ :for="id"
24
38
  :size="size"
25
39
  role="presentation"
26
40
  :has-error="hasError"
27
41
  :class="clsx('celeste-text-input-wrapper', props.class)"
28
42
  >
43
+ <Primitive as-child class="celeste-text-input-icon celeste-text-input-leading-icon">
44
+ <slot name="leadingIcon" />
45
+ </Primitive>
46
+
47
+ <Primitive as-child class="celeste-text-input-node celeste-text-input-leading-node">
48
+ <slot name="leadingNode" />
49
+ </Primitive>
50
+
51
+ <Primitive
52
+ inline
53
+ as-child
54
+ class="celeste-text-input-inline-node celeste-text-input-leading-inline-node"
55
+ >
56
+ <slot name="leadingInlineNode" />
57
+ </Primitive>
58
+
29
59
  <input
60
+ :id="id"
30
61
  v-model="modelValue"
31
62
  v-bind="$attrs"
32
63
  :type="type"
33
64
  class="celeste-text-input"
34
65
  >
35
- <slot />
66
+
67
+ <Primitive as-child class="celeste-text-input-icon celeste-text-input-trailing-icon">
68
+ <slot name="trailingIcon" />
69
+ </Primitive>
70
+
71
+ <Primitive as-child class="celeste-text-input-node celeste-text-input-trailing-node">
72
+
73
+ <slot name="trailingNode" />
74
+ </Primitive>
75
+
76
+ <Primitive
77
+ inline
78
+ as-child
79
+ class="celeste-text-input-inline-node celeste-text-input-trailing-inline-node"
80
+ >
81
+ <TextInputButton
82
+ v-if="showClearButton"
83
+ type="button"
84
+ aria-label="Clear search"
85
+ @click="clearInput"
86
+ >
87
+ <i class="i-celeste-close-line" />
88
+ </TextInputButton>
89
+ <slot v-else name="trailingInlineNode" />
90
+ </Primitive>
36
91
  </label>
37
92
  </template>
38
93
 
39
94
  <style scoped lang="scss">
95
+ /* stylelint-disable no-descending-specificity */
96
+
40
97
  .celeste-text-input-wrapper {
41
- --celeste-input-wrapper-border-color: var(--color-stroke-soft-200);
98
+ --celeste-text-input-border-color: var(--color-stroke-soft-200);
99
+ --celeste-text-input-drop-shadow: var(--shadow-regular-xs);
100
+ --celeste-text-input-icon-color: var(--color-text-soft-400);
101
+ --celeste-text-input-affix-color: var(--color-text-soft-400);
102
+ --celeste-text-input-placeholder-color: var(--color-text-soft-400);
103
+ --celeste-text-input-affix-background-color: var(--color-bg-white-0);
42
104
 
43
105
  display: flex;
44
106
  box-sizing: border-box;
@@ -46,13 +108,12 @@ export interface TextInputProps extends /* @vue-ignore */ InputHTMLAttributes {
46
108
  height: var(--input-height);
47
109
  padding-inline: calc(var(--input-padding) + var(--spacing-2)) var(--input-padding);
48
110
  transition: all var(--animation-fast) ease-out;
111
+ border: 1px solid var(--celeste-text-input-border-color);
49
112
  border-radius: var(--input-radius);
50
113
  outline: 2px solid transparent;
51
114
  outline-offset: 2px;
52
115
  background-color: var(--color-bg-white-0);
53
- box-shadow:
54
- inset 0 0 0 1px var(--celeste-input-wrapper-border-color),
55
- var(--shadow-regular-xs);
116
+ box-shadow: var(--celeste-text-input-drop-shadow);
56
117
  color: var(--color-text-strong-950);
57
118
  font: var(--paragraph-sm);
58
119
  gap: var(--input-gap);
@@ -79,7 +140,7 @@ export interface TextInputProps extends /* @vue-ignore */ InputHTMLAttributes {
79
140
  }
80
141
 
81
142
  &[has-error='true'] {
82
- --celeste-input-wrapper-border-color: var(--color-state-error-base);
143
+ --celeste-text-input-border-color: var(--color-state-error-base);
83
144
  }
84
145
 
85
146
  .celeste-text-input {
@@ -94,24 +155,53 @@ export interface TextInputProps extends /* @vue-ignore */ InputHTMLAttributes {
94
155
 
95
156
  &::placeholder {
96
157
  transition: color var(--animation-fast) ease-out;
97
- color: var(--color-text-soft-400);
158
+ color: var(--celeste-text-input-placeholder-color);
159
+ }
160
+
161
+ // Hide default webkit search cancel button
162
+ &[type='search'] {
163
+ &::-webkit-search-cancel-button {
164
+ display: none;
165
+ appearance: none;
166
+ }
167
+
168
+ &::-webkit-search-decoration {
169
+ display: none;
170
+ appearance: none;
171
+ }
98
172
  }
99
173
  }
100
174
 
175
+ &:has(.celeste-text-input-leading-node) {
176
+ padding-inline-start: 0;
177
+ }
178
+
179
+ &:has(.celeste-text-input-trailing-node) {
180
+ padding-inline-end: 0;
181
+ }
182
+
101
183
  &:has(.celeste-text-input:focus) {
102
- --celeste-input-wrapper-border-color: var(--color-stroke-strong-950);
184
+ --celeste-text-input-border-color: var(--color-stroke-strong-950);
185
+ --celeste-text-input-placeholder-color: var(--color-text-sub-600);
186
+ --celeste-text-input-icon-color: var(--color-text-sub-600);
187
+ --celeste-text-input-affix-color: var(--color-text-sub-600);
103
188
 
104
189
  outline-color: var(--color-stroke-soft-200);
105
190
 
106
191
  &[has-error='true'] {
107
- --celeste-input-wrapper-border-color: var(--color-state-error-base);
192
+ --celeste-text-input-border-color: var(--color-state-error-base);
108
193
 
109
194
  outline-color: var(--color-state-error-lighter);
110
195
  }
111
196
  }
112
197
 
113
198
  &:has(.celeste-text-input:disabled) {
114
- --celeste-input-wrapper-border-color: transparent;
199
+ --celeste-text-input-border-color: transparent;
200
+ --celeste-text-input-drop-shadow: none;
201
+ --celeste-text-input-affix-background-color: var(--color-bg-weak-50);
202
+ --celeste-text-input-affix-color: var(--color-text-disabled-300);
203
+ --celeste-text-input-placeholder-color: var(--color-text-disabled-300);
204
+ --celeste-text-input-icon-color: var(--color-text-disabled-300);
115
205
 
116
206
  background-color: var(--color-bg-weak-50);
117
207
  box-shadow: none;
@@ -122,73 +212,48 @@ export interface TextInputProps extends /* @vue-ignore */ InputHTMLAttributes {
122
212
  color: currentcolor;
123
213
  }
124
214
 
125
- &:deep(.celeste-text-input-icon) {
126
- color: var(--color-icon-disabled-300);
127
- }
128
-
129
- &:deep(.celeste-text-input-affix),
130
- &:deep(.celeste-text-input-button) {
131
- background-color: var(--color-bg-weak-50) !important;
215
+ .celeste-text-input-clear-button {
132
216
  color: var(--color-text-disabled-300);
217
+ pointer-events: none;
133
218
  }
134
219
  }
135
220
 
136
- &:has(.celeste-text-input-button, .celeste-text-input-affix[inline='false'][askbd='false']) {
137
- gap: var(--spacing-0);
138
- padding-inline-end: var(--spacing-0);
139
-
140
- &:has(.celeste-text-input-button[inline='false'], .celeste-text-input-affix[variant='suffix']) {
141
- .celeste-text-input {
142
- padding-inline-end: var(--input-padding);
143
- border-inline-end: 1px solid var(--celeste-input-wrapper-border-color);
144
- }
145
- }
146
-
147
- &:has(.celeste-text-input-affix[variant='prefix']) {
148
- padding-inline: var(--spacing-0) var(--input-padding);
149
-
150
- .celeste-text-input {
151
- padding-inline-start: var(--input-padding);
152
- border-inline-start: 1px solid var(--celeste-input-wrapper-border-color);
153
- }
221
+ &:has(.celeste-text-input:hover:not(:focus, :disabled)) {
222
+ &:not(:has(.celeste-text-input-node)) {
223
+ --celeste-text-input-border-color: transparent;
154
224
  }
155
225
 
156
- &:deep(.celeste-text-input-icon) {
157
- &[position='start'] {
158
- margin-inline-end: var(--input-gap);
159
- }
226
+ &:not(:has(.celeste-text-input-node:hover)) {
227
+ --celeste-text-input-icon-color: var(--color-text-sub-600);
228
+ --celeste-text-input-placeholder-color: var(--color-text-sub-600);
160
229
 
161
- &[position='end'] {
162
- margin-inline-start: var(--input-gap);
163
- }
230
+ background-color: var(--color-bg-weak-50);
164
231
  }
165
232
  }
166
233
 
167
- &:has(.celeste-text-input:hover:not(:focus, :disabled)) {
168
- /* stylelint-disable-next-line no-descending-specificity */
169
- &:not(:has(.celeste-text-input-button, .celeste-text-input-affix)) {
170
- --celeste-input-wrapper-border-color: transparent;
171
-
172
- background-color: var(--color-bg-weak-50);
173
- }
234
+ .celeste-text-input-icon {
235
+ flex-shrink: 0;
236
+ width: 20px;
237
+ height: 20px;
238
+ transition: all var(--animation-fast) ease-out;
239
+ color: var(--celeste-text-input-icon-color);
240
+ }
174
241
 
175
- &:has(.celeste-text-input-button:not(:hover), .celeste-text-input-affix:not(:hover)) {
176
- background-color: var(--color-bg-weak-50);
177
- }
242
+ :deep(.celeste-text-input-node) {
243
+ height: calc(var(--input-height) - var(--spacing-2));
244
+ border-radius: var(--input-radius) !important;
245
+ }
178
246
 
179
- &:not(:has(.celeste-text-input-button:hover)) {
180
- .celeste-text-input::placeholder {
181
- color: var(--color-text-sub-600);
182
- }
183
- }
247
+ :deep(.celeste-text-input-leading-node) {
248
+ border-end-end-radius: 0 !important;
249
+ border-start-end-radius: 0 !important;
250
+ border-inline-end: 1px solid var(--color-stroke-soft-200) !important;
184
251
  }
185
252
 
186
- &:has(.celeste-text-input:placeholder-shown:not(:disabled)) {
187
- /* stylelint-disable-next-line no-descending-specificity */
188
- &:deep(.celeste-text-input-icon),
189
- &:deep(.celeste-text-input-affix) {
190
- color: var(--color-text-soft-400);
191
- }
253
+ :deep(.celeste-text-input-trailing-node) {
254
+ border-inline-start: 1px solid var(--color-stroke-soft-200) !important;
255
+ border-end-start-radius: 0 !important;
256
+ border-start-start-radius: 0 !important;
192
257
  }
193
258
  }
194
259
  </style>
@@ -1,29 +0,0 @@
1
- "use strict";
2
- const Mo = require("vue");
3
- const useDelegatedProps = require("./use-delegated-props.js");
4
- const clsx = require("./chunks/clsx.js");
5
- ;/* empty css */
6
- const _pluginVue_exportHelper = require("./chunks/_plugin-vue_export-helper.js");
7
- const _sfc_main = /* @__PURE__ */ Mo.defineComponent({
8
- __name: "text-input-icon",
9
- props: {
10
- icon: {},
11
- position: { default: "start" },
12
- class: {}
13
- },
14
- setup(__props) {
15
- const props = __props;
16
- const delegatedProps = useDelegatedProps.useDelegatedProps(props, "class");
17
- return (_ctx, _cache) => {
18
- return Mo.openBlock(), Mo.createElementBlock("div", Mo.mergeProps(Mo.unref(delegatedProps), {
19
- class: Mo.unref(clsx.clsx)("celeste-text-input-icon", props.class)
20
- }), [
21
- Mo.createElementVNode("i", {
22
- class: Mo.normalizeClass(_ctx.icon)
23
- }, null, 2)
24
- ], 16);
25
- };
26
- }
27
- });
28
- const TextInputIcon = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-3b859b72"]]);
29
- module.exports = TextInputIcon;
@@ -1,10 +0,0 @@
1
- import { HTMLAttributes } from 'vue';
2
- type __VLS_Props = {
3
- icon: string;
4
- position?: 'start' | 'end';
5
- class?: HTMLAttributes['class'];
6
- };
7
- declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
8
- position: "start" | "end";
9
- }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
10
- export default _default;
@@ -1,30 +0,0 @@
1
- import { defineComponent, openBlock, createElementBlock, mergeProps, unref, createElementVNode, normalizeClass } from "vue";
2
- import { useDelegatedProps } from "./use-delegated-props.js";
3
- import { c as clsx } from "./chunks/clsx.js";
4
- /* empty css */
5
- import { _ as _export_sfc } from "./chunks/_plugin-vue_export-helper.js";
6
- const _sfc_main = /* @__PURE__ */ defineComponent({
7
- __name: "text-input-icon",
8
- props: {
9
- icon: {},
10
- position: { default: "start" },
11
- class: {}
12
- },
13
- setup(__props) {
14
- const props = __props;
15
- const delegatedProps = useDelegatedProps(props, "class");
16
- return (_ctx, _cache) => {
17
- return openBlock(), createElementBlock("div", mergeProps(unref(delegatedProps), {
18
- class: unref(clsx)("celeste-text-input-icon", props.class)
19
- }), [
20
- createElementVNode("i", {
21
- class: normalizeClass(_ctx.icon)
22
- }, null, 2)
23
- ], 16);
24
- };
25
- }
26
- });
27
- const TextInputIcon = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-3b859b72"]]);
28
- export {
29
- TextInputIcon as default
30
- };
@@ -1,37 +0,0 @@
1
- <script setup lang="ts">
2
- import type { HTMLAttributes } from 'vue';
3
- import { useDelegatedProps } from '@/composables/use-delegated-props';
4
- import clsx from 'clsx';
5
-
6
- const props = withDefaults(defineProps<{
7
- icon: string;
8
- position?: 'start' | 'end';
9
- class?: HTMLAttributes['class'];
10
- }>(), {
11
- position: 'start',
12
- });
13
- const delegatedProps = useDelegatedProps(props, 'class');
14
- </script>
15
-
16
- <template>
17
- <div v-bind="delegatedProps" :class="clsx('celeste-text-input-icon', props.class)">
18
- <i :class="icon" />
19
- </div>
20
- </template>
21
-
22
- <style scoped lang="scss">
23
- .celeste-text-input-icon {
24
- display: flex;
25
- align-items: center;
26
- color: var(--color-text-sub-600);
27
-
28
- &[position='start'] {
29
- order: -1;
30
- }
31
-
32
- & > i {
33
- width: 20px;
34
- height: 20px;
35
- }
36
- }
37
- </style>