@byyuurin/ui 0.0.8 → 0.0.10

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 (151) hide show
  1. package/README.md +0 -3
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +4 -3
  4. package/dist/module.mjs.map +1 -1
  5. package/dist/runtime/app/injections.d.ts +9299 -8
  6. package/dist/runtime/app/injections.js +35 -5
  7. package/dist/runtime/components/Accordion.vue +17 -19
  8. package/dist/runtime/components/Alert.vue +6 -9
  9. package/dist/runtime/components/App.vue +14 -19
  10. package/dist/runtime/components/Avatar.vue +5 -8
  11. package/dist/runtime/components/AvatarGroup.vue +2 -5
  12. package/dist/runtime/components/Badge.vue +3 -6
  13. package/dist/runtime/components/Breadcrumb.vue +22 -23
  14. package/dist/runtime/components/Button.vue +2 -3
  15. package/dist/runtime/components/ButtonGroup.vue +2 -5
  16. package/dist/runtime/components/Calendar.vue +185 -0
  17. package/dist/runtime/components/Card.vue +2 -5
  18. package/dist/runtime/components/Carousel.vue +11 -16
  19. package/dist/runtime/components/Checkbox.vue +13 -11
  20. package/dist/runtime/components/Chip.vue +6 -9
  21. package/dist/runtime/components/Collapsible.vue +2 -5
  22. package/dist/runtime/components/Drawer.vue +88 -45
  23. package/dist/runtime/components/DropdownMenu.vue +143 -0
  24. package/dist/runtime/components/DropdownMenuContent.vue +188 -0
  25. package/dist/runtime/components/Form.vue +311 -0
  26. package/dist/runtime/components/FormItem.vue +129 -0
  27. package/dist/runtime/components/Input.vue +34 -23
  28. package/dist/runtime/components/InputNumber.vue +23 -18
  29. package/dist/runtime/components/Kbd.vue +2 -6
  30. package/dist/runtime/components/Link.vue +25 -7
  31. package/dist/runtime/components/Modal.vue +31 -22
  32. package/dist/runtime/components/OverlayProvider.vue +29 -0
  33. package/dist/runtime/components/Pagination.vue +34 -27
  34. package/dist/runtime/components/PinInput.vue +23 -17
  35. package/dist/runtime/components/Popover.vue +5 -8
  36. package/dist/runtime/components/Progress.vue +2 -5
  37. package/dist/runtime/components/RadioGroup.vue +52 -49
  38. package/dist/runtime/components/ScrollArea.vue +2 -6
  39. package/dist/runtime/components/Select.vue +96 -89
  40. package/dist/runtime/components/Separator.vue +2 -6
  41. package/dist/runtime/components/Skeleton.vue +2 -5
  42. package/dist/runtime/components/Slider.vue +13 -11
  43. package/dist/runtime/components/Switch.vue +18 -11
  44. package/dist/runtime/components/Table.vue +23 -13
  45. package/dist/runtime/components/Tabs.vue +14 -16
  46. package/dist/runtime/components/Textarea.vue +20 -17
  47. package/dist/runtime/components/Toast.vue +12 -13
  48. package/dist/runtime/components/{Toaster.vue → ToastProvider.vue} +18 -16
  49. package/dist/runtime/components/Tooltip.vue +5 -8
  50. package/dist/runtime/composables/useFormItem.d.ts +27 -0
  51. package/dist/runtime/composables/useFormItem.js +64 -0
  52. package/dist/runtime/composables/useKbd.d.ts +1 -1
  53. package/dist/runtime/composables/useOverlay.d.ts +29 -0
  54. package/dist/runtime/composables/useOverlay.js +69 -0
  55. package/dist/runtime/composables/useTheme.d.ts +6 -2
  56. package/dist/runtime/composables/useTheme.js +10 -3
  57. package/dist/runtime/composables/useToast.d.ts +4 -20
  58. package/dist/runtime/composables/useToast.js +6 -5
  59. package/dist/runtime/index.d.ts +6 -2
  60. package/dist/runtime/index.js +6 -2
  61. package/dist/runtime/locale/en.js +6 -0
  62. package/dist/runtime/locale/zh-tw.js +6 -0
  63. package/dist/runtime/theme/accordion.js +3 -3
  64. package/dist/runtime/theme/alert.js +3 -3
  65. package/dist/runtime/theme/app.d.ts +1 -0
  66. package/dist/runtime/theme/app.js +2 -1
  67. package/dist/runtime/theme/avatar.js +2 -2
  68. package/dist/runtime/theme/badge.d.ts +21 -45
  69. package/dist/runtime/theme/breadcrumb.d.ts +3 -3
  70. package/dist/runtime/theme/breadcrumb.js +5 -5
  71. package/dist/runtime/theme/button.d.ts +111 -57
  72. package/dist/runtime/theme/button.js +13 -13
  73. package/dist/runtime/theme/calendar.d.ts +56 -0
  74. package/dist/runtime/theme/calendar.js +69 -0
  75. package/dist/runtime/theme/card.js +6 -6
  76. package/dist/runtime/theme/carousel.js +1 -1
  77. package/dist/runtime/theme/checkbox.js +5 -5
  78. package/dist/runtime/theme/chip.d.ts +11 -44
  79. package/dist/runtime/theme/chip.js +3 -3
  80. package/dist/runtime/theme/drawer.d.ts +85 -47
  81. package/dist/runtime/theme/drawer.js +46 -19
  82. package/dist/runtime/theme/dropdown-menu.d.ts +71 -0
  83. package/dist/runtime/theme/dropdown-menu.js +83 -0
  84. package/dist/runtime/theme/form-item.d.ts +76 -0
  85. package/dist/runtime/theme/form-item.js +34 -0
  86. package/dist/runtime/theme/form.d.ts +8 -0
  87. package/dist/runtime/theme/form.js +7 -0
  88. package/dist/runtime/theme/index.d.ts +5 -1
  89. package/dist/runtime/theme/index.js +5 -1
  90. package/dist/runtime/theme/input-number.d.ts +41 -61
  91. package/dist/runtime/theme/input-number.js +1 -1
  92. package/dist/runtime/theme/input.d.ts +99 -71
  93. package/dist/runtime/theme/input.js +15 -15
  94. package/dist/runtime/theme/kbd.d.ts +2 -2
  95. package/dist/runtime/theme/kbd.js +1 -1
  96. package/dist/runtime/theme/link.d.ts +1 -1
  97. package/dist/runtime/theme/link.js +3 -3
  98. package/dist/runtime/theme/modal.d.ts +5 -33
  99. package/dist/runtime/theme/modal.js +4 -4
  100. package/dist/runtime/theme/pagination.d.ts +27 -3
  101. package/dist/runtime/theme/pagination.js +6 -2
  102. package/dist/runtime/theme/pinInput.d.ts +42 -42
  103. package/dist/runtime/theme/pinInput.js +13 -13
  104. package/dist/runtime/theme/progress.d.ts +117 -53
  105. package/dist/runtime/theme/progress.js +4 -4
  106. package/dist/runtime/theme/radio-group.d.ts +2 -2
  107. package/dist/runtime/theme/radio-group.js +7 -7
  108. package/dist/runtime/theme/select.d.ts +100 -84
  109. package/dist/runtime/theme/select.js +21 -20
  110. package/dist/runtime/theme/separator.d.ts +13 -28
  111. package/dist/runtime/theme/separator.js +1 -1
  112. package/dist/runtime/theme/skeleton.d.ts +1 -1
  113. package/dist/runtime/theme/skeleton.js +1 -1
  114. package/dist/runtime/theme/slider.js +1 -1
  115. package/dist/runtime/theme/switch.js +5 -5
  116. package/dist/runtime/theme/table.d.ts +3 -0
  117. package/dist/runtime/theme/table.js +8 -7
  118. package/dist/runtime/theme/tabs.d.ts +51 -68
  119. package/dist/runtime/theme/tabs.js +10 -10
  120. package/dist/runtime/theme/textarea.d.ts +37 -43
  121. package/dist/runtime/theme/textarea.js +13 -13
  122. package/dist/runtime/theme/{toaster.d.ts → toast-provider.d.ts} +26 -41
  123. package/dist/runtime/theme/toast.js +5 -5
  124. package/dist/runtime/theme/tooltip.js +1 -1
  125. package/dist/runtime/types/components.d.ts +6 -1
  126. package/dist/runtime/types/form.d.ts +45 -0
  127. package/dist/runtime/types/form.js +0 -0
  128. package/dist/runtime/types/index.d.ts +5 -2
  129. package/dist/runtime/types/index.js +1 -0
  130. package/dist/runtime/types/locale.d.ts +6 -0
  131. package/dist/runtime/types/utils.d.ts +35 -12
  132. package/dist/runtime/utils/extend-theme.js +15 -4
  133. package/dist/runtime/utils/form.d.ts +5 -0
  134. package/dist/runtime/utils/form.js +24 -0
  135. package/dist/runtime/utils/index.d.ts +2 -0
  136. package/dist/runtime/utils/index.js +4 -0
  137. package/dist/runtime/utils/link.d.ts +4 -26
  138. package/dist/runtime/utils/link.js +10 -3
  139. package/dist/shared/ui.3e7fad19.mjs +5 -0
  140. package/dist/shared/ui.3e7fad19.mjs.map +1 -0
  141. package/dist/unocss.mjs +21 -16
  142. package/dist/unocss.mjs.map +1 -1
  143. package/dist/unplugin.mjs +1 -1
  144. package/dist/vite.mjs +1 -1
  145. package/package.json +20 -18
  146. package/dist/runtime/components/ModalProvider.vue +0 -11
  147. package/dist/runtime/composables/useModal.d.ts +0 -10
  148. package/dist/runtime/composables/useModal.js +0 -47
  149. package/dist/shared/ui.ba24b380.mjs +0 -4
  150. package/dist/shared/ui.ba24b380.mjs.map +0 -1
  151. /package/dist/runtime/theme/{toaster.js → toast-provider.js} +0 -0
@@ -9,16 +9,46 @@ export const {
9
9
  inject: injectButtonGroup,
10
10
  provide: provideButtonGroup
11
11
  } = defineInjection("ui.button-group");
12
+ export const {
13
+ InjectionKey: InjectionKeyFormOptions,
14
+ inject: injectFormOptions,
15
+ provide: provideFormOptions
16
+ } = defineInjection("ui.form-options");
17
+ export const {
18
+ InjectionKey: InjectionKeyFormBus,
19
+ inject: injectFormBus,
20
+ provide: provideFormBus
21
+ } = defineInjection("ui.form-bus");
22
+ export const {
23
+ InjectionKey: InjectionKeyFormItem,
24
+ inject: injectFormItem,
25
+ provide: provideFormItem
26
+ } = defineInjection("ui.form-item");
27
+ export const {
28
+ InjectionKey: InjectionKeyFormInputId,
29
+ inject: injectFormInputId,
30
+ provide: provideFormInputId
31
+ } = defineInjection("ui.form-input-id");
32
+ export const {
33
+ InjectionKey: InjectionKeyFormInputs,
34
+ inject: injectFormInputs,
35
+ provide: provideFormInputs
36
+ } = defineInjection("ui.form-inputs");
37
+ export const {
38
+ InjectionKey: InjectionKeyFormLoading,
39
+ inject: injectFormLoading,
40
+ provide: provideFormLoading
41
+ } = defineInjection("ui.form-loading");
42
+ export const {
43
+ InjectionKey: InjectionKeyFormErrors,
44
+ inject: injectFormErrors,
45
+ provide: provideFormErrors
46
+ } = defineInjection("ui.form-errors", null);
12
47
  export const {
13
48
  InjectionKey: InjectionKeyLocaleContext,
14
49
  inject: injectLocaleContext,
15
50
  provide: provideLocaleContext
16
51
  } = defineInjection("ui.locale-context");
17
- export const {
18
- InjectionKey: InjectionKeyModalState,
19
- inject: injectModalState,
20
- provide: provideModalState
21
- } = defineInjection("ui.modal");
22
52
  export const {
23
53
  InjectionKey: InjectionKeyThemeExtension,
24
54
  provide: provideThemeExtension,
@@ -5,16 +5,6 @@ import type { ComponentAttrs, DynamicSlots } from '../types'
5
5
 
6
6
  export interface AccordionEmits extends AccordionRootEmits {}
7
7
 
8
- type SlotProps<T> = (props: { item: T, index: number, open: boolean }) => any
9
-
10
- export type AccordionSlots<T extends { slot?: string }> = {
11
- default?: SlotProps<T>
12
- leading?: SlotProps<T>
13
- trailing?: SlotProps<T>
14
- content?: SlotProps<T>
15
- body?: SlotProps<T>
16
- } & DynamicSlots<T, SlotProps<T>>
17
-
18
8
  export interface AccordionItem {
19
9
  label?: string
20
10
  icon?: string
@@ -24,9 +14,20 @@ export interface AccordionItem {
24
14
  /** A unique value for the accordion item. Defaults to the index. */
25
15
  value?: string
26
16
  disabled?: boolean
17
+ [key: string]: any
27
18
  }
28
19
 
29
- export interface AccordionProps<T> extends ComponentAttrs<typeof accordion>, Pick<AccordionRootProps, 'as' | 'collapsible' | 'defaultValue' | 'modelValue' | 'type' | 'disabled' | 'unmountOnHide'> {
20
+ type SlotProps<T extends AccordionItem> = (props: { item: T, index: number, open: boolean }) => any
21
+
22
+ export type AccordionSlots<T extends AccordionItem = AccordionItem> = {
23
+ default?: SlotProps<T>
24
+ leading?: SlotProps<T>
25
+ trailing?: SlotProps<T>
26
+ content?: SlotProps<T>
27
+ body?: SlotProps<T>
28
+ } & DynamicSlots<T, 'body', SlotProps<T>>
29
+
30
+ export interface AccordionProps<T extends AccordionItem = AccordionItem> extends ComponentAttrs<typeof accordion>, Pick<AccordionRootProps, 'as' | 'collapsible' | 'defaultValue' | 'modelValue' | 'type' | 'disabled' | 'unmountOnHide'> {
30
31
  items?: T[]
31
32
  /**
32
33
  * The icon displayed on the right side of the trigger.
@@ -55,11 +56,8 @@ const emit = defineEmits<AccordionEmits>()
55
56
  const slots = defineSlots<AccordionSlots<T>>()
56
57
  const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'collapsible', 'defaultValue', 'disabled', 'modelValue', 'type', 'unmountOnHide'), emit)
57
58
 
58
- const { theme, createStyler } = useTheme()
59
- const style = computed(() => {
60
- const styler = createStyler(theme.value.accordion)
61
- return styler(props)
62
- })
59
+ const { theme, generateStyle } = useTheme()
60
+ const style = computed(() => generateStyle('accordion', props))
63
61
  </script>
64
62
 
65
63
  <template>
@@ -89,12 +87,12 @@ const style = computed(() => {
89
87
  </AccordionHeader>
90
88
 
91
89
  <AccordionContent
92
- v-if="item.content || slots.content || (item.slot && slots[item.slot]) || slots.body || (slots[`${item.slot}-body`])"
90
+ v-if="item.content || slots.content || (item.slot && slots[item.slot as keyof AccordionSlots<T>]) || slots.body || (item.slot && slots[`${item.slot}-body` as keyof AccordionSlots<T>])"
93
91
  :class="style.content({ class: props.ui?.content })"
94
92
  >
95
- <slot :name="item.slot || 'content'" v-bind="{ item, index, open }">
93
+ <slot :name="((item.slot || 'content') as keyof AccordionSlots<T>)" v-bind="{ item, index, open }">
96
94
  <div :class="style.body({ class: props.ui?.body })">
97
- <slot :name="item.slot ? item.slot : 'body'" v-bind="{ item, index, open }">
95
+ <slot :name="((item.slot ? `${item.slot}-body` : 'body') as keyof AccordionSlots<T>)" v-bind="{ item, index, open }">
98
96
  {{ item.content }}
99
97
  </slot>
100
98
  </div>
@@ -5,7 +5,7 @@ import type { alert } from '../theme'
5
5
  import type { ButtonProps, ComponentAttrs } from '../types'
6
6
 
7
7
  export interface AlertEmits {
8
- (event: 'update:open', value: boolean): void
8
+ 'update:open': [value: boolean]
9
9
  }
10
10
 
11
11
  export interface AlertSlots {
@@ -64,14 +64,11 @@ const emit = defineEmits<AlertEmits>()
64
64
  const slots = defineSlots<AlertSlots>()
65
65
 
66
66
  const { t } = useLocale()
67
- const { theme, createStyler } = useTheme()
68
- const style = computed(() => {
69
- const styler = createStyler(theme.value.alert)
70
- return styler({
71
- ...props,
72
- title: !!props.title || !!slots.title,
73
- })
74
- })
67
+ const { theme, generateStyle } = useTheme()
68
+ const style = computed(() => generateStyle('alert', {
69
+ ...props,
70
+ title: !!props.title || !!slots.title,
71
+ }))
75
72
  </script>
76
73
 
77
74
  <template>
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { UserConfig } from '@unocss/core'
3
3
  import type { ConfigProviderProps, TooltipProviderProps } from 'reka-ui'
4
- import type { Messages, ThemeExtension, ToasterProps } from '../types'
4
+ import type { Messages, ThemeExtension, ToastProviderProps } from '../types'
5
5
  import type { Locale } from '../utils'
6
6
 
7
7
  export interface AppSlots {
@@ -11,7 +11,7 @@ export interface AppSlots {
11
11
  export interface AppProps extends Omit<ConfigProviderProps, 'useId' | 'dir' | 'locale'> {
12
12
  unoConfig?: UserConfig
13
13
  ui?: ThemeExtension
14
- toaster?: ToasterProps
14
+ toaster?: ToastProviderProps
15
15
  tooltip?: TooltipProviderProps
16
16
  locale?: Locale<Messages>
17
17
  }
@@ -20,11 +20,10 @@ export interface AppProps extends Omit<ConfigProviderProps, 'useId' | 'dir' | 'l
20
20
  <script setup lang="ts">
21
21
  import { reactivePick } from '@vueuse/core'
22
22
  import { ConfigProvider, TooltipProvider, useForwardProps } from 'reka-ui'
23
- import { shallowRef, toRef, useId } from 'vue'
24
- import type { ModalStateProvideValue } from '../app/injections'
25
- import { provideLocaleContext, provideModalState, provideThemeExtension, provideUnoConfig } from '../app/injections'
26
- import ModalProvider from './ModalProvider.vue'
27
- import Toaster from './Toaster.vue'
23
+ import { toRef, useId } from 'vue'
24
+ import { provideLocaleContext, provideThemeExtension, provideUnoConfig } from '../app/injections'
25
+ import OverlayProvider from './OverlayProvider.vue'
26
+ import ToastProvider from './ToastProvider.vue'
28
27
 
29
28
  const props = withDefaults(defineProps<AppProps>(), {
30
29
  unoConfig: () => ({}),
@@ -35,27 +34,23 @@ defineSlots<AppSlots>()
35
34
 
36
35
  const configProviderProps = useForwardProps(reactivePick(props, 'scrollBody'))
37
36
  const tooltipProps = toRef(() => props.tooltip)
38
- const toasterProps = toRef(() => props.toaster)
37
+ const toastProviderProps = toRef(() => props.toaster)
39
38
 
40
- const modalState = shallowRef<ModalStateProvideValue>({
41
- component: 'div',
42
- props: {},
43
- })
44
-
45
- provideModalState(modalState)
46
39
  provideUnoConfig(() => props.unoConfig)
47
40
  provideThemeExtension(() => props.ui)
48
- provideLocaleContext(() => props.locale)
41
+
42
+ const locale = toRef(() => props.locale)
43
+ provideLocaleContext(locale)
49
44
  </script>
50
45
 
51
46
  <template>
52
- <ConfigProvider :use-id="useId" v-bind="configProviderProps">
47
+ <ConfigProvider :use-id="useId" :dir="locale?.dir" :locale="locale?.code" v-bind="configProviderProps">
53
48
  <TooltipProvider v-bind="tooltipProps">
54
- <Toaster v-if="props.toaster !== null" v-bind="toasterProps">
49
+ <ToastProvider v-if="props.toaster !== null" v-bind="toastProviderProps">
55
50
  <slot></slot>
56
- </Toaster>
51
+ </ToastProvider>
57
52
  <slot v-else></slot>
58
53
  </TooltipProvider>
59
- <ModalProvider />
54
+ <OverlayProvider />
60
55
  </ConfigProvider>
61
56
  </template>
@@ -40,14 +40,11 @@ const props = withDefaults(defineProps<AvatarProps>(), {
40
40
  const { size } = useAvatarGroup(props)
41
41
  const fallback = computed(() => props.text || (props.alt || '').split(' ').map((word) => word.charAt(0)).join('').slice(0, 2))
42
42
 
43
- const { theme, createStyler } = useTheme()
44
- const style = computed(() => {
45
- const styler = createStyler(theme.value.avatar)
46
- return styler({
47
- ...props,
48
- size: size.value,
49
- })
50
- })
43
+ const { generateStyle } = useTheme()
44
+ const style = computed(() => generateStyle('avatar', {
45
+ ...props,
46
+ size: size.value,
47
+ }))
51
48
 
52
49
  const error = shallowRef(false)
53
50
 
@@ -73,11 +73,8 @@ const hiddenCount = computed(() => {
73
73
  return children.value.length - visibleAvatars.value.length
74
74
  })
75
75
 
76
- const { theme, createStyler } = useTheme()
77
- const style = computed(() => {
78
- const styler = createStyler(theme.value.avatarGroup)
79
- return styler(props)
80
- })
76
+ const { generateStyle } = useTheme()
77
+ const style = computed(() => generateStyle('avatarGroup', props))
81
78
 
82
79
  provideAvatarGroup(computed(() => props))
83
80
  </script>
@@ -5,7 +5,7 @@ import type { badge } from '../theme'
5
5
  import type { ComponentAttrs } from '../types'
6
6
 
7
7
  export interface BadgeEmits {
8
- (e: 'update:show', payload: boolean): void
8
+ 'update:show': [payload: boolean]
9
9
  }
10
10
 
11
11
  export interface BadgeSlots {
@@ -50,11 +50,8 @@ defineSlots<BadgeSlots>()
50
50
 
51
51
  const show = defineModel<boolean>('show', { default: true })
52
52
 
53
- const { theme, createStyler } = useTheme()
54
- const style = computed(() => {
55
- const styler = createStyler(theme.value.badge)
56
- return styler(props)
57
- })
53
+ const { generateStyle } = useTheme()
54
+ const style = computed(() => generateStyle('badge', props))
58
55
  </script>
59
56
 
60
57
  <template>
@@ -3,29 +3,29 @@ import type { PrimitiveProps } from 'reka-ui'
3
3
  import type { breadcrumb } from '../theme'
4
4
  import type { ComponentAttrs, DynamicSlots, LinkProps } from '../types'
5
5
 
6
- type SlotProps<T> = (props: { item: T, index: number, active?: boolean }) => any
7
-
8
- export type BreadcrumbSlots<T extends { slot?: string }> = {
9
- 'item'?: SlotProps<T>
10
- 'item-leading'?: SlotProps<T>
11
- 'item-label'?: SlotProps<T>
12
- 'item-trailing'?: SlotProps<T>
13
- 'separator'?: (props?: {}) => any
14
- } & DynamicSlots<T, SlotProps<T>>
15
-
16
6
  export interface BreadcrumbItem extends Omit<LinkProps, 'raw' | 'custom'> {
17
7
  label?: string
18
8
  icon?: string
19
9
  slot?: string
10
+ [key: string]: any
20
11
  }
21
12
 
22
- export interface BreadcrumbProps<T> extends ComponentAttrs<typeof breadcrumb> {
13
+ type SlotProps<T extends BreadcrumbItem> = (props: { item: T, index: number, active?: boolean }) => any
14
+
15
+ export type BreadcrumbSlots<T extends BreadcrumbItem = BreadcrumbItem> = {
16
+ 'item'?: SlotProps<T>
17
+ 'item-leading'?: SlotProps<T>
18
+ 'item-label'?: SlotProps<T>
19
+ 'item-trailing'?: SlotProps<T>
20
+ 'separator'?: any
21
+ } & DynamicSlots<T, 'leading' | 'label' | 'trailing', SlotProps<T>>
22
+
23
+ export interface BreadcrumbProps<T extends BreadcrumbItem = BreadcrumbItem> extends ComponentAttrs<typeof breadcrumb> {
23
24
  /**
24
25
  * The element or component this component should render as.
25
26
  * @default "nav"
26
27
  */
27
28
  as?: PrimitiveProps['as']
28
- dir?: 'rtl' | 'ltr'
29
29
  items?: T[]
30
30
  /**
31
31
  * The icon to use as a separator.
@@ -43,6 +43,7 @@ export interface BreadcrumbProps<T> extends ComponentAttrs<typeof breadcrumb> {
43
43
  <script setup lang="ts" generic="T extends BreadcrumbItem">
44
44
  import { Primitive } from 'reka-ui'
45
45
  import { computed } from 'vue'
46
+ import { useLocale } from '../composables/useLocale'
46
47
  import { useTheme } from '../composables/useTheme'
47
48
  import { get, pickLinkProps } from '../utils'
48
49
  import Link from './Link.vue'
@@ -55,14 +56,12 @@ const props = withDefaults(defineProps<BreadcrumbProps<T>>(), {
55
56
 
56
57
  const slots = defineSlots<BreadcrumbSlots<T>>()
57
58
 
58
- const { theme, createStyler } = useTheme()
59
+ const { dir } = useLocale()
60
+ const { theme, generateStyle } = useTheme()
59
61
 
60
- const separatorIcon = computed(() => props.separatorIcon || (props.dir === 'rtl' ? theme.value.app.icons.chevronLeft : theme.value.app.icons.chevronRight))
62
+ const separatorIcon = computed(() => props.separatorIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronLeft : theme.value.app.icons.chevronRight))
61
63
 
62
- const style = computed(() => {
63
- const styler = createStyler(theme.value.breadcrumb)
64
- return styler(props)
65
- })
64
+ const style = computed(() => generateStyle('breadcrumb', props))
66
65
  </script>
67
66
 
68
67
  <template>
@@ -77,18 +76,18 @@ const style = computed(() => {
77
76
  :aria-current="active && (index === items!.length - 1) ? 'page' : undefined"
78
77
  :class="style.link({ class: props.ui?.link, active: index === items!.length - 1, disabled: item.disabled, to: !!item.to })"
79
78
  >
80
- <slot :name="item.slot || 'item'" :item="item" :index="index">
81
- <slot :name="`${item.slot || 'item'}-leading`" :item="item" :active="index === items!.length - 1" :index="index">
79
+ <slot :name="((item.slot || 'item') as keyof BreadcrumbSlots<T>)" :item="item" :index="index">
80
+ <slot :name="(`${item.slot || 'item'}-leading` as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index">
82
81
  <span v-if="item.icon" :class="style.linkLeadingIcon({ class: [item.icon, props.ui?.linkLeadingIcon] })"></span>
83
82
  </slot>
84
83
 
85
- <span v-if="get(item, props.labelKey) || slots[`${item.slot || 'item'}-label`]" :class="style.linkLabel({ class: props.ui?.linkLabel })">
86
- <slot :name="`${item.slot || 'item'}-label`" :item="item" :active="index === items!.length - 1" :index="index">
84
+ <span v-if="get(item, props.labelKey) || slots[(`${item.slot || 'item'}-label` as keyof BreadcrumbSlots<T>)]" :class="style.linkLabel({ class: props.ui?.linkLabel })">
85
+ <slot :name="(`${item.slot || 'item'}-label` as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index">
87
86
  {{ get(item, props.labelKey) }}
88
87
  </slot>
89
88
  </span>
90
89
 
91
- <slot :name="`${item.slot || 'item'}-trailing`" :item="item" :active="index === items!.length - 1" :index="index"></slot>
90
+ <slot :name="(`${item.slot || 'item'}-trailing` as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index"></slot>
92
91
  </slot>
93
92
  </LinkBase>
94
93
  </Link>
@@ -46,11 +46,10 @@ const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponen
46
46
 
47
47
  const linkProps = useForwardProps(pickLinkProps(props))
48
48
 
49
- const { theme, createStyler } = useTheme()
49
+ const { generateStyle } = useTheme()
50
50
 
51
51
  const style = computed(() => {
52
- const styler = createStyler(theme.value.button)
53
- return styler({
52
+ return generateStyle('button', {
54
53
  ...props,
55
54
  size: size.value,
56
55
  groupOrientation: orientation.value,
@@ -35,11 +35,8 @@ defineSlots<ButtonGroupSlots>()
35
35
 
36
36
  provideButtonGroup(computed(() => props))
37
37
 
38
- const { theme, createStyler } = useTheme()
39
- const style = computed(() => {
40
- const styler = createStyler(theme.value.buttonGroup)
41
- return styler(props)
42
- })
38
+ const { generateStyle } = useTheme()
39
+ const style = computed(() => generateStyle('buttonGroup', props))
43
40
  </script>
44
41
 
45
42
  <template>
@@ -0,0 +1,185 @@
1
+ <script lang="ts">
2
+ import type { VariantProps } from '@byyuurin/ui-kit'
3
+ import type { DateValue } from '@internationalized/date'
4
+ import type { CalendarCellTriggerProps, CalendarRootEmits, CalendarRootProps, DateRange, RangeCalendarRootEmits, RangeCalendarRootProps } from 'reka-ui'
5
+ import type { calendar } from '../theme'
6
+ import type { ComponentAttrs } from '../types'
7
+
8
+ export interface CalendarEmits<R extends boolean, M extends boolean> extends Omit<CalendarRootEmits & RangeCalendarRootEmits, 'update:modelValue'> {
9
+ 'update:modelValue': [date: CalendarModelValue<R, M>]
10
+ }
11
+
12
+ export interface CalendarSlots {
13
+ 'heading'?: (props: { value: string }) => any
14
+ 'day'?: (props: Pick<CalendarCellTriggerProps, 'day'>) => any
15
+ 'week-day'?: (props: { day: string }) => any
16
+ }
17
+
18
+ type CalendarVariants = VariantProps<typeof calendar>
19
+
20
+ type CalendarDefaultValue<R extends boolean = false, M extends boolean = false> = R extends true
21
+ ? DateRange
22
+ : M extends true ? DateValue[] : DateValue
23
+
24
+ type CalendarModelValue<R extends boolean = false, M extends boolean = false> = R extends true
25
+ ? (DateRange | null)
26
+ : M extends true
27
+ ? (DateValue[] | undefined)
28
+ : (DateValue | undefined)
29
+
30
+ type _CalendarRootProps = Omit<CalendarRootProps, 'as' | 'asChild' | 'modelValue' | 'defaultValue' | 'dir' | 'locale' | 'calendarLabel' | 'multiple'>
31
+ type _RangeCalendarRootProps = Omit<RangeCalendarRootProps, 'as' | 'asChild' | 'modelValue' | 'defaultValue' | 'dir' | 'locale' | 'calendarLabel' | 'multiple'>
32
+
33
+ export interface CalendarProps<R extends boolean = false, M extends boolean = false> extends ComponentAttrs<typeof calendar>, _CalendarRootProps, _RangeCalendarRootProps {
34
+ /**
35
+ * The icon to use for the next year control.
36
+ * @default app.icons.chevronDoubleRight
37
+ */
38
+ nextYearIcon?: string
39
+ /**
40
+ * The icon to use for the next month control.
41
+ * @default app.icons.chevronRight
42
+ */
43
+ nextMonthIcon?: string
44
+ /**
45
+ * The icon to use for the previous year control.
46
+ * @default app.icons.chevronDoubleLeft
47
+ */
48
+ prevYearIcon?: string
49
+ /**
50
+ * The icon to use for the previous month control.
51
+ * @default app.icons.chevronLeft
52
+ */
53
+ prevMonthIcon?: string
54
+ /**
55
+ * @default "md"
56
+ */
57
+ size?: CalendarVariants['size']
58
+ /** Whether or not a range of dates can be selected */
59
+ range?: R & boolean
60
+ /** Whether or not multiple dates can be selected */
61
+ multiple?: M & boolean
62
+ /** Show month controls */
63
+ monthControls?: boolean
64
+ /** Show year controls */
65
+ yearControls?: boolean
66
+ defaultValue?: CalendarDefaultValue<R, M>
67
+ modelValue?: CalendarDefaultValue<R, M>
68
+ }
69
+ </script>
70
+
71
+ <script setup lang="ts" generic="R extends boolean, M extends boolean">
72
+ import { reactiveOmit } from '@vueuse/core'
73
+ import { useForwardPropsEmits } from 'reka-ui'
74
+ import { Calendar as BaseCalendar, RangeCalendar } from 'reka-ui/namespaced'
75
+ import { computed } from 'vue'
76
+ import { useLocale } from '../composables/useLocale'
77
+ import { useTheme } from '../composables/useTheme'
78
+ import Button from './Button.vue'
79
+
80
+ const props = withDefaults(defineProps<CalendarProps<R, M>>(), {
81
+ fixedWeeks: true,
82
+ monthControls: true,
83
+ yearControls: true,
84
+ })
85
+ const emit = defineEmits<CalendarEmits<R, M>>()
86
+ defineSlots<CalendarSlots>()
87
+
88
+ const rootProps = useForwardPropsEmits(reactiveOmit(props, 'range', 'modelValue', 'defaultValue', 'size', 'monthControls', 'yearControls', 'class', 'ui'), emit)
89
+
90
+ const { code: locale, dir, t } = useLocale()
91
+ const { theme, generateStyle } = useTheme()
92
+
93
+ const nextYearIcon = computed(() => props.nextYearIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronDoubleLeft : theme.value.app.icons.chevronDoubleRight))
94
+ const nextMonthIcon = computed(() => props.nextMonthIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronLeft : theme.value.app.icons.chevronRight))
95
+ const prevYearIcon = computed(() => props.prevYearIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronDoubleRight : theme.value.app.icons.chevronDoubleLeft))
96
+ const prevMonthIcon = computed(() => props.prevMonthIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronRight : theme.value.app.icons.chevronLeft))
97
+
98
+ function paginateYear(date: DateValue, sign: -1 | 1) {
99
+ if (sign === -1)
100
+ return date.subtract({ years: 1 })
101
+
102
+ return date.add({ years: 1 })
103
+ }
104
+
105
+ const Calendar = computed(() => props.range ? RangeCalendar : BaseCalendar)
106
+
107
+ const style = computed(() => generateStyle('calendar', props))
108
+ </script>
109
+
110
+ <template>
111
+ <Calendar.Root
112
+ v-slot="{ weekDays, grid }"
113
+ v-bind="rootProps"
114
+ :model-value="props.modelValue"
115
+ :default-value="props.defaultValue"
116
+ :locale="locale"
117
+ :dir="dir"
118
+ :class="style.root({ class: [props.class, props.ui?.root] })"
119
+ >
120
+ <Calendar.Header :class="style.header({ class: props.ui?.header })">
121
+ <Calendar.Prev v-if="props.yearControls" :prev-page="date => paginateYear(date, -1)" :aria-label="t('calendar.prevYear')" as-child>
122
+ <Button :icon="prevYearIcon" :size="props.size" variant="ghost" />
123
+ </Calendar.Prev>
124
+ <Calendar.Prev v-if="props.monthControls" :aria-label="t('calendar.prevMonth')" as-child>
125
+ <Button :icon="prevMonthIcon" :size="props.size" variant="ghost" />
126
+ </Calendar.Prev>
127
+
128
+ <Calendar.Heading v-slot="{ headingValue }" :class="style.heading({ class: props.ui?.heading })">
129
+ <slot name="heading" :value="headingValue">
130
+ {{ headingValue }}
131
+ </slot>
132
+ </Calendar.Heading>
133
+ <Calendar.Next v-if="props.monthControls" :aria-label="t('calendar.nextMonth')" as-child>
134
+ <Button :icon="nextMonthIcon" :size="props.size" variant="ghost" />
135
+ </Calendar.Next>
136
+ <Calendar.Next v-if="props.yearControls" :next-page="(date) => paginateYear(date, 1)" :aria-label="t('calendar.nextYear')" as-child>
137
+ <Button :icon="nextYearIcon" :size="props.size" variant="ghost" />
138
+ </Calendar.Next>
139
+ </Calendar.Header>
140
+ <div :class="style.body({ class: props.ui?.body })">
141
+ <Calendar.Grid
142
+ v-for="month in grid"
143
+ :key="month.value.toString()"
144
+ :class="style.grid({ class: props.ui?.grid })"
145
+ >
146
+ <Calendar.GridHead>
147
+ <Calendar.GridRow :class="style.gridWeekDaysRow({ class: props.ui?.gridWeekDaysRow })">
148
+ <Calendar.HeadCell v-for="day in weekDays" :key="day" :class="style.headCell({ class: props.ui?.headCell })">
149
+ <slot name="week-day" :day="day">
150
+ {{ day }}
151
+ </slot>
152
+ </Calendar.HeadCell>
153
+ </Calendar.GridRow>
154
+ </Calendar.GridHead>
155
+ <Calendar.GridBody :class="style.gridBody({ class: props.ui?.gridBody })">
156
+ <Calendar.GridRow
157
+ v-for="(weekDates, index) in month.rows"
158
+ :key="`weekDates-${index}`"
159
+ :class="style.gridRow({ class: props.ui?.gridRow })"
160
+ >
161
+ <Calendar.Cell
162
+ v-for="weekDate in weekDates"
163
+ :key="weekDate.toString()"
164
+ :date="weekDate"
165
+ :class="style.cell({ class: props.ui?.cell })"
166
+ >
167
+ <Calendar.CellTrigger
168
+ v-slot="{ disabled, unavailable }"
169
+ :day="weekDate"
170
+ :month="month.value"
171
+ as-child
172
+ >
173
+ <div :class="style.cellTrigger({ class: props.ui?.cellTrigger, disabled: disabled || unavailable })">
174
+ <slot name="day" :day="weekDate">
175
+ {{ weekDate.day }}
176
+ </slot>
177
+ </div>
178
+ </Calendar.CellTrigger>
179
+ </Calendar.Cell>
180
+ </Calendar.GridRow>
181
+ </Calendar.GridBody>
182
+ </Calendar.Grid>
183
+ </div>
184
+ </Calendar.Root>
185
+ </template>
@@ -35,11 +35,8 @@ import { useTheme } from '../composables/useTheme'
35
35
  const props = withDefaults(defineProps<CardProps>(), {})
36
36
  const slots = defineSlots<CardSlots>()
37
37
 
38
- const { theme, createStyler } = useTheme()
39
- const style = computed(() => {
40
- const styler = createStyler(theme.value.card)
41
- return styler(props)
42
- })
38
+ const { generateStyle } = useTheme()
39
+ const style = computed(() => generateStyle('card', props))
43
40
  </script>
44
41
 
45
42
  <template>