@soave/ui 0.1.0 → 0.2.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 (74) hide show
  1. package/dist/adapters/css-variables.d.ts +2 -0
  2. package/dist/adapters/css-variables.mjs +228 -0
  3. package/dist/adapters/headless.d.ts +7 -0
  4. package/dist/adapters/headless.mjs +7 -0
  5. package/dist/adapters/index.d.ts +5 -0
  6. package/dist/adapters/index.mjs +11 -0
  7. package/dist/adapters/tailwind.d.ts +2 -0
  8. package/dist/adapters/tailwind.mjs +443 -0
  9. package/dist/adapters/types.d.ts +38 -0
  10. package/dist/adapters/types.mjs +10 -0
  11. package/dist/build.config.mjs +1 -1
  12. package/dist/components/ui/Alert.vue +18 -16
  13. package/dist/components/ui/AlertDescription.vue +13 -3
  14. package/dist/components/ui/AlertTitle.vue +13 -3
  15. package/dist/components/ui/Button.vue +30 -4
  16. package/dist/components/ui/Card.vue +27 -3
  17. package/dist/components/ui/CardContent.vue +13 -3
  18. package/dist/components/ui/CardDescription.vue +13 -3
  19. package/dist/components/ui/CardFooter.vue +13 -3
  20. package/dist/components/ui/CardHeader.vue +13 -3
  21. package/dist/components/ui/CardTitle.vue +13 -3
  22. package/dist/components/ui/Checkbox.vue +23 -2
  23. package/dist/components/ui/Dialog.vue +31 -9
  24. package/dist/components/ui/DialogDescription.vue +13 -3
  25. package/dist/components/ui/DialogFooter.vue +13 -3
  26. package/dist/components/ui/DialogHeader.vue +13 -3
  27. package/dist/components/ui/DialogTitle.vue +13 -3
  28. package/dist/components/ui/DropdownMenuContent.vue +16 -13
  29. package/dist/components/ui/DropdownMenuItem.vue +11 -17
  30. package/dist/components/ui/Input.vue +26 -3
  31. package/dist/components/ui/PopoverContent.vue +16 -12
  32. package/dist/components/ui/RadioGroup.vue +12 -7
  33. package/dist/components/ui/RadioItem.vue +31 -10
  34. package/dist/components/ui/Select.vue +8 -1
  35. package/dist/components/ui/SelectContent.vue +31 -5
  36. package/dist/components/ui/SelectItem.vue +20 -16
  37. package/dist/components/ui/SelectTrigger.vue +39 -7
  38. package/dist/components/ui/SelectValue.vue +13 -2
  39. package/dist/components/ui/Sheet.vue +32 -24
  40. package/dist/components/ui/SheetDescription.vue +13 -6
  41. package/dist/components/ui/SheetFooter.vue +13 -6
  42. package/dist/components/ui/SheetHeader.vue +13 -6
  43. package/dist/components/ui/SheetTitle.vue +13 -6
  44. package/dist/components/ui/Switch.vue +23 -3
  45. package/dist/components/ui/Textarea.vue +26 -3
  46. package/dist/components/ui/Toast.vue +38 -29
  47. package/dist/components/ui/Toaster.vue +12 -16
  48. package/dist/components/ui/TooltipContent.vue +18 -15
  49. package/dist/components/ui/UIProvider.vue +6 -2
  50. package/dist/composables/index.d.ts +1 -1
  51. package/dist/composables/index.mjs +1 -1
  52. package/dist/composables/useUIConfig.d.ts +16 -5
  53. package/dist/composables/useUIConfig.mjs +26 -9
  54. package/dist/index.d.ts +1 -0
  55. package/dist/index.mjs +1 -0
  56. package/dist/styles/css-variables.css +1 -0
  57. package/dist/styles/index.d.ts +1 -0
  58. package/dist/styles/index.mjs +1 -0
  59. package/dist/types/alert.d.ts +2 -0
  60. package/dist/types/card.d.ts +5 -0
  61. package/dist/types/composables.d.ts +122 -0
  62. package/dist/types/composables.mjs +0 -0
  63. package/dist/types/config.d.ts +8 -0
  64. package/dist/types/dialog.d.ts +7 -0
  65. package/dist/types/dropdown.d.ts +8 -0
  66. package/dist/types/index.d.ts +1 -0
  67. package/dist/types/index.mjs +1 -0
  68. package/dist/types/popover.d.ts +6 -0
  69. package/dist/types/radio.d.ts +4 -0
  70. package/dist/types/select.d.ts +21 -0
  71. package/dist/types/sheet.d.ts +19 -0
  72. package/dist/types/toast.d.ts +2 -0
  73. package/dist/types/tooltip.d.ts +6 -0
  74. package/package.json +9 -1
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <textarea
3
3
  :id="id"
4
- :class="composable.base_classes.value"
4
+ :class="[computed_classes, props.class]"
5
5
  :disabled="composable.is_disabled.value"
6
6
  :readonly="composable.is_readonly.value"
7
7
  :placeholder="placeholder"
@@ -15,20 +15,25 @@
15
15
  </template>
16
16
 
17
17
  <script setup lang="ts">
18
- import { toRef } from "vue"
18
+ import { toRef, computed } from "vue"
19
19
  import { useTextarea } from "../../composables/useTextarea"
20
+ import { useStyleAdapter, useUI } from "../../composables/useUIConfig"
20
21
  import type { TextareaProps } from "../../types/textarea"
22
+ import type { TextareaState } from "../../types/composables"
21
23
 
22
24
  interface Props extends TextareaProps {
23
25
  id?: string
24
26
  modelValue?: string
27
+ class?: string
28
+ unstyled?: boolean
25
29
  }
26
30
 
27
31
  const props = withDefaults(defineProps<Props>(), {
28
32
  rows: 3,
29
33
  resize: "vertical",
30
34
  disabled: false,
31
- readonly: false
35
+ readonly: false,
36
+ unstyled: false
32
37
  })
33
38
 
34
39
  const emit = defineEmits<{
@@ -36,8 +41,26 @@ const emit = defineEmits<{
36
41
  blur: [event: FocusEvent]
37
42
  }>()
38
43
 
44
+ const ui_config = useUI("input")
45
+ const style_adapter = useStyleAdapter()
39
46
  const composable = useTextarea(toRef(() => props))
40
47
 
48
+ // StyleAdapterからクラスを取得
49
+ const computed_classes = computed(() => {
50
+ if (props.unstyled) {
51
+ return ""
52
+ }
53
+
54
+ const state: TextareaState = {
55
+ size: props.size ?? ui_config.default_size,
56
+ disabled: composable.is_disabled.value,
57
+ readonly: composable.is_readonly.value,
58
+ error: props.error
59
+ }
60
+
61
+ return style_adapter.getClasses("textarea", state)
62
+ })
63
+
41
64
  const handleInput = (event: Event) => {
42
65
  const target = event.target as HTMLTextAreaElement
43
66
  emit("update:modelValue", target.value)
@@ -1,15 +1,15 @@
1
1
  <template>
2
2
  <div
3
- :class="cn(base_classes, variant_classes[variant], props.class)"
3
+ :class="[computed_classes, props.class]"
4
4
  :role="aria_role"
5
5
  :aria-live="aria_live"
6
6
  aria-atomic="true"
7
7
  >
8
8
  <div class="flex-1 space-y-1">
9
- <div v-if="title" class="text-sm font-semibold">
9
+ <div v-if="title" :class="title_classes">
10
10
  {{ title }}
11
11
  </div>
12
- <div v-if="description" class="text-sm opacity-90">
12
+ <div v-if="description" :class="description_classes">
13
13
  {{ description }}
14
14
  </div>
15
15
  </div>
@@ -18,7 +18,7 @@
18
18
  <button
19
19
  v-if="action"
20
20
  type="button"
21
- :class="action_button_classes"
21
+ :class="action_classes"
22
22
  @click="action.onClick"
23
23
  >
24
24
  {{ action.label }}
@@ -27,7 +27,7 @@
27
27
  <button
28
28
  v-if="dismissible"
29
29
  type="button"
30
- :class="dismiss_button_classes"
30
+ :class="dismiss_classes"
31
31
  aria-label="Dismiss"
32
32
  @click="emit('dismiss')"
33
33
  >
@@ -52,8 +52,9 @@
52
52
 
53
53
  <script setup lang="ts">
54
54
  import { computed } from "vue"
55
- import { cn } from "../../utils/cn"
55
+ import { useStyleAdapter } from "../../composables"
56
56
  import type { ToastVariant, ToastAction } from "../../types/toast"
57
+ import type { ToastState } from "../../types/composables"
57
58
 
58
59
  export interface Props {
59
60
  title?: string
@@ -62,26 +63,48 @@ export interface Props {
62
63
  dismissible?: boolean
63
64
  action?: ToastAction
64
65
  class?: string
66
+ unstyled?: boolean
65
67
  }
66
68
 
67
69
  const props = withDefaults(defineProps<Props>(), {
68
70
  variant: "default",
69
- dismissible: true
71
+ dismissible: true,
72
+ unstyled: false
70
73
  })
71
74
 
72
75
  const emit = defineEmits<{
73
76
  dismiss: []
74
77
  }>()
75
78
 
76
- const base_classes = "pointer-events-auto flex items-start gap-4 rounded-lg border p-4 shadow-lg transition-all"
79
+ const style_adapter = useStyleAdapter()
77
80
 
78
- const variant_classes: Record<ToastVariant, string> = {
79
- default: "bg-background text-foreground border-border",
80
- success: "bg-green-50 text-green-900 border-green-200 dark:bg-green-950 dark:text-green-100 dark:border-green-800",
81
- error: "bg-red-50 text-red-900 border-red-200 dark:bg-red-950 dark:text-red-100 dark:border-red-800",
82
- warning: "bg-yellow-50 text-yellow-900 border-yellow-200 dark:bg-yellow-950 dark:text-yellow-100 dark:border-yellow-800",
83
- info: "bg-blue-50 text-blue-900 border-blue-200 dark:bg-blue-950 dark:text-blue-100 dark:border-blue-800"
84
- }
81
+ const computed_classes = computed(() => {
82
+ if (props.unstyled) return ""
83
+ const state: ToastState = {
84
+ variant: props.variant
85
+ }
86
+ return style_adapter.getClasses("toast", state)
87
+ })
88
+
89
+ const title_classes = computed(() => {
90
+ if (props.unstyled) return ""
91
+ return style_adapter.getClasses("toast-title", {})
92
+ })
93
+
94
+ const description_classes = computed(() => {
95
+ if (props.unstyled) return ""
96
+ return style_adapter.getClasses("toast-description", {})
97
+ })
98
+
99
+ const action_classes = computed(() => {
100
+ if (props.unstyled) return ""
101
+ return style_adapter.getClasses("toast-action", {})
102
+ })
103
+
104
+ const dismiss_classes = computed(() => {
105
+ if (props.unstyled) return ""
106
+ return style_adapter.getClasses("toast-dismiss", {})
107
+ })
85
108
 
86
109
  const aria_role = computed(() => {
87
110
  return props.variant === "error" ? "alert" : "status"
@@ -90,18 +113,4 @@ const aria_role = computed(() => {
90
113
  const aria_live = computed(() => {
91
114
  return props.variant === "error" ? "assertive" : "polite"
92
115
  })
93
-
94
- const action_button_classes = cn(
95
- "inline-flex items-center justify-center rounded-md text-sm font-medium",
96
- "h-8 px-3 ring-offset-background transition-colors",
97
- "hover:bg-secondary focus-visible:outline-none focus-visible:ring-2",
98
- "focus-visible:ring-ring focus-visible:ring-offset-2"
99
- )
100
-
101
- const dismiss_button_classes = cn(
102
- "inline-flex items-center justify-center rounded-md",
103
- "h-6 w-6 shrink-0 opacity-70 transition-opacity",
104
- "hover:opacity-100 focus-visible:outline-none focus-visible:ring-2",
105
- "focus-visible:ring-ring"
106
- )
107
116
  </script>
@@ -1,13 +1,13 @@
1
1
  <template>
2
2
  <Teleport to="body">
3
3
  <div
4
- :class="cn(container_classes, position_classes[position], props.class)"
4
+ :class="[computed_classes, props.class]"
5
5
  aria-label="Notifications"
6
6
  >
7
7
  <TransitionGroup
8
8
  name="toast"
9
9
  tag="div"
10
- :class="cn('flex flex-col', gap_class)"
10
+ class="flex flex-col gap-2"
11
11
  >
12
12
  <Toast
13
13
  v-for="toast in visible_toasts"
@@ -17,6 +17,7 @@
17
17
  :variant="toast.variant"
18
18
  :dismissible="toast.dismissible"
19
19
  :action="toast.action"
20
+ :unstyled="unstyled"
20
21
  @dismiss="handleDismiss(toast.id)"
21
22
  />
22
23
  </TransitionGroup>
@@ -26,7 +27,7 @@
26
27
 
27
28
  <script setup lang="ts">
28
29
  import { computed, ref, watchEffect } from "vue"
29
- import { cn } from "../../utils/cn"
30
+ import { useStyleAdapter } from "../../composables"
30
31
  import { useToast } from "../../composables/useToast"
31
32
  import Toast from "./Toast.vue"
32
33
  import type { ToastPosition, Toast as ToastType } from "../../types/toast"
@@ -36,15 +37,18 @@ export interface Props {
36
37
  max_toasts?: number
37
38
  gap?: number
38
39
  class?: string
40
+ unstyled?: boolean
39
41
  }
40
42
 
41
43
  const props = withDefaults(defineProps<Props>(), {
42
44
  position: "bottom-right",
43
45
  max_toasts: 5,
44
- gap: 8
46
+ gap: 8,
47
+ unstyled: false
45
48
  })
46
49
 
47
50
  const { toasts, dismiss } = useToast()
51
+ const style_adapter = useStyleAdapter()
48
52
 
49
53
  const internal_toasts = ref<ToastType[]>([])
50
54
 
@@ -61,18 +65,10 @@ const handleDismiss = (id: string): void => {
61
65
  dismiss(id)
62
66
  }
63
67
 
64
- const container_classes = "fixed z-[100] flex pointer-events-none p-4"
65
-
66
- const position_classes: Record<ToastPosition, string> = {
67
- "top-left": "top-0 left-0 flex-col",
68
- "top-center": "top-0 left-1/2 -translate-x-1/2 flex-col items-center",
69
- "top-right": "top-0 right-0 flex-col items-end",
70
- "bottom-left": "bottom-0 left-0 flex-col-reverse",
71
- "bottom-center": "bottom-0 left-1/2 -translate-x-1/2 flex-col-reverse items-center",
72
- "bottom-right": "bottom-0 right-0 flex-col-reverse items-end"
73
- }
74
-
75
- const gap_class = computed(() => `gap-${props.gap / 4}`)
68
+ const computed_classes = computed(() => {
69
+ if (props.unstyled) return ""
70
+ return style_adapter.getClasses("toaster", { position: props.position })
71
+ })
76
72
  </script>
77
73
 
78
74
  <style scoped>
@@ -6,7 +6,7 @@
6
6
  :id="tooltip_id"
7
7
  role="tooltip"
8
8
  :style="position_styles"
9
- :class="cn(base_classes, props.class)"
9
+ :class="[computed_classes, props.class]"
10
10
  @mouseenter="handleContentMouseEnter"
11
11
  @mouseleave="handleContentMouseLeave"
12
12
  >
@@ -16,15 +16,15 @@
16
16
  </template>
17
17
 
18
18
  <script setup lang="ts">
19
- import { inject, ref, watchEffect } from "vue"
20
- import { cn } from "../../utils/cn"
19
+ import { inject, ref, computed, watchEffect } from "vue"
20
+ import { useStyleAdapter } from "../../composables"
21
21
  import { TOOLTIP_CONTEXT_KEY } from "./Tooltip.vue"
22
+ import type { TooltipContentProps } from "../../types/tooltip"
23
+ import type { TooltipState } from "../../types/composables"
22
24
 
23
- export interface Props {
24
- class?: string
25
- }
26
-
27
- const props = defineProps<Props>()
25
+ const props = withDefaults(defineProps<TooltipContentProps>(), {
26
+ unstyled: false
27
+ })
28
28
 
29
29
  const context = inject(TOOLTIP_CONTEXT_KEY)
30
30
 
@@ -41,26 +41,29 @@ const {
41
41
  handleMouseLeave
42
42
  } = context
43
43
 
44
+ const style_adapter = useStyleAdapter()
44
45
  const content_element = ref<HTMLElement | null>(null)
45
46
 
46
47
  watchEffect(() => {
47
48
  content_ref.value = content_element.value
48
49
  })
49
50
 
51
+ const computed_classes = computed(() => {
52
+ if (props.unstyled) return ""
53
+ const state: TooltipState = {
54
+ is_open: is_open.value,
55
+ side: "top"
56
+ }
57
+ return style_adapter.getClasses("tooltip", state)
58
+ })
59
+
50
60
  const handleContentMouseEnter = (): void => {
51
- // Keep tooltip open when hovering over content
52
61
  handleMouseEnter()
53
62
  }
54
63
 
55
64
  const handleContentMouseLeave = (): void => {
56
65
  handleMouseLeave()
57
66
  }
58
-
59
- const base_classes = cn(
60
- "z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5",
61
- "text-xs text-primary-foreground shadow-md",
62
- "animate-in fade-in-0 zoom-in-95"
63
- )
64
67
  </script>
65
68
 
66
69
  <style scoped>
@@ -1,17 +1,21 @@
1
1
  <script setup lang="ts">
2
2
  import type { DeepPartial } from "../../types/utils"
3
3
  import type { UIConfig } from "../../types/config"
4
+ import type { StyleAdapter } from "../../adapters/types"
4
5
  import { useUIProvider } from "../../composables/useUIConfig"
6
+ import { tailwindAdapter } from "../../adapters/tailwind"
5
7
 
6
8
  interface UIProviderProps {
7
9
  config?: DeepPartial<UIConfig>
10
+ adapter?: StyleAdapter
8
11
  }
9
12
 
10
13
  const props = withDefaults(defineProps<UIProviderProps>(), {
11
- config: () => ({})
14
+ config: () => ({}),
15
+ adapter: () => tailwindAdapter
12
16
  })
13
17
 
14
- useUIProvider(props.config)
18
+ useUIProvider(props.config, props.adapter)
15
19
  </script>
16
20
 
17
21
  <template>
@@ -3,7 +3,7 @@ export { useInput } from "./useInput";
3
3
  export { useCard } from "./useCard";
4
4
  export { useDialog } from "./useDialog";
5
5
  export { useForm } from "./useForm";
6
- export { useUIProvider, useUI, useUIConfig, UI_CONFIG_KEY } from "./useUIConfig";
6
+ export { useUIProvider, useUI, useUIConfig, useStyleAdapter, UI_PROVIDER_KEY, UI_CONFIG_KEY } from "./useUIConfig";
7
7
  export { useCheckbox } from "./useCheckbox";
8
8
  export { useRadioItem } from "./useRadio";
9
9
  export { useSwitch } from "./useSwitch";
@@ -3,7 +3,7 @@ export { useInput } from "./useInput.mjs";
3
3
  export { useCard } from "./useCard.mjs";
4
4
  export { useDialog } from "./useDialog.mjs";
5
5
  export { useForm } from "./useForm.mjs";
6
- export { useUIProvider, useUI, useUIConfig, UI_CONFIG_KEY } from "./useUIConfig.mjs";
6
+ export { useUIProvider, useUI, useUIConfig, useStyleAdapter, UI_PROVIDER_KEY, UI_CONFIG_KEY } from "./useUIConfig.mjs";
7
7
  export { useCheckbox } from "./useCheckbox.mjs";
8
8
  export { useRadioItem } from "./useRadio.mjs";
9
9
  export { useSwitch } from "./useSwitch.mjs";
@@ -1,16 +1,22 @@
1
1
  import { type InjectionKey } from "vue";
2
2
  import type { DeepPartial } from "../types/utils";
3
- import type { UIConfig, ButtonConfig, InputConfig, CardConfig, AlertConfig } from "../types/config";
3
+ import type { UIConfig, UIProviderContext, ButtonConfig, InputConfig, CardConfig, AlertConfig } from "../types/config";
4
+ import type { StyleAdapter } from "../adapters/types";
4
5
  /**
5
- * UIConfig用のInjectionKey
6
+ * UIProviderContext用のInjectionKey
7
+ */
8
+ export declare const UI_PROVIDER_KEY: InjectionKey<UIProviderContext>;
9
+ /**
10
+ * @deprecated UI_CONFIG_KEY は後方互換性のために残されています。UI_PROVIDER_KEY を使用してください。
6
11
  */
7
12
  export declare const UI_CONFIG_KEY: InjectionKey<UIConfig>;
8
13
  /**
9
- * UIProviderで設定を提供する
14
+ * UIProviderで設定とStyleAdapterを提供する
10
15
  * @param config - 部分的なUI設定(デフォルト値とマージされる)
11
- * @returns マージされたUI設定
16
+ * @param adapter - 使用するStyleAdapter(デフォルト: tailwindAdapter)
17
+ * @returns UIProviderContext
12
18
  */
13
- export declare const useUIProvider: (config?: DeepPartial<UIConfig>) => UIConfig;
19
+ export declare const useUIProvider: (config?: DeepPartial<UIConfig>, adapter?: StyleAdapter) => UIProviderContext;
14
20
  /**
15
21
  * コンポーネント固有の設定を取得する
16
22
  * @param component - コンポーネント名
@@ -26,3 +32,8 @@ export declare function useUI(component: "alert"): Readonly<AlertConfig>;
26
32
  * @returns 読み取り専用の全体設定
27
33
  */
28
34
  export declare const useUIConfig: () => Readonly<UIConfig>;
35
+ /**
36
+ * Style Adapter を取得する
37
+ * @returns 現在設定されているStyleAdapter(デフォルト: tailwindAdapter)
38
+ */
39
+ export declare const useStyleAdapter: () => StyleAdapter;
@@ -1,36 +1,53 @@
1
1
  import { inject, provide, reactive, readonly } from "vue";
2
2
  import { DEFAULT_UI_CONFIG } from "../types/config.mjs";
3
+ import { tailwindAdapter } from "../adapters/tailwind.mjs";
3
4
  import { deepMerge } from "../utils/deepMerge.mjs";
4
5
  import { COMPONENT_ERRORS } from "../constants/errors.mjs";
5
6
  import { CONFIG_LOGS } from "../constants/logs.mjs";
7
+ export const UI_PROVIDER_KEY = Symbol("ui-provider");
6
8
  export const UI_CONFIG_KEY = Symbol("ui-config");
7
- export const useUIProvider = (config = {}) => {
9
+ export const useUIProvider = (config = {}, adapter = tailwindAdapter) => {
8
10
  const merged_config = reactive(
9
11
  deepMerge(DEFAULT_UI_CONFIG, config)
10
12
  );
13
+ const context = {
14
+ config: merged_config,
15
+ adapter
16
+ };
17
+ provide(UI_PROVIDER_KEY, context);
11
18
  provide(UI_CONFIG_KEY, merged_config);
12
19
  if (import.meta.env.DEV) {
13
- console.debug(CONFIG_LOGS.PROVIDER_INITIALIZED, merged_config);
20
+ console.debug(CONFIG_LOGS.PROVIDER_INITIALIZED, context);
14
21
  }
15
- return merged_config;
22
+ return context;
16
23
  };
17
24
  export function useUI(component) {
18
- const config = inject(UI_CONFIG_KEY, null);
19
- if (!config) {
25
+ const context = inject(UI_PROVIDER_KEY, null);
26
+ if (!context) {
20
27
  if (import.meta.env.DEV) {
21
28
  console.warn(COMPONENT_ERRORS.PROVIDER_NOT_FOUND);
22
29
  }
23
30
  return readonly(DEFAULT_UI_CONFIG[component]);
24
31
  }
25
- return readonly(config[component]);
32
+ return readonly(context.config[component]);
26
33
  }
27
34
  export const useUIConfig = () => {
28
- const config = inject(UI_CONFIG_KEY, null);
29
- if (!config) {
35
+ const context = inject(UI_PROVIDER_KEY, null);
36
+ if (!context) {
30
37
  if (import.meta.env.DEV) {
31
38
  console.warn(COMPONENT_ERRORS.PROVIDER_NOT_FOUND);
32
39
  }
33
40
  return readonly(DEFAULT_UI_CONFIG);
34
41
  }
35
- return readonly(config);
42
+ return readonly(context.config);
43
+ };
44
+ export const useStyleAdapter = () => {
45
+ const context = inject(UI_PROVIDER_KEY, null);
46
+ if (!context) {
47
+ if (import.meta.env.DEV) {
48
+ console.warn(COMPONENT_ERRORS.PROVIDER_NOT_FOUND);
49
+ }
50
+ return tailwindAdapter;
51
+ }
52
+ return context.adapter;
36
53
  };
package/dist/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export * from "./components/ui";
3
3
  export * from "./types";
4
4
  export * from "./utils";
5
5
  export * from "./constants";
6
+ export * from "./adapters";
package/dist/index.mjs CHANGED
@@ -3,3 +3,4 @@ export * from "./components/ui/index.mjs";
3
3
  export * from "./types/index.mjs";
4
4
  export * from "./utils/index.mjs";
5
5
  export * from "./constants/index.mjs";
6
+ export * from "./adapters/index.mjs";
@@ -0,0 +1 @@
1
+ :root{--color-primary:#0080ff;--color-primary-foreground:#fff;--color-primary-hover:#0073e6;--color-primary-active:#06c;--color-secondary:#f5f5f5;--color-secondary-foreground:#000;--color-secondary-hover:#e6e6e6;--color-accent:#141414;--color-accent-foreground:#fff;--color-destructive:#ef4343;--color-destructive-foreground:#fff;--color-ghost-hover:#f1f5f9;--color-input:#f1f5f9;--color-input-border:#dbe6f0;--color-input-error:#ef4343;--color-card:#fff;--color-card-border:#dbe6f0;--color-card-foreground:#000;--color-background:#fff;--color-foreground:#000;--color-muted:#f1f5f9;--color-muted-foreground:#4573a1;--color-popover:#fff;--color-popover-foreground:#000;--color-alert-info:#e6f2ff;--color-alert-info-border:#9cf;--color-alert-info-foreground:#004d99;--color-alert-success:#e6ffe6;--color-alert-success-border:#9f9;--color-alert-success-foreground:green;--color-alert-warning:#fff7e6;--color-alert-warning-border:#fd9;--color-alert-warning-foreground:#805500;--size-xs:0.75rem;--size-sm:0.875rem;--size-md:1rem;--size-lg:1.125rem;--size-xl:1.25rem;--space-0-5:0.125rem;--space-1:0.25rem;--space-2:0.5rem;--space-3:0.75rem;--space-4:1rem;--space-5:1.25rem;--space-6:1.5rem;--space-8:2rem;--space-10:2.5rem;--space-11:2.75rem;--space-12:3rem;--space-16:4rem;--radius-sm:0.375rem;--radius-md:0.5rem;--radius-lg:0.625rem;--radius-full:9999px;--border-width-1:1px;--border-width-2:2px;--font-family-base:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;--font-family-mono:"Courier New",monospace;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.2;--line-height-normal:1.5;--line-height-relaxed:1.75;--transition-fast:150ms cubic-bezier(0.16,1,0.3,1);--transition-normal:250ms cubic-bezier(0.16,1,0.3,1);--transition-slow:350ms cubic-bezier(0.16,1,0.3,1);--shadow-xs:0 1px 2px rgba(0,0,0,.05);--shadow-sm:0 1px 3px rgba(0,0,0,.1),0 1px 2px rgba(0,0,0,.06);--shadow-md:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--z-dropdown:50;--z-sticky:100;--z-fixed:200;--z-modal-backdrop:300;--z-modal:400;--z-popover:500;--z-tooltip:600}.button{align-items:center;border:none;border-radius:var(--radius-md);cursor:pointer;display:inline-flex;font-family:var(--font-family-base);font-size:var(--size-sm);font-weight:var(--font-weight-medium);gap:var(--space-2);justify-content:center;transition:all var(--transition-normal);white-space:nowrap}.button:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.button--primary{background-color:var(--color-primary);border:var(--border-width-1) solid var(--color-primary);color:var(--color-primary-foreground)}.button--primary:hover:not(:disabled){background-color:var(--color-primary-hover);border-color:var(--color-primary-hover)}.button--primary:active:not(:disabled){background-color:var(--color-primary-active)}.button--secondary{background-color:var(--color-secondary);border:var(--border-width-1) solid var(--color-input-border);color:var(--color-secondary-foreground)}.button--secondary:hover:not(:disabled){background-color:var(--color-secondary-hover)}.button--outline{background-color:transparent;border:var(--border-width-1) solid var(--color-input-border);color:var(--color-foreground)}.button--outline:hover:not(:disabled){background-color:var(--color-ghost-hover)}.button--ghost{background-color:transparent;border:none;color:var(--color-foreground)}.button--ghost:hover:not(:disabled){background-color:var(--color-ghost-hover)}.button--destructive{background-color:var(--color-destructive);border:var(--border-width-1) solid var(--color-destructive);color:var(--color-destructive-foreground)}.button--destructive:hover:not(:disabled){background-color:#ed2c2c}.button--sm{font-size:var(--size-sm);height:var(--space-8);padding:var(--space-2) var(--space-3)}.button--md{height:var(--space-10);padding:var(--space-2) var(--space-4)}.button--lg{font-size:var(--size-lg);height:var(--space-11);padding:var(--space-3) var(--space-8)}.button--disabled{cursor:not-allowed;opacity:.5;pointer-events:none}.button--loading{cursor:wait}.input{background-color:var(--color-background);border:var(--border-width-1) solid var(--color-input-border);border-radius:var(--radius-md);display:flex;font-family:var(--font-family-base);font-size:var(--size-sm);padding:var(--space-2) var(--space-3);transition:border-color var(--transition-fast),box-shadow var(--transition-fast);width:100%}.input::-moz-placeholder{color:var(--color-muted-foreground)}.input::placeholder{color:var(--color-muted-foreground)}.input:focus{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(0,128,255,.1);outline:none}.input--sm{font-size:var(--size-sm);height:var(--space-8);padding:var(--space-1) var(--space-2)}.input--md{height:var(--space-10);padding:var(--space-2) var(--space-3)}.input--lg{font-size:var(--size-lg);height:var(--space-11);padding:var(--space-3) var(--space-4)}.input--error{border-color:var(--color-input-error)}.input--error:focus{box-shadow:0 0 0 3px rgba(239,67,67,.1)}.input--disabled{cursor:not-allowed;opacity:.7}.input--disabled,.input--readonly{background-color:var(--color-muted)}.textarea{background-color:var(--color-background);border:var(--border-width-1) solid var(--color-input-border);border-radius:var(--radius-md);display:flex;font-family:var(--font-family-base);font-size:var(--size-sm);padding:var(--space-2) var(--space-3);resize:vertical;transition:border-color var(--transition-fast),box-shadow var(--transition-fast);width:100%}.textarea::-moz-placeholder{color:var(--color-muted-foreground)}.textarea::placeholder{color:var(--color-muted-foreground)}.textarea:focus{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(0,128,255,.1);outline:none}.textarea--sm{font-size:var(--size-sm);min-height:80px}.textarea--md{min-height:100px}.textarea--lg{font-size:var(--size-lg);min-height:120px}.textarea--error{border-color:var(--color-input-error)}.textarea--disabled{cursor:not-allowed;opacity:.7}.textarea--disabled,.textarea--readonly{background-color:var(--color-muted)}.card{background-color:var(--color-card);border:var(--border-width-1) solid var(--color-card-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm);color:var(--color-card-foreground)}.card--padding-sm{padding:var(--space-4)}.card--padding-md{padding:var(--space-6)}.card--padding-lg{padding:var(--space-8)}.checkbox{align-items:center;background-color:var(--color-background);border:var(--border-width-1) solid var(--color-primary);border-radius:var(--radius-sm);cursor:pointer;display:inline-flex;height:1rem;justify-content:center;transition:all var(--transition-fast);width:1rem}.checkbox:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.checkbox--checked,.checkbox--indeterminate{background-color:var(--color-primary);color:var(--color-primary-foreground)}.checkbox--disabled{cursor:not-allowed;opacity:.5}.radio{align-items:center;background-color:var(--color-background);border:var(--border-width-1) solid var(--color-primary);border-radius:var(--radius-full);cursor:pointer;display:inline-flex;height:1rem;justify-content:center;transition:all var(--transition-fast);width:1rem}.radio:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.radio--checked:after{background-color:var(--color-primary);border-radius:var(--radius-full);content:"";display:block;height:.5rem;width:.5rem}.radio--disabled{cursor:not-allowed;opacity:.5}.switch{align-items:center;background-color:var(--color-input-border);border-radius:var(--radius-full);cursor:pointer;display:inline-flex;height:1.5rem;padding:2px;transition:all var(--transition-fast);width:2.75rem}.switch:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.switch--checked{background-color:var(--color-primary)}.switch--disabled{cursor:not-allowed;opacity:.5}.select{align-items:center;background-color:var(--color-background);border:var(--border-width-1) solid var(--color-input-border);border-radius:var(--radius-md);cursor:pointer;display:flex;font-size:var(--size-sm);justify-content:space-between;padding:var(--space-2) var(--space-3);transition:border-color var(--transition-fast),box-shadow var(--transition-fast);width:100%}.select:focus{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(0,128,255,.1);outline:none}.select--sm{font-size:var(--size-sm);height:var(--space-8)}.select--md{height:var(--space-10)}.select--lg{font-size:var(--size-lg);height:var(--space-11)}.select--disabled{cursor:not-allowed;opacity:.5}.select__content{background-color:var(--color-popover);border:var(--border-width-1) solid var(--color-card-border);border-radius:var(--radius-md);box-shadow:var(--shadow-md);max-height:24rem;min-width:8rem;overflow:auto;position:absolute;z-index:var(--z-dropdown)}.select__item{align-items:center;cursor:pointer;display:flex;font-size:var(--size-sm);padding:var(--space-2) var(--space-3);transition:background-color var(--transition-fast);width:100%}.select__item:hover{background-color:var(--color-ghost-hover)}.dialog{background-color:var(--color-background);border:var(--border-width-1) solid var(--color-card-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);left:50%;max-width:32rem;padding:var(--space-6);position:fixed;top:50%;transform:translate(-50%,-50%);width:100%;z-index:var(--z-modal)}.dialog__overlay{background-color:rgba(0,0,0,.8);inset:0;position:fixed;z-index:var(--z-modal-backdrop)}.sheet{background-color:var(--color-background);box-shadow:var(--shadow-lg);padding:var(--space-6);position:fixed;transition:transform var(--transition-slow);z-index:var(--z-modal)}.sheet--top{border-bottom:var(--border-width-1) solid var(--color-card-border);inset:0 0 auto 0}.sheet--bottom{border-top:var(--border-width-1) solid var(--color-card-border);inset:auto 0 0 0}.sheet--left{border-right:var(--border-width-1) solid var(--color-card-border);inset:0 auto 0 0}.sheet--left,.sheet--right{height:100%;max-width:24rem;width:75%}.sheet--right{border-left:var(--border-width-1) solid var(--color-card-border);inset:0 0 0 auto}.sheet__overlay{background-color:rgba(0,0,0,.8);inset:0;position:fixed;z-index:var(--z-modal-backdrop)}.alert{border:var(--border-width-1) solid var(--color-card-border);border-radius:var(--radius-lg);padding:var(--space-4);position:relative;width:100%}.alert--default{background-color:var(--color-background);color:var(--color-foreground)}.alert--info{background-color:var(--color-alert-info);border-color:var(--color-alert-info-border);color:var(--color-alert-info-foreground)}.alert--success{background-color:var(--color-alert-success);border-color:var(--color-alert-success-border);color:var(--color-alert-success-foreground)}.alert--warning{background-color:var(--color-alert-warning);border-color:var(--color-alert-warning-border);color:var(--color-alert-warning-foreground)}.alert--destructive{background-color:rgba(239,67,67,.1);border-color:rgba(239,67,67,.5);color:var(--color-destructive)}.toast{align-items:center;border:var(--border-width-1) solid var(--color-card-border);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);display:flex;gap:var(--space-4);justify-content:space-between;overflow:hidden;padding:var(--space-6);padding-right:var(--space-8);width:100%}.toast--default{background-color:var(--color-background);color:var(--color-foreground)}.toast--success{background-color:var(--color-alert-success);border-color:var(--color-alert-success-border);color:var(--color-alert-success-foreground)}.toast--error{background-color:rgba(239,67,67,.1);border-color:var(--color-destructive);color:var(--color-destructive)}.toast--warning{background-color:var(--color-alert-warning);border-color:var(--color-alert-warning-border);color:var(--color-alert-warning-foreground)}.toast--info{background-color:var(--color-alert-info);border-color:var(--color-alert-info-border);color:var(--color-alert-info-foreground)}.tooltip{font-size:var(--size-sm);overflow:hidden;padding:var(--space-1) var(--space-3);z-index:var(--z-tooltip)}.popover,.tooltip{background-color:var(--color-popover);border:var(--border-width-1) solid var(--color-card-border);border-radius:var(--radius-md);box-shadow:var(--shadow-md);color:var(--color-popover-foreground)}.popover{padding:var(--space-4);width:18rem;z-index:var(--z-popover)}.dropdown{background-color:var(--color-popover);border:var(--border-width-1) solid var(--color-card-border);border-radius:var(--radius-md);box-shadow:var(--shadow-md);color:var(--color-popover-foreground);min-width:8rem;overflow:hidden;padding:var(--space-1);z-index:var(--z-dropdown)}.dropdown__item{align-items:center;border-radius:var(--radius-sm);cursor:pointer;display:flex;font-size:var(--size-sm);padding:var(--space-2);transition:background-color var(--transition-fast)}.dropdown__item:hover{background-color:var(--color-ghost-hover)}.label{font-size:var(--size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight)}@media (prefers-color-scheme:dark){:root{--color-primary:#39f;--color-primary-foreground:#000;--color-secondary:#25292c;--color-secondary-foreground:#fff;--color-card:#171a1c;--color-card-border:#2e3338;--color-card-foreground:#fff;--color-background:#131416;--color-foreground:#fff;--color-muted:#25292c;--color-muted-foreground:#9099a2;--color-input:#25292c;--color-input-border:#3a4045;--color-popover:#1c1f21;--color-popover-foreground:#fff;--color-ghost-hover:#2e3338;--color-alert-info:#00264d;--color-alert-info-border:#06c;--color-alert-info-foreground:#9cf;--color-alert-success:#004d00;--color-alert-success-border:#00b300;--color-alert-success-foreground:#9f9;--color-alert-warning:#4d3300;--color-alert-warning-border:#e69900;--color-alert-warning-foreground:#fd9}}[data-theme=dark]{--color-primary:#39f;--color-primary-foreground:#000;--color-secondary:#25292c;--color-secondary-foreground:#fff;--color-card:#171a1c;--color-card-border:#2e3338;--color-card-foreground:#fff;--color-background:#131416;--color-foreground:#fff;--color-muted:#25292c;--color-muted-foreground:#9099a2;--color-input:#25292c;--color-input-border:#3a4045;--color-popover:#1c1f21;--color-popover-foreground:#fff;--color-ghost-hover:#2e3338;--color-alert-info:#00264d;--color-alert-info-border:#06c;--color-alert-info-foreground:#9cf;--color-alert-success:#004d00;--color-alert-success-border:#00b300;--color-alert-success-foreground:#9f9;--color-alert-warning:#4d3300;--color-alert-warning-border:#e69900;--color-alert-warning-foreground:#fd9}[data-theme=light]{--color-primary:#0080ff;--color-primary-foreground:#fff;--color-secondary:#f5f5f5;--color-secondary-foreground:#000;--color-card:#fff;--color-card-border:#dbe6f0;--color-card-foreground:#000;--color-background:#fff;--color-foreground:#000;--color-muted:#f1f5f9;--color-muted-foreground:#4573a1;--color-input:#f1f5f9;--color-input-border:#dbe6f0;--color-popover:#fff;--color-popover-foreground:#000;--color-ghost-hover:#f1f5f9;--color-alert-info:#e6f2ff;--color-alert-info-border:#9cf;--color-alert-info-foreground:#004d99;--color-alert-success:#e6ffe6;--color-alert-success-border:#9f9;--color-alert-success-foreground:green;--color-alert-warning:#fff7e6;--color-alert-warning-border:#fd9;--color-alert-warning-foreground:#805500}
@@ -0,0 +1 @@
1
+ export declare const CSS_VARIABLES_PATH = "./css-variables.css";
@@ -0,0 +1 @@
1
+ export const CSS_VARIABLES_PATH = "./css-variables.css";
@@ -9,7 +9,9 @@ export interface AlertReturn {
9
9
  }
10
10
  export interface AlertTitleProps {
11
11
  class?: string;
12
+ unstyled?: boolean;
12
13
  }
13
14
  export interface AlertDescriptionProps {
14
15
  class?: string;
16
+ unstyled?: boolean;
15
17
  }
@@ -8,16 +8,21 @@ export interface CardReturn {
8
8
  }
9
9
  export interface CardHeaderProps {
10
10
  class?: string;
11
+ unstyled?: boolean;
11
12
  }
12
13
  export interface CardTitleProps {
13
14
  class?: string;
15
+ unstyled?: boolean;
14
16
  }
15
17
  export interface CardDescriptionProps {
16
18
  class?: string;
19
+ unstyled?: boolean;
17
20
  }
18
21
  export interface CardContentProps {
19
22
  class?: string;
23
+ unstyled?: boolean;
20
24
  }
21
25
  export interface CardFooterProps {
22
26
  class?: string;
27
+ unstyled?: boolean;
23
28
  }