@youcan/celeste 0.6.20 → 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 -357
  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 -19
  27. package/src/components/text-input/text-input-button.vue +8 -3
  28. package/src/components/text-input/text-input.vue +133 -61
  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,35 +34,86 @@ 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 {
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);
104
+
41
105
  display: flex;
42
106
  box-sizing: border-box;
43
107
  align-items: center;
44
108
  height: var(--input-height);
45
109
  padding-inline: calc(var(--input-padding) + var(--spacing-2)) var(--input-padding);
46
110
  transition: all var(--animation-fast) ease-out;
47
- border: 1px solid var(--color-stroke-soft-200);
111
+ border: 1px solid var(--celeste-text-input-border-color);
48
112
  border-radius: var(--input-radius);
49
113
  outline: 2px solid transparent;
50
114
  outline-offset: 2px;
51
115
  background-color: var(--color-bg-white-0);
52
- box-shadow: var(--shadow-regular-xs);
116
+ box-shadow: var(--celeste-text-input-drop-shadow);
53
117
  color: var(--color-text-strong-950);
54
118
  font: var(--paragraph-sm);
55
119
  gap: var(--input-gap);
@@ -76,7 +140,7 @@ export interface TextInputProps extends /* @vue-ignore */ InputHTMLAttributes {
76
140
  }
77
141
 
78
142
  &[has-error='true'] {
79
- border-color: var(--color-state-error-base);
143
+ --celeste-text-input-border-color: var(--color-state-error-base);
80
144
  }
81
145
 
82
146
  .celeste-text-input {
@@ -91,22 +155,54 @@ export interface TextInputProps extends /* @vue-ignore */ InputHTMLAttributes {
91
155
 
92
156
  &::placeholder {
93
157
  transition: color var(--animation-fast) ease-out;
94
- 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
+ }
95
172
  }
96
173
  }
97
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
+
98
183
  &:has(.celeste-text-input:focus) {
99
- 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);
188
+
100
189
  outline-color: var(--color-stroke-soft-200);
101
190
 
102
191
  &[has-error='true'] {
103
- border-color: var(--color-state-error-base);
192
+ --celeste-text-input-border-color: var(--color-state-error-base);
193
+
104
194
  outline-color: var(--color-state-error-lighter);
105
195
  }
106
196
  }
107
197
 
108
198
  &:has(.celeste-text-input:disabled) {
109
- 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);
205
+
110
206
  background-color: var(--color-bg-weak-50);
111
207
  box-shadow: none;
112
208
  color: var(--color-text-disabled-300);
@@ -116,72 +212,48 @@ export interface TextInputProps extends /* @vue-ignore */ InputHTMLAttributes {
116
212
  color: currentcolor;
117
213
  }
118
214
 
119
- &:deep(.celeste-text-input-icon) {
120
- color: var(--color-icon-disabled-300);
121
- }
122
-
123
- &:deep(.celeste-text-input-affix),
124
- &:deep(.celeste-text-input-button) {
125
- background-color: var(--color-bg-weak-50) !important;
215
+ .celeste-text-input-clear-button {
126
216
  color: var(--color-text-disabled-300);
217
+ pointer-events: none;
127
218
  }
128
219
  }
129
220
 
130
- &:has(.celeste-text-input-button, .celeste-text-input-affix[inline='false'][askbd='false']) {
131
- gap: var(--spacing-0);
132
- padding-inline-end: var(--spacing-0);
133
-
134
- &:has(.celeste-text-input-button[inline='false'], .celeste-text-input-affix[variant='suffix']) {
135
- .celeste-text-input {
136
- padding-inline-end: var(--input-padding);
137
- border-inline-end: 1px solid var(--color-stroke-soft-200);
138
- }
139
- }
140
-
141
- &:has(.celeste-text-input-affix[variant='prefix']) {
142
- padding-inline: var(--spacing-0) var(--input-padding);
143
-
144
- .celeste-text-input {
145
- padding-inline-start: var(--input-padding);
146
- border-inline-start: 1px solid var(--color-stroke-soft-200);
147
- }
221
+ &:has(.celeste-text-input:hover:not(:focus, :disabled)) {
222
+ &:not(:has(.celeste-text-input-node)) {
223
+ --celeste-text-input-border-color: transparent;
148
224
  }
149
225
 
150
- &:deep(.celeste-text-input-icon) {
151
- &[position='start'] {
152
- margin-inline-end: var(--input-gap);
153
- }
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);
154
229
 
155
- &[position='end'] {
156
- margin-inline-start: var(--input-gap);
157
- }
230
+ background-color: var(--color-bg-weak-50);
158
231
  }
159
232
  }
160
233
 
161
- &:has(.celeste-text-input:hover:not(:focus, :disabled)) {
162
- /* stylelint-disable-next-line no-descending-specificity */
163
- &:not(:has(.celeste-text-input-button, .celeste-text-input-affix)) {
164
- border-color: transparent;
165
- background-color: var(--color-bg-weak-50);
166
- }
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
+ }
167
241
 
168
- &:has(.celeste-text-input-button:not(:hover), .celeste-text-input-affix:not(:hover)) {
169
- background-color: var(--color-bg-weak-50);
170
- }
242
+ :deep(.celeste-text-input-node) {
243
+ height: calc(var(--input-height) - var(--spacing-2));
244
+ border-radius: var(--input-radius) !important;
245
+ }
171
246
 
172
- &:not(:has(.celeste-text-input-button:hover)) {
173
- .celeste-text-input::placeholder {
174
- color: var(--color-text-sub-600);
175
- }
176
- }
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;
177
251
  }
178
252
 
179
- &:has(.celeste-text-input:placeholder-shown:not(:disabled)) {
180
- /* stylelint-disable-next-line no-descending-specificity */
181
- &:deep(.celeste-text-input-icon),
182
- &:deep(.celeste-text-input-affix) {
183
- color: var(--color-text-soft-400);
184
- }
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;
185
257
  }
186
258
  }
187
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>