@youcan/celeste 0.12.0 → 0.13.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 (76) hide show
  1. package/ai/component-registry.json +2 -2
  2. package/ai/component-registry.md +1 -1
  3. package/ai/icons.md +1 -1
  4. package/ai/tokens.md +1 -1
  5. package/dist/celeste.css +148 -158
  6. package/dist/cjs/chunks/ConfigProvider.cjs +58 -1
  7. package/dist/cjs/chunks/calendar.cjs +73 -67
  8. package/dist/cjs/chunks/combobox-root.cjs +12 -5
  9. package/dist/cjs/chunks/digit-input.cjs +13 -7
  10. package/dist/cjs/chunks/dropdown-menu.cjs +10 -4
  11. package/dist/cjs/chunks/radio-group.cjs +9 -3
  12. package/dist/cjs/chunks/range-calendar.cjs +73 -67
  13. package/dist/cjs/chunks/scroll-area.cjs +18 -12
  14. package/dist/cjs/chunks/scroll-bar.cjs +1 -0
  15. package/dist/cjs/chunks/segmented-control.cjs +23 -17
  16. package/dist/cjs/chunks/select.cjs +9 -3
  17. package/dist/cjs/chunks/slider.cjs +16 -10
  18. package/dist/cjs/chunks/tab-menu-list.cjs +3 -3
  19. package/dist/cjs/chunks/tab-menu.cjs +12 -5
  20. package/dist/cjs/chunks/text-input.cjs +1 -1
  21. package/dist/cjs/command-root.cjs +9 -3
  22. package/dist/cjs/index.cjs +2 -0
  23. package/dist/cjs/use-direction.cjs +31 -0
  24. package/dist/cjs/use-tab-observer.cjs +1 -1
  25. package/dist/components/combobox/combobox-root.d.ts +2 -2
  26. package/dist/components/dropdown-menu/dropdown-menu.d.ts +2 -2
  27. package/dist/components/radio-group/radio-group.d.ts +2 -2
  28. package/dist/components/scroll-area/scroll-area.d.ts +2 -2
  29. package/dist/components/segmented-control/segmented-control.d.ts +2 -2
  30. package/dist/components/select/select.d.ts +2 -2
  31. package/dist/components/tab-menu/tab-menu.d.ts +2 -2
  32. package/dist/composables/index.d.ts +1 -0
  33. package/dist/composables/use-direction.d.ts +3 -0
  34. package/dist/es/chunks/ConfigProvider.js +53 -2
  35. package/dist/es/chunks/FocusScope.js +1 -1
  36. package/dist/es/chunks/Teleport.js +1 -1
  37. package/dist/es/chunks/calendar.js +73 -67
  38. package/dist/es/chunks/combobox-root.js +13 -6
  39. package/dist/es/chunks/digit-input.js +14 -8
  40. package/dist/es/chunks/dropdown-menu.js +11 -5
  41. package/dist/es/chunks/radio-group.js +10 -4
  42. package/dist/es/chunks/range-calendar.js +73 -67
  43. package/dist/es/chunks/scroll-area.js +18 -12
  44. package/dist/es/chunks/scroll-bar.js +1 -0
  45. package/dist/es/chunks/segmented-control.js +24 -18
  46. package/dist/es/chunks/select.js +10 -4
  47. package/dist/es/chunks/slider.js +16 -10
  48. package/dist/es/chunks/tab-menu-list.js +3 -3
  49. package/dist/es/chunks/tab-menu.js +13 -6
  50. package/dist/es/chunks/text-input.js +1 -1
  51. package/dist/es/chunks/useDirection.js +1 -1
  52. package/dist/es/chunks/useId.js +1 -1
  53. package/dist/es/chunks/useLocale.js +1 -1
  54. package/dist/es/chunks/useNonce.js +1 -1
  55. package/dist/es/command-root.js +10 -4
  56. package/dist/es/index.js +2 -1
  57. package/dist/es/use-direction.js +30 -0
  58. package/dist/es/use-tab-observer.js +1 -1
  59. package/package.json +3 -3
  60. package/src/components/calendar/calendar.vue +66 -60
  61. package/src/components/combobox/combobox-root.vue +9 -4
  62. package/src/components/command/command-root.vue +13 -8
  63. package/src/components/digit-input/digit-input.vue +13 -8
  64. package/src/components/dropdown-menu/dropdown-menu.vue +12 -7
  65. package/src/components/radio-group/radio-group.vue +12 -7
  66. package/src/components/range-calendar/range-calendar.vue +67 -61
  67. package/src/components/scroll-area/scroll-area.vue +17 -18
  68. package/src/components/segmented-control/segmented-control.vue +28 -23
  69. package/src/components/select/select.vue +12 -7
  70. package/src/components/slider/slider.vue +19 -14
  71. package/src/components/tab-menu/tab-menu-list.vue +8 -8
  72. package/src/components/tab-menu/tab-menu.vue +12 -4
  73. package/src/components/text-input/text-input.vue +11 -29
  74. package/src/composables/index.ts +1 -0
  75. package/src/composables/use-direction.ts +40 -0
  76. package/src/composables/use-tab-observer.ts +1 -2
@@ -2,23 +2,28 @@
2
2
  import type { RadioGroupRootEmits, RadioGroupRootProps } from 'reka-ui';
3
3
  import type { HTMLAttributes } from 'vue';
4
4
  import clsx from 'clsx';
5
- import { RadioGroupRoot, useForwardPropsEmits } from 'reka-ui';
5
+ import { ConfigProvider, RadioGroupRoot, useForwardPropsEmits } from 'reka-ui';
6
6
  import { useDelegatedProps } from '@/composables/use-delegated-props';
7
+ import { useDirection } from '@/composables/use-direction';
7
8
 
8
9
  const props = defineProps<RadioGroupRootProps & { class?: HTMLAttributes['class'] }>();
9
10
  const emits = defineEmits<RadioGroupRootEmits>();
10
11
 
11
12
  const delegatedProps = useDelegatedProps(props, 'class');
12
13
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
14
+
15
+ const direction = useDirection();
13
16
  </script>
14
17
 
15
18
  <template>
16
- <RadioGroupRoot
17
- :class="clsx('celeste-radio-wrapper', props.class)"
18
- v-bind="forwarded"
19
- >
20
- <slot />
21
- </RadioGroupRoot>
19
+ <ConfigProvider :dir="props.dir ?? direction">
20
+ <RadioGroupRoot
21
+ :class="clsx('celeste-radio-wrapper', props.class)"
22
+ v-bind="forwarded"
23
+ >
24
+ <slot />
25
+ </RadioGroupRoot>
26
+ </ConfigProvider>
22
27
  </template>
23
28
 
24
29
  <style lang="scss">
@@ -4,6 +4,7 @@ import type { HTMLAttributes } from 'vue';
4
4
  import { DateFormatter, getLocalTimeZone, isEqualDay } from '@internationalized/date';
5
5
  import clsx from 'clsx';
6
6
  import {
7
+ ConfigProvider,
7
8
  RangeCalendarCell,
8
9
  RangeCalendarCellTrigger,
9
10
  RangeCalendarGrid,
@@ -18,6 +19,7 @@ import {
18
19
  } from 'reka-ui';
19
20
  import { computed } from 'vue';
20
21
  import { useDelegatedProps } from '@/composables/use-delegated-props';
22
+ import { useDirection } from '@/composables/use-direction';
21
23
 
22
24
  export interface RangeCalendarProps extends RangeCalendarRootProps {
23
25
  class?: HTMLAttributes['class'];
@@ -36,6 +38,8 @@ const emits = defineEmits<RangeCalendarRootEmits>();
36
38
  const delegatedProps = useDelegatedProps(props, ['class', 'markedDates']);
37
39
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
38
40
 
41
+ const direction = useDirection();
42
+
39
43
  const monthFormatter = computed(
40
44
  () => new DateFormatter(props.locale ?? 'en-US', { month: 'long', year: 'numeric' }),
41
45
  );
@@ -54,70 +58,72 @@ function weekdayLabel(day: string): string {
54
58
  </script>
55
59
 
56
60
  <template>
57
- <RangeCalendarRoot
58
- v-slot="{ weekDays, grid }"
59
- v-bind="forwarded"
60
- :class="clsx('celeste-range-calendar', props.class)"
61
- >
62
- <div class="celeste-range-calendar-months">
63
- <div
64
- v-for="month in grid"
65
- :key="month.value.toString()"
66
- class="celeste-range-calendar-month"
67
- >
68
- <div class="celeste-range-calendar-header">
69
- <RangeCalendarPrev as-child>
70
- <button type="button" class="celeste-range-calendar-nav">
71
- <i class="i-celeste-arrow-left-s-line" />
72
- </button>
73
- </RangeCalendarPrev>
74
- <span class="celeste-range-calendar-heading">{{ formatMonth(month.value) }}</span>
75
- <RangeCalendarNext as-child>
76
- <button type="button" class="celeste-range-calendar-nav">
77
- <i class="i-celeste-arrow-right-s-line" />
78
- </button>
79
- </RangeCalendarNext>
80
- </div>
81
-
82
- <RangeCalendarGrid class="celeste-range-calendar-grid">
83
- <RangeCalendarGridHead>
84
- <RangeCalendarGridRow class="celeste-range-calendar-week">
85
- <RangeCalendarHeadCell
86
- v-for="day in weekDays"
87
- :key="day"
88
- class="celeste-range-calendar-weekday"
89
- >
90
- {{ weekdayLabel(day) }}
91
- </RangeCalendarHeadCell>
92
- </RangeCalendarGridRow>
93
- </RangeCalendarGridHead>
94
- <RangeCalendarGridBody class="celeste-range-calendar-body">
95
- <RangeCalendarGridRow
96
- v-for="(weekDates, index) in month.rows"
97
- :key="`week-${index}`"
98
- class="celeste-range-calendar-week"
99
- >
100
- <RangeCalendarCell
101
- v-for="weekDate in weekDates"
102
- :key="weekDate.toString()"
103
- :date="weekDate"
104
- class="celeste-range-calendar-cell"
61
+ <ConfigProvider :dir="props.dir ?? direction">
62
+ <RangeCalendarRoot
63
+ v-slot="{ weekDays, grid }"
64
+ v-bind="forwarded"
65
+ :class="clsx('celeste-range-calendar', props.class)"
66
+ >
67
+ <div class="celeste-range-calendar-months">
68
+ <div
69
+ v-for="month in grid"
70
+ :key="month.value.toString()"
71
+ class="celeste-range-calendar-month"
72
+ >
73
+ <div class="celeste-range-calendar-header">
74
+ <RangeCalendarPrev as-child>
75
+ <button type="button" class="celeste-range-calendar-nav">
76
+ <i class="i-celeste-arrow-left-s-line" />
77
+ </button>
78
+ </RangeCalendarPrev>
79
+ <span class="celeste-range-calendar-heading">{{ formatMonth(month.value) }}</span>
80
+ <RangeCalendarNext as-child>
81
+ <button type="button" class="celeste-range-calendar-nav">
82
+ <i class="i-celeste-arrow-right-s-line" />
83
+ </button>
84
+ </RangeCalendarNext>
85
+ </div>
86
+
87
+ <RangeCalendarGrid class="celeste-range-calendar-grid">
88
+ <RangeCalendarGridHead>
89
+ <RangeCalendarGridRow class="celeste-range-calendar-week">
90
+ <RangeCalendarHeadCell
91
+ v-for="day in weekDays"
92
+ :key="day"
93
+ class="celeste-range-calendar-weekday"
94
+ >
95
+ {{ weekdayLabel(day) }}
96
+ </RangeCalendarHeadCell>
97
+ </RangeCalendarGridRow>
98
+ </RangeCalendarGridHead>
99
+ <RangeCalendarGridBody class="celeste-range-calendar-body">
100
+ <RangeCalendarGridRow
101
+ v-for="(weekDates, index) in month.rows"
102
+ :key="`week-${index}`"
103
+ class="celeste-range-calendar-week"
105
104
  >
106
- <RangeCalendarCellTrigger
107
- :day="weekDate"
108
- :month="month.value"
109
- class="celeste-range-calendar-day"
110
- :data-marked="isMarked(weekDate) ? '' : undefined"
105
+ <RangeCalendarCell
106
+ v-for="weekDate in weekDates"
107
+ :key="weekDate.toString()"
108
+ :date="weekDate"
109
+ class="celeste-range-calendar-cell"
111
110
  >
112
- <span class="celeste-range-calendar-day-number">{{ weekDate.day }}</span>
113
- </RangeCalendarCellTrigger>
114
- </RangeCalendarCell>
115
- </RangeCalendarGridRow>
116
- </RangeCalendarGridBody>
117
- </RangeCalendarGrid>
111
+ <RangeCalendarCellTrigger
112
+ :day="weekDate"
113
+ :month="month.value"
114
+ class="celeste-range-calendar-day"
115
+ :data-marked="isMarked(weekDate) ? '' : undefined"
116
+ >
117
+ <span class="celeste-range-calendar-day-number">{{ weekDate.day }}</span>
118
+ </RangeCalendarCellTrigger>
119
+ </RangeCalendarCell>
120
+ </RangeCalendarGridRow>
121
+ </RangeCalendarGridBody>
122
+ </RangeCalendarGrid>
123
+ </div>
118
124
  </div>
119
- </div>
120
- </RangeCalendarRoot>
125
+ </RangeCalendarRoot>
126
+ </ConfigProvider>
121
127
  </template>
122
128
 
123
129
  <style scoped lang="scss">
@@ -2,32 +2,31 @@
2
2
  import type { ScrollAreaRootProps } from 'reka-ui';
3
3
  import type { HTMLAttributes } from 'vue';
4
4
  import clsx from 'clsx';
5
- import {
6
- ScrollAreaCorner,
7
- ScrollAreaRoot,
8
-
9
- ScrollAreaViewport,
10
- } from 'reka-ui';
11
- import { useDelegatedProps } from '@/composables';
5
+ import { ConfigProvider, ScrollAreaCorner, ScrollAreaRoot, ScrollAreaViewport } from 'reka-ui';
6
+ import { useDelegatedProps, useDirection } from '@/composables';
12
7
  import ScrollBar from './scroll-bar.vue';
13
8
 
14
9
  const props = defineProps<ScrollAreaRootProps & { class?: HTMLAttributes['class'] }>();
15
10
 
16
11
  const delegatedProps = useDelegatedProps(props, 'class');
12
+
13
+ const direction = useDirection();
17
14
  </script>
18
15
 
19
16
  <template>
20
- <ScrollAreaRoot
21
- v-bind="delegatedProps"
22
- :class="clsx('celeste-scroll-area', props.class)"
23
- >
24
- <ScrollAreaViewport class="celeste-scroll-area-viewport">
25
- <slot />
26
- </ScrollAreaViewport>
27
- <ScrollBar />
28
- <ScrollBar orientation="horizontal" />
29
- <ScrollAreaCorner />
30
- </ScrollAreaRoot>
17
+ <ConfigProvider :dir="props.dir ?? direction">
18
+ <ScrollAreaRoot
19
+ v-bind="delegatedProps"
20
+ :class="clsx('celeste-scroll-area', props.class)"
21
+ >
22
+ <ScrollAreaViewport class="celeste-scroll-area-viewport">
23
+ <slot />
24
+ </ScrollAreaViewport>
25
+ <ScrollBar />
26
+ <ScrollBar orientation="horizontal" />
27
+ <ScrollAreaCorner />
28
+ </ScrollAreaRoot>
29
+ </ConfigProvider>
31
30
  </template>
32
31
 
33
32
  <style scoped lang="scss">
@@ -2,8 +2,9 @@
2
2
  import type { ToggleGroupRootEmits, ToggleGroupRootProps } from 'reka-ui';
3
3
  import type { HTMLAttributes } from 'vue';
4
4
  import clsx from 'clsx';
5
- import { ToggleGroupRoot as SegmentedControlRoot, useForwardPropsEmits } from 'reka-ui';
5
+ import { ConfigProvider, ToggleGroupRoot as SegmentedControlRoot, useForwardPropsEmits } from 'reka-ui';
6
6
  import { useDelegatedProps } from '@/composables/use-delegated-props';
7
+ import { useDirection } from '@/composables/use-direction';
7
8
  import { useTabObserver } from '@/composables/use-tab-observer';
8
9
 
9
10
  const props = defineProps<Omit<ToggleGroupRootProps, 'type'> & { class?: HTMLAttributes['class'] }>();
@@ -12,27 +13,31 @@ const emits = defineEmits<ToggleGroupRootEmits>();
12
13
  const delegatedProps = useDelegatedProps(props, 'class');
13
14
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
14
15
 
16
+ const direction = useDirection();
17
+
15
18
  const { listRef, indicator, ready } = useTabObserver('[data-state="on"]');
16
19
  </script>
17
20
 
18
21
  <template>
19
- <SegmentedControlRoot
20
- ref="listRef"
21
- :class="clsx('celeste-segmented-control', props.class)"
22
- v-bind="forwarded"
23
- type="single"
24
- >
25
- <slot />
26
- <div
27
- class="celeste-segmented-control-indicator"
28
- :data-ready="ready"
29
- :style="{
30
- width: `${indicator.width}px`,
31
- height: `${indicator.height}px`,
32
- transform: `translate3d(${indicator.left}px, ${indicator.top}px, 0)`,
33
- }"
34
- />
35
- </SegmentedControlRoot>
22
+ <ConfigProvider :dir="props.dir ?? direction">
23
+ <SegmentedControlRoot
24
+ ref="listRef"
25
+ :class="clsx('celeste-segmented-control', props.class)"
26
+ v-bind="forwarded"
27
+ type="single"
28
+ >
29
+ <slot />
30
+ <div
31
+ :hidden="!ready"
32
+ class="celeste-segmented-control-indicator"
33
+ :style="{
34
+ width: `${indicator.width}px`,
35
+ height: `${indicator.height}px`,
36
+ transform: `translate3d(${indicator.left}px, ${indicator.top}px, 0)`,
37
+ }"
38
+ />
39
+ </SegmentedControlRoot>
40
+ </ConfigProvider>
36
41
  </template>
37
42
 
38
43
  <style scoped>
@@ -58,17 +63,17 @@ const { listRef, indicator, ready } = useTabObserver('[data-state="on"]');
58
63
  top: 0;
59
64
  left: 0;
60
65
  transition-property: transform, width, height;
61
- transition-duration: 0s;
66
+ transition-duration: var(--animation-normal);
62
67
  transition-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
63
68
  border-radius: var(--radius-6);
64
- opacity: 0;
65
69
  background-color: var(--color-bg-white-0);
66
70
  box-shadow: var(--shadow-toggle-switch);
67
71
  pointer-events: none;
72
+ }
68
73
 
69
- &[data-ready='true'] {
70
- transition-duration: var(--animation-normal);
71
- opacity: 1;
74
+ @media (prefers-reduced-motion: reduce) {
75
+ .celeste-segmented-control-indicator {
76
+ transition-duration: 0s;
72
77
  }
73
78
  }
74
79
  </style>
@@ -2,21 +2,26 @@
2
2
  import type { SelectRootEmits, SelectRootProps } from 'reka-ui';
3
3
  import type { HTMLAttributes } from 'vue';
4
4
  import clsx from 'clsx';
5
- import { SelectRoot, useForwardPropsEmits } from 'reka-ui';
5
+ import { ConfigProvider, SelectRoot, useForwardPropsEmits } from 'reka-ui';
6
6
  import { useDelegatedProps } from '@/composables/use-delegated-props';
7
+ import { useDirection } from '@/composables/use-direction';
7
8
 
8
9
  const props = defineProps<SelectRootProps & { class?: HTMLAttributes['class'] }>();
9
10
  const emits = defineEmits<SelectRootEmits>();
10
11
 
11
12
  const delegatedProps = useDelegatedProps(props, 'class');
12
13
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
14
+
15
+ const direction = useDirection();
13
16
  </script>
14
17
 
15
18
  <template>
16
- <SelectRoot
17
- v-bind="forwarded"
18
- :class="clsx('celeste-select', props.class)"
19
- >
20
- <slot />
21
- </SelectRoot>
19
+ <ConfigProvider :dir="props.dir ?? direction">
20
+ <SelectRoot
21
+ v-bind="forwarded"
22
+ :class="clsx('celeste-select', props.class)"
23
+ >
24
+ <slot />
25
+ </SelectRoot>
26
+ </ConfigProvider>
22
27
  </template>
@@ -2,31 +2,36 @@
2
2
  import type { SliderRootEmits, SliderRootProps } from 'reka-ui';
3
3
  import type { HTMLAttributes } from 'vue';
4
4
  import clsx from 'clsx';
5
- import { SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'reka-ui';
5
+ import { ConfigProvider, SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'reka-ui';
6
6
  import { useDelegatedProps } from '@/composables/use-delegated-props';
7
+ import { useDirection } from '@/composables/use-direction';
7
8
 
8
9
  const props = defineProps<Omit<SliderRootProps, 'orientation'> & { class?: HTMLAttributes['class'] }>();
9
10
  const emits = defineEmits<SliderRootEmits>();
10
11
 
11
12
  const delegatedProps = useDelegatedProps(props, 'class');
12
13
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
14
+
15
+ const direction = useDirection();
13
16
  </script>
14
17
 
15
18
  <template>
16
- <SliderRoot
17
- v-bind="forwarded"
18
- :class="clsx('celeste-slider', props.class)"
19
- >
20
- <SliderTrack class="celeste-slider-track">
21
- <SliderRange class="celeste-slider-range" />
22
- </SliderTrack>
19
+ <ConfigProvider :dir="props.dir ?? direction">
20
+ <SliderRoot
21
+ v-bind="forwarded"
22
+ :class="clsx('celeste-slider', props.class)"
23
+ >
24
+ <SliderTrack class="celeste-slider-track">
25
+ <SliderRange class="celeste-slider-range" />
26
+ </SliderTrack>
23
27
 
24
- <SliderThumb
25
- v-for="(_, key) in modelValue"
26
- :key="key"
27
- class="celeste-slider-thumb"
28
- />
29
- </SliderRoot>
28
+ <SliderThumb
29
+ v-for="(_, key) in modelValue"
30
+ :key="key"
31
+ class="celeste-slider-thumb"
32
+ />
33
+ </SliderRoot>
34
+ </ConfigProvider>
30
35
  </template>
31
36
 
32
37
  <style lang="scss">
@@ -41,8 +41,8 @@ const { listRef, indicator, ready } = useTabObserver('[data-state="active"]');
41
41
  >
42
42
  <slot />
43
43
  <div
44
+ :hidden="!ready"
44
45
  class="celeste-tab-menu-indicator"
45
- :data-ready="ready"
46
46
  :style="{
47
47
  width: `${indicator.width}px`,
48
48
  transform: `translate3d(${indicator.left}px, 0, 0)`,
@@ -104,9 +104,8 @@ const { listRef, indicator, ready } = useTabObserver('[data-state="active"]');
104
104
  left: 0;
105
105
  height: 2px;
106
106
  transition-property: transform, width;
107
- transition-duration: 0s;
107
+ transition-duration: var(--animation-normal);
108
108
  transition-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
109
- opacity: 0;
110
109
  background-color: var(--color-primary-base);
111
110
  pointer-events: none;
112
111
 
@@ -114,13 +113,14 @@ const { listRef, indicator, ready } = useTabObserver('[data-state="active"]');
114
113
  bottom: 0;
115
114
  }
116
115
 
117
- &[data-ready='true'] {
118
- transition-duration: var(--animation-normal);
119
- opacity: 1;
120
- }
121
-
122
116
  .celeste-tab-menu-list[data-orientation='vertical'] > & {
123
117
  display: none;
124
118
  }
125
119
  }
120
+
121
+ @media (prefers-reduced-motion: reduce) {
122
+ .celeste-tab-menu-indicator {
123
+ transition-duration: 0s;
124
+ }
125
+ }
126
126
  </style>
@@ -1,17 +1,25 @@
1
1
  <script setup lang="ts">
2
2
  import type { TabsRootEmits, TabsRootProps } from 'reka-ui';
3
- import { TabsRoot, useForwardPropsEmits } from 'reka-ui';
3
+ import { ConfigProvider, TabsRoot, useForwardPropsEmits } from 'reka-ui';
4
+ import { useDirection } from '@/composables/use-direction';
4
5
 
5
6
  const props = defineProps<TabsRootProps>();
6
7
  const emits = defineEmits<TabsRootEmits>();
7
8
 
8
9
  const forwarded = useForwardPropsEmits(props, emits);
10
+
11
+ const direction = useDirection();
9
12
  </script>
10
13
 
11
14
  <template>
12
- <TabsRoot v-bind="forwarded" class="celeste-tab-menu-root">
13
- <slot />
14
- </TabsRoot>
15
+ <ConfigProvider :dir="props.dir ?? direction">
16
+ <TabsRoot
17
+ v-bind="forwarded"
18
+ class="celeste-tab-menu-root"
19
+ >
20
+ <slot />
21
+ </TabsRoot>
22
+ </ConfigProvider>
15
23
  </template>
16
24
 
17
25
  <style scoped>
@@ -270,41 +270,23 @@ function clearInput() {
270
270
 
271
271
  :deep(.celeste-text-input-node.celeste-text-input-leading-node),
272
272
  :deep(.celeste-text-input-node.celeste-text-input-trailing-node) {
273
- height: calc(var(--input-height) - var(--spacing-2)) !important;
274
- }
275
-
276
- [dir='ltr'] & {
277
- :deep(.celeste-text-input-node.celeste-text-input-leading-node) {
278
- border-right: 1px solid var(--color-stroke-soft-200) !important;
279
- border-radius: var(--input-radius) 0 0 var(--input-radius) !important;
280
- }
281
-
282
- :deep(.celeste-text-input-node.celeste-text-input-trailing-node) {
283
- border-left: 1px solid var(--color-stroke-soft-200) !important;
284
- border-radius: 0 var(--input-radius) var(--input-radius) 0 !important;
285
- }
286
- }
287
-
288
- [dir='rtl'] & {
289
- :deep(.celeste-text-input-node.celeste-text-input-leading-node) {
290
- border-left: 1px solid var(--color-stroke-soft-200) !important;
291
- border-radius: 0 var(--input-radius) var(--input-radius) 0 !important;
292
- }
293
-
294
- :deep(.celeste-text-input-node.celeste-text-input-trailing-node) {
295
- border-right: 1px solid var(--color-stroke-soft-200) !important;
296
- border-radius: var(--input-radius) 0 0 var(--input-radius) !important;
297
- }
273
+ height: calc(var(--input-height) - var(--spacing-2));
298
274
  }
299
275
 
300
276
  :deep(.celeste-text-input-node.celeste-text-input-leading-node) {
301
- border-right: 1px solid var(--color-stroke-soft-200) !important;
302
- border-radius: var(--input-radius) 0 0 var(--input-radius) !important;
277
+ border-inline-end: 1px solid var(--color-stroke-soft-200);
278
+ border-start-start-radius: var(--input-radius);
279
+ border-start-end-radius: 0;
280
+ border-end-end-radius: 0;
281
+ border-end-start-radius: var(--input-radius);
303
282
  }
304
283
 
305
284
  :deep(.celeste-text-input-node.celeste-text-input-trailing-node) {
306
- border-left: 1px solid var(--color-stroke-soft-200) !important;
307
- border-radius: 0 var(--input-radius) var(--input-radius) 0 !important;
285
+ border-inline-start: 1px solid var(--color-stroke-soft-200);
286
+ border-start-start-radius: 0;
287
+ border-start-end-radius: var(--input-radius);
288
+ border-end-end-radius: var(--input-radius);
289
+ border-end-start-radius: 0;
308
290
  }
309
291
  }
310
292
  </style>
@@ -1,5 +1,6 @@
1
1
  export * from './use-chart-motion';
2
2
  export * from './use-delegated-props';
3
+ export * from './use-direction';
3
4
  export * from './use-locale';
4
5
  export * from './use-sidebar';
5
6
  export * from './use-tab-observer';
@@ -0,0 +1,40 @@
1
+ import type { Direction } from 'reka-ui';
2
+ import type { Ref } from 'vue';
3
+ import { getCurrentInstance, onMounted, ref, watch } from 'vue';
4
+
5
+ const revision = ref(0);
6
+
7
+ let observer: MutationObserver | undefined;
8
+
9
+ function observeDocument(): void {
10
+ if (observer || typeof document === 'undefined')
11
+ return;
12
+
13
+ observer = new MutationObserver(() => revision.value++);
14
+ observer.observe(document.documentElement, { attributeFilter: ['dir'], subtree: true });
15
+ }
16
+
17
+ function documentDirection(): Direction {
18
+ return typeof document !== 'undefined' && document.documentElement.dir === 'rtl' ? 'rtl' : 'ltr';
19
+ }
20
+
21
+ export function useDirection(): Ref<Direction> {
22
+ const instance = getCurrentInstance();
23
+ const direction = ref<Direction>(documentDirection());
24
+
25
+ observeDocument();
26
+
27
+ function read(): void {
28
+ const node = instance?.vnode.el as Node | null | undefined;
29
+ const element = node instanceof HTMLElement ? node : node?.parentElement;
30
+
31
+ direction.value = element
32
+ ? getComputedStyle(element).direction === 'rtl' ? 'rtl' : 'ltr'
33
+ : documentDirection();
34
+ }
35
+
36
+ onMounted(read);
37
+ watch(revision, read);
38
+
39
+ return direction;
40
+ }
@@ -35,8 +35,7 @@ export function useTabObserver(activeSelector: string): TabObserver {
35
35
  height: active.offsetHeight,
36
36
  };
37
37
 
38
- if (!ready.value)
39
- requestAnimationFrame(() => requestAnimationFrame(() => ready.value = true));
38
+ ready.value = true;
40
39
  }
41
40
 
42
41
  useResizeObserver(listRef, update);