@youcan/celeste 0.6.15 → 0.6.17

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 (88) hide show
  1. package/dist/celeste.css +597 -198
  2. package/dist/cjs/chunks/combobox-anchor.js +31 -0
  3. package/dist/cjs/chunks/combobox-root.js +38 -0
  4. package/dist/cjs/chunks/index.js +17 -0
  5. package/dist/cjs/combobox-anchor.js +3 -0
  6. package/dist/cjs/combobox-empty.js +32 -0
  7. package/dist/cjs/combobox-group.js +42 -0
  8. package/dist/cjs/combobox-input.js +67 -0
  9. package/dist/cjs/combobox-item.js +109 -0
  10. package/dist/cjs/combobox-list.js +62 -0
  11. package/dist/cjs/combobox-root.js +3 -0
  12. package/dist/cjs/combobox-separator.js +32 -0
  13. package/dist/cjs/combobox-trigger.js +46 -0
  14. package/dist/cjs/combobox.js +190 -0
  15. package/dist/cjs/dropdown.js +10 -3
  16. package/dist/cjs/index.js +30 -0
  17. package/dist/cjs/text-input-icon.js +2 -2
  18. package/dist/components/combobox/combobox-anchor.d.ts +22 -0
  19. package/dist/components/combobox/combobox-empty.d.ts +22 -0
  20. package/dist/components/combobox/combobox-group.d.ts +23 -0
  21. package/dist/components/combobox/combobox-input.d.ts +17 -0
  22. package/dist/components/combobox/combobox-item.d.ts +31 -0
  23. package/dist/components/combobox/combobox-list.d.ts +36 -0
  24. package/dist/components/combobox/combobox-root.d.ts +29 -0
  25. package/dist/components/combobox/combobox-separator.d.ts +22 -0
  26. package/dist/components/combobox/combobox-trigger.d.ts +20 -0
  27. package/dist/components/combobox/combobox.d.ts +40 -0
  28. package/dist/components/combobox/index.d.ts +20 -0
  29. package/dist/components/dropdown/dropdown.d.ts +5 -1
  30. package/dist/components/dropdown-menu/dropdown-menu-sub-content.d.ts +4 -4
  31. package/dist/components/index.d.ts +1 -0
  32. package/dist/components/modal/modal-content.d.ts +2 -2
  33. package/dist/components/popover/popover-content.d.ts +2 -2
  34. package/dist/es/chunks/combobox-anchor.js +32 -0
  35. package/dist/es/chunks/combobox-root.js +39 -0
  36. package/dist/es/chunks/index.js +59 -42
  37. package/dist/es/combobox-anchor.js +4 -0
  38. package/dist/es/combobox-empty.js +33 -0
  39. package/dist/es/combobox-group.js +43 -0
  40. package/dist/es/combobox-input.js +68 -0
  41. package/dist/es/combobox-item.js +110 -0
  42. package/dist/es/combobox-list.js +63 -0
  43. package/dist/es/combobox-root.js +4 -0
  44. package/dist/es/combobox-separator.js +33 -0
  45. package/dist/es/combobox-trigger.js +47 -0
  46. package/dist/es/combobox.js +191 -0
  47. package/dist/es/command-group.js +1 -1
  48. package/dist/es/command-input.js +1 -1
  49. package/dist/es/command-separator.js +1 -1
  50. package/dist/es/dropdown-menu-group.js +1 -1
  51. package/dist/es/dropdown-menu-item.js +1 -1
  52. package/dist/es/dropdown-menu-label.js +1 -1
  53. package/dist/es/dropdown-menu-separator.js +1 -1
  54. package/dist/es/dropdown-menu-trigger.js +1 -1
  55. package/dist/es/dropdown-menu.js +1 -1
  56. package/dist/es/dropdown.js +11 -4
  57. package/dist/es/index.js +75 -45
  58. package/dist/es/label.js +1 -1
  59. package/dist/es/modal-content.js +1 -1
  60. package/dist/es/modal-header.js +1 -1
  61. package/dist/es/popover-content.js +1 -1
  62. package/dist/es/popover-trigger.js +1 -1
  63. package/dist/es/segmented-control-item.js +1 -1
  64. package/dist/es/segmented-control.js +1 -1
  65. package/dist/es/select-content.js +1 -1
  66. package/dist/es/select-item.js +1 -1
  67. package/dist/es/select-trigger.js +1 -1
  68. package/dist/es/select-value.js +1 -1
  69. package/dist/es/tab-menu-content.js +1 -1
  70. package/dist/es/tab-menu-item.js +1 -1
  71. package/dist/es/tab-menu-list.js +1 -1
  72. package/dist/es/text-input-icon.js +2 -2
  73. package/dist/es/tooltip.js +1 -1
  74. package/package.json +3 -3
  75. package/src/components/combobox/combobox-anchor.vue +25 -0
  76. package/src/components/combobox/combobox-empty.vue +30 -0
  77. package/src/components/combobox/combobox-group.vue +42 -0
  78. package/src/components/combobox/combobox-input.vue +64 -0
  79. package/src/components/combobox/combobox-item.vue +196 -0
  80. package/src/components/combobox/combobox-list.vue +100 -0
  81. package/src/components/combobox/combobox-root.vue +14 -0
  82. package/src/components/combobox/combobox-separator.vue +31 -0
  83. package/src/components/combobox/combobox-trigger.vue +249 -0
  84. package/src/components/combobox/combobox.vue +235 -0
  85. package/src/components/combobox/index.ts +29 -0
  86. package/src/components/combobox/stories/combobox.stories.ts +242 -0
  87. package/src/components/dropdown/dropdown.vue +33 -2
  88. package/src/components/index.ts +1 -0
@@ -0,0 +1,249 @@
1
+ <script setup lang="ts">
2
+ import type { ComboboxTriggerProps } from 'radix-vue';
3
+ import clsx from 'clsx';
4
+ import { ComboboxTrigger, useForwardProps } from 'radix-vue';
5
+ import { computed, type HTMLAttributes } from 'vue';
6
+
7
+ const props = withDefaults(defineProps<CustomComboboxTriggerProps>(), {
8
+ type: 'normal',
9
+ });
10
+
11
+ const delegatedProps = computed(() => {
12
+ const { class: _, ...delegated } = props;
13
+
14
+ return delegated;
15
+ });
16
+
17
+ const forwarded = useForwardProps(delegatedProps);
18
+ </script>
19
+
20
+ <script lang="ts">
21
+ export interface CustomComboboxTriggerProps extends ComboboxTriggerProps {
22
+ class?: HTMLAttributes['class'];
23
+ size?: 'xs' | 'sm' | 'md';
24
+ filled?: boolean;
25
+ type?: 'normal' | 'compact' | 'inline' | 'compact-input';
26
+ error?: boolean;
27
+ }
28
+ </script>
29
+
30
+ <template>
31
+ <ComboboxTrigger
32
+ v-bind="forwarded"
33
+ tabindex="0"
34
+ :class="clsx(
35
+ 'celeste-dropdown-anchor-trigger',
36
+ `celeste-dropdown-anchor-trigger-size-${props.size}`,
37
+ `celeste-dropdown-anchor-trigger-type-${props.type}`,
38
+ { 'celeste-dropdown-anchor-trigger-error': props.error },
39
+ { 'celeste-dropdown-anchor-trigger-filled': filled },
40
+ props.class,
41
+ )"
42
+ >
43
+ <slot />
44
+ </ComboboxTrigger>
45
+ </template>
46
+
47
+ <style lang="scss" scoped>
48
+ @use 'sass:map';
49
+
50
+ @mixin transition-default {
51
+ transition-property: background-color, transform, opacity;
52
+ transition-duration: var(--animation-fast);
53
+ transition-timing-function: ease-out;
54
+ }
55
+
56
+ .celeste-dropdown-anchor-trigger {
57
+ @include transition-default;
58
+
59
+ display: flex;
60
+ align-items: center;
61
+ border: 1px solid var(--color-stroke-soft-200);
62
+ background-color: var(--color-bg-white-0);
63
+ box-shadow: var(--shadow-regular-xs);
64
+ gap: var(--spacing-8);
65
+ cursor: pointer;
66
+
67
+ :deep(i) {
68
+ width: 20px;
69
+ height: 20px;
70
+ color: var(--color-icon-soft-400);
71
+ }
72
+
73
+ &:hover {
74
+ background: var(--color-bg-weak-50);
75
+ }
76
+
77
+ &:focus,
78
+ &:focus-visible,
79
+ &:focus-within {
80
+ outline: none;
81
+ box-shadow: var(--shadow-buttons-important-focus);
82
+ }
83
+
84
+ .celeste-dropdown-anchor-trigger-prefix {
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+
89
+ &-selected {
90
+ display: flex;
91
+ align-items: center;
92
+ justify-content: center;
93
+ }
94
+ }
95
+
96
+ .celeste-dropdown-input {
97
+ display: flex;
98
+ flex: 1 0 0;
99
+ align-items: center;
100
+ justify-content: space-between;
101
+ background: inherit;
102
+ color: var(--color-text-sub-600);
103
+ font: var(--paragraph-sm);
104
+ cursor: pointer;
105
+ gap: var(--spacing-8);
106
+ }
107
+
108
+ .celeste-dropdown-trigger {
109
+ @include transition-default;
110
+
111
+ display: flex;
112
+ place-items: center center;
113
+ border: none;
114
+ background: none;
115
+ color: var(--color-icon-soft-400);
116
+ cursor: pointer;
117
+ }
118
+
119
+ &[data-state='open']:not([data-disabled]) {
120
+ :deep(.celeste-dropdown-trigger) {
121
+ transform: rotate(180deg);
122
+ }
123
+ }
124
+
125
+ &-error:not(.celeste-dropdown-anchor-trigger-type-compact) {
126
+ border: 1px solid var(--color-state-error-base);
127
+ }
128
+
129
+ &[data-disabled] {
130
+ background: var(--color-bg-weak-50);
131
+ color: var(--color-text-disabled-300);
132
+ cursor: not-allowed;
133
+
134
+ .celeste-dropdown-input {
135
+ color: var(--color-text-disabled-300);
136
+ cursor: not-allowed;
137
+ }
138
+
139
+ &:deep(i),
140
+ .celeste-dropdown-trigger {
141
+ color: var(--color-icon-disabled-300);
142
+ cursor: not-allowed;
143
+ }
144
+ }
145
+
146
+ &[data-state='open']:not(
147
+ [data-disabled],
148
+ .celeste-dropdown-anchor-trigger-type-compact,
149
+ .celeste-dropdown-anchor-trigger-type-compact-input
150
+ ) {
151
+ border: 1px solid var(--color-stroke-strong-950);
152
+ box-shadow: var(--shadow-buttons-important-focus);
153
+ color: var(--color-text-strong-950);
154
+
155
+ .celeste-dropdown-input {
156
+ color: var(--color-text-strong-950);
157
+ }
158
+
159
+ i {
160
+ color: var(--color-icon-strong-950);
161
+ }
162
+ }
163
+
164
+ &-filled {
165
+ color: var(--color-text-strong-950);
166
+
167
+ :deep(.celeste-dropdown-input) {
168
+ color: var(--color-text-strong-950);
169
+ }
170
+ }
171
+
172
+ &.celeste-dropdown-anchor-trigger-type-compact {
173
+ width: fit-content;
174
+ border: none;
175
+ background: transparent;
176
+ box-shadow: none;
177
+
178
+ &:deep(.celeste-dropdown-input) {
179
+ flex: inherit;
180
+ }
181
+
182
+ &:hover:not([data-disabled]),
183
+ &[data-state='open']:not([data-disabled]) {
184
+ .celeste-dropdown-input {
185
+ color: var(--color-text-strong-950);
186
+ }
187
+
188
+ &:deep(i) {
189
+ color: var(--color-icon-strong-950);
190
+ }
191
+ }
192
+ }
193
+
194
+ &.celeste-dropdown-anchor-trigger-type-compact-input {
195
+ width: fit-content;
196
+ border: none;
197
+ border-radius: var(--radius-0);
198
+ box-shadow: none;
199
+
200
+ &:deep(.celeste-dropdown-input) {
201
+ flex: inherit;
202
+ }
203
+
204
+ &[data-state='open'] {
205
+ box-shadow: none;
206
+ }
207
+ }
208
+
209
+ &.celeste-dropdown-anchor-trigger-type-inline {
210
+ width: fit-content;
211
+ gap: var(--spacing-4);
212
+
213
+ &:deep(.celeste-dropdown-input) {
214
+ flex: inherit;
215
+ }
216
+ }
217
+
218
+ &.celeste-dropdown-anchor-trigger-type-normal {
219
+ width: 100%;
220
+ min-width: 300px;
221
+ }
222
+
223
+ $sizes-map: (
224
+ 'xs': (
225
+ 'padding': var(--spacing-6),
226
+ 'border-radius': var(--radius-8),
227
+ 'height': 32px,
228
+ ),
229
+ 'sm': (
230
+ 'padding': var(--spacing-8),
231
+ 'border-radius': var(--radius-8),
232
+ 'height': 36px,
233
+ ),
234
+ 'md': (
235
+ 'padding': var(--spacing-10),
236
+ 'border-radius': var(--radius-10),
237
+ 'height': 40px,
238
+ ),
239
+ );
240
+
241
+ @each $size, $values in $sizes-map {
242
+ &-size-#{$size} {
243
+ height: map.get($values, 'height');
244
+ padding: map.get($values, 'padding');
245
+ border-radius: map.get($values, 'border-radius');
246
+ }
247
+ }
248
+ }
249
+ </style>
@@ -0,0 +1,235 @@
1
+ <script setup lang="ts">
2
+ import type { ComboboxRootEmits, ComboboxRootProps } from 'radix-vue';
3
+ import type { BadgeProps } from '../badge/badge.vue';
4
+ import type { ComboboxItemPropsType } from './combobox-item.vue';
5
+
6
+ import { useForwardPropsEmits } from 'radix-vue';
7
+ import { computed } from 'vue';
8
+ import Badge from '../badge/badge.vue';
9
+ import ComboboxAnchor from './combobox-anchor.vue';
10
+ import ComboboxEmpty from './combobox-empty.vue';
11
+ import ComboboxGroup from './combobox-group.vue';
12
+ import ComboboxInput from './combobox-input.vue';
13
+ import ComboboxItem from './combobox-item.vue';
14
+ import ComboboxList from './combobox-list.vue';
15
+ import ComboboxRoot from './combobox-root.vue';
16
+ import ComboboxSeparator from './combobox-separator.vue';
17
+ import ComboboxTrigger from './combobox-trigger.vue';
18
+
19
+ const props = withDefaults(defineProps<ComboboxPropsType>(), {
20
+ placeholder: 'Select',
21
+ size: 'sm',
22
+ });
23
+ const emits = defineEmits<ComboboxRootEmits>();
24
+
25
+ const delegatedProps = computed(() => {
26
+ const { open, filterFunction, ...delegated } = props;
27
+
28
+ return delegated;
29
+ });
30
+
31
+ const forwarded = useForwardPropsEmits(delegatedProps, emits);
32
+
33
+ const model = computed(() => props.modelValue as ComboboxItemPropsType[] | ComboboxItemPropsType | undefined);
34
+
35
+ function isSelected(value: ComboboxItemPropsType['value']): boolean | undefined {
36
+ if (!Array.isArray(props.modelValue) || !props.multiple)
37
+ return;
38
+
39
+ if (value === undefined || value === null)
40
+ return false;
41
+
42
+ return props.modelValue.some((selectedItem: ComboboxItemPropsType) => {
43
+ const { value: selectedValue } = selectedItem;
44
+
45
+ if (
46
+ props.valueBy
47
+ && Object.prototype.hasOwnProperty.call(value, props.valueBy)
48
+ && Object.prototype.hasOwnProperty.call(selectedValue, props.valueBy)) {
49
+ return (value as Record<string, any>)[props.valueBy] === (selectedValue as Record<string, any>)[props.valueBy];
50
+ }
51
+
52
+ return selectedValue === value;
53
+ });
54
+ }
55
+
56
+ const mergedBadgeProps = computed(() => ({
57
+ ...props.badgeProps,
58
+ disabled: props.disabled,
59
+ }));
60
+ </script>
61
+
62
+ <script lang="ts">
63
+ export interface ComboboxPropsType extends ComboboxRootProps {
64
+ options: ComboboxItemPropsType[];
65
+ valueBy?: string;
66
+ placeholder?: string;
67
+ type?: 'normal' | 'compact' | 'inline' | 'compact-input';
68
+ size?: 'xs' | 'sm' | 'md';
69
+ emptyLabel?: string;
70
+ badgeProps?: BadgeProps;
71
+ searchable?: boolean;
72
+ }
73
+ </script>
74
+
75
+ <template>
76
+ <ComboboxRoot
77
+ v-bind="forwarded"
78
+ :filter-function="filterFunction"
79
+ >
80
+ <ComboboxAnchor as-child>
81
+ <ComboboxTrigger
82
+ :type="type"
83
+ :filled="!!model"
84
+ :size="size"
85
+ >
86
+ <div class="celeste-dropdown-anchor-trigger-prefix">
87
+ <div v-if="model && !Array.isArray(model)" class="celeste-dropdown-anchor-trigger-prefix-selected">
88
+ <i v-if="model.icon" :class="model.icon" />
89
+ <div v-if="model.image">
90
+ <slot name="image" v-bind="{ selected: model }">
91
+ <img
92
+ :src="model.image"
93
+ alt="Selected option"
94
+ class="selected-dropdown-image"
95
+ >
96
+ </slot>
97
+ </div>
98
+ </div>
99
+ <slot
100
+ v-else
101
+ name="prefix"
102
+ class="celeste-dropdown-anchor-trigger-prefix-default"
103
+ />
104
+ </div>
105
+
106
+ <div
107
+ v-if="type !== 'inline'"
108
+ class="celeste-dropdown-input"
109
+ >
110
+ <span v-if="multiple">{{ placeholder }}</span>
111
+ <span v-else>
112
+ {{ model && !Array.isArray(model) ? model.label : props.placeholder }}
113
+ </span>
114
+ <span v-if="mergedBadgeProps && badgeProps" class="celeste-input-badge">
115
+ <Badge v-bind="mergedBadgeProps" />
116
+ </span>
117
+ </div>
118
+ <div class="celeste-dropdown-trigger">
119
+ <i class="i-celeste-arrow-down-s-line" />
120
+ </div>
121
+ </ComboboxTrigger>
122
+ </ComboboxAnchor>
123
+
124
+ <ComboboxList>
125
+ <div class="celeste-dropdown-inner-input" :class="{ 'sr-only': !searchable }">
126
+ <ComboboxInput :searchable="searchable" />
127
+ <ComboboxSeparator v-if="searchable" />
128
+ </div>
129
+
130
+ <ComboboxEmpty>
131
+ <template v-if="emptyLabel" #default>
132
+ {{ emptyLabel }}
133
+ </template>
134
+ </ComboboxEmpty>
135
+
136
+ <ComboboxGroup>
137
+ <ComboboxItem
138
+ v-for="option in props.options"
139
+ :key="option.label"
140
+ :label="option.label"
141
+ :sublabel="option.sublabel"
142
+ :description="option.description"
143
+ :checkbox="props.multiple"
144
+ :value="option"
145
+ :selected="isSelected(option.value)"
146
+ >
147
+ <template #prefix>
148
+ <i v-if="option.icon" :class="option.icon" />
149
+ <img
150
+ v-if="option.image"
151
+ :src="option.image"
152
+ alt="option"
153
+ class="celeste-dropdown-item-image"
154
+ >
155
+ </template>
156
+ </ComboboxItem>
157
+ </ComboboxGroup>
158
+ </ComboboxList>
159
+ </ComboboxRoot>
160
+ </template>
161
+
162
+ <style lang="scss" scoped>
163
+ * {
164
+ box-sizing: border-box;
165
+ }
166
+
167
+ .celeste-dropdown-anchor-trigger-prefix {
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+
172
+ &-selected {
173
+ display: flex;
174
+ align-items: center;
175
+ justify-content: center;
176
+ }
177
+ }
178
+
179
+ .celeste-dropdown-item-image,
180
+ .selected-dropdown-image {
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ width: 20px;
185
+ height: 20px;
186
+ object-fit: cover;
187
+ border-radius: var(--radius-full);
188
+ }
189
+
190
+ .celeste-dropdown-input {
191
+ display: flex;
192
+ flex: 1 0 0;
193
+ align-items: center;
194
+ justify-content: space-between;
195
+ background: inherit;
196
+ color: var(--color-text-sub-600);
197
+ font: var(--paragraph-sm);
198
+ cursor: pointer;
199
+ gap: var(--spacing-8);
200
+ }
201
+
202
+ .celeste-dropdown-trigger {
203
+ display: flex;
204
+ place-items: center center;
205
+ transition-property: transform;
206
+ transition-duration: var(--animation-fast);
207
+ transition-timing-function: ease-out;
208
+ border: none;
209
+ background: none;
210
+ color: var(--color-icon-soft-400);
211
+ cursor: pointer;
212
+ }
213
+
214
+ .celeste-dropdown-inner-input {
215
+ display: flex;
216
+ position: sticky;
217
+ z-index: 50;
218
+ top: 0;
219
+ flex-direction: column;
220
+ gap: var(--spacing-4);
221
+ background-color: var(--color-bg-white-0);
222
+
223
+ &.sr-only {
224
+ position: absolute;
225
+ width: 1px;
226
+ height: 1px;
227
+ margin: -1px;
228
+ padding: 0;
229
+ overflow: hidden;
230
+ clip: rect(0, 0, 0, 0);
231
+ border: 0;
232
+ white-space: nowrap;
233
+ }
234
+ }
235
+ </style>
@@ -0,0 +1,29 @@
1
+ export * from './combobox-anchor.vue';
2
+ export { default as ComboboxAnchor } from './combobox-anchor.vue';
3
+
4
+ export * from './combobox-empty.vue';
5
+ export { default as ComboboxEmpty } from './combobox-empty.vue';
6
+
7
+ export * from './combobox-group.vue';
8
+ export { default as ComboboxGroup } from './combobox-group.vue';
9
+
10
+ export * from './combobox-input.vue';
11
+ export { default as ComboboxInput } from './combobox-input.vue';
12
+
13
+ export * from './combobox-item.vue';
14
+ export { default as ComboboxItem } from './combobox-item.vue';
15
+
16
+ export * from './combobox-list.vue';
17
+ export { default as ComboboxList } from './combobox-list.vue';
18
+
19
+ export * from './combobox-root.vue';
20
+ export { default as ComboboxRoot } from './combobox-root.vue';
21
+
22
+ export * from './combobox-separator.vue';
23
+ export { default as ComboboxSeparator } from './combobox-separator.vue';
24
+
25
+ export * from './combobox-trigger.vue';
26
+ export { default as ComboboxTrigger } from './combobox-trigger.vue';
27
+
28
+ export * from './combobox.vue';
29
+ export { default as Combobox } from './combobox.vue';