@rimelight/ui 0.0.25 → 0.0.27

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.
@@ -1,35 +1,47 @@
1
1
  <script setup lang="ts">
2
- import { computed } from "vue"
2
+ import { computed, useSlots } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
- import type { ComponentVariants } from "../../types"
5
+ import type { ComponentVariants, ComponentSlots } from "../../types"
6
6
  import sectionTheme from "../../themes/section.theme"
7
+ import type { RLVButtonProps } from "./RLVButton.vue"
8
+ import RLVIcon from "./RLVIcon.vue"
9
+ import RLVButton from "./RLVButton.vue"
7
10
 
8
11
  const section = scv(sectionTheme)
9
12
  type SectionVariants = ComponentVariants<typeof sectionTheme>
10
13
 
11
14
  export interface RLVSectionProps {
15
+ as?: any
12
16
  variant?: SectionVariants["variant"]
13
17
  headline?: string
14
18
  icon?: string
15
19
  title?: string
16
20
  description?: string
21
+ links?: RLVButtonProps[]
17
22
  orientation?: SectionVariants["orientation"]
18
23
  reverse?: boolean
19
24
  ctaVariant?: SectionVariants["ctaVariant"]
20
- ui?: Partial<Record<string, string>>
21
- class?: string
25
+ ui?: ComponentSlots<typeof sectionTheme>
26
+ class?: any
22
27
  }
23
28
 
24
29
  const {
30
+ as = "div",
25
31
  variant = "default",
26
32
  orientation = "vertical",
27
33
  reverse = false,
28
- ctaVariant = "outline",
34
+ ctaVariant = "solid",
35
+ ui: uiProp,
29
36
  class: className,
30
- ui: uiProp
37
+ headline,
38
+ title,
39
+ description,
40
+ links
31
41
  } = defineProps<RLVSectionProps>()
32
42
 
43
+ const slots = useSlots()
44
+
33
45
  const resolvedClasses = computed(() =>
34
46
  resolveClasses(
35
47
  section,
@@ -38,10 +50,10 @@ const resolvedClasses = computed(() =>
38
50
  orientation,
39
51
  reverse,
40
52
  ...(variant === "cta" && { ctaVariant }),
41
- headline: false,
42
- title: false,
43
- description: false,
44
- body: false
53
+ headline: !!(slots.headline || headline),
54
+ title: !!(slots.title || title),
55
+ description: !!(slots.description || description),
56
+ body: !!slots.body
45
57
  },
46
58
  useUi("section", uiProp),
47
59
  className
@@ -50,8 +62,14 @@ const resolvedClasses = computed(() =>
50
62
  </script>
51
63
 
52
64
  <template>
53
- <div data-slot="rlv-section" :class="[resolvedClasses.root]" v-bind="$attrs">
54
- <slot name="background">
65
+ <component
66
+ :is="as"
67
+ data-slot="root"
68
+ :data-orientation="orientation"
69
+ :class="[resolvedClasses.root]"
70
+ v-bind="$attrs"
71
+ >
72
+ <slot v-if="$slots.background" name="background">
55
73
  <div :class="resolvedClasses.background" data-slot="background">
56
74
  <slot name="background" />
57
75
  </div>
@@ -59,40 +77,90 @@ const resolvedClasses = computed(() =>
59
77
 
60
78
  <slot name="top" />
61
79
 
62
- <div :class="resolvedClasses.container">
63
- <div :class="resolvedClasses.wrapper">
64
- <div :class="resolvedClasses.header">
65
- <slot name="leading">
66
- <span v-if="icon" :class="resolvedClasses.leadingIcon" data-slot="leading-icon">
67
- <span :class="icon" aria-hidden="true" />
68
- </span>
69
- </slot>
80
+ <div data-slot="container" :class="resolvedClasses.container">
81
+ <div
82
+ v-if="
83
+ $slots.header ||
84
+ icon ||
85
+ headline ||
86
+ title ||
87
+ description ||
88
+ $slots.body ||
89
+ $slots.footer ||
90
+ $slots.links ||
91
+ links?.length
92
+ "
93
+ data-slot="wrapper"
94
+ :class="resolvedClasses.wrapper"
95
+ >
96
+ <div
97
+ v-if="$slots.header || icon || headline || title || description"
98
+ data-slot="header"
99
+ :class="resolvedClasses.header"
100
+ >
101
+ <slot name="header">
102
+ <div v-if="icon || $slots.leading" data-slot="leading" :class="resolvedClasses.leading">
103
+ <slot name="leading" :ui="resolvedClasses">
104
+ <RLVIcon
105
+ v-if="icon"
106
+ :name="icon"
107
+ size="md"
108
+ :ui="{ root: resolvedClasses.leadingIcon }"
109
+ />
110
+ </slot>
111
+ </div>
70
112
 
71
- <div v-if="headline" :class="resolvedClasses.headline">
72
- {{ headline }}
73
- </div>
113
+ <div v-if="headline" data-slot="headline" :class="resolvedClasses.headline">
114
+ <slot name="headline">
115
+ {{ headline }}
116
+ </slot>
117
+ </div>
74
118
 
75
- <h2 v-if="title" :class="resolvedClasses.title">
76
- {{ title }}
77
- </h2>
119
+ <component
120
+ :is="variant === 'hero' ? 'h1' : 'h2'"
121
+ v-if="title"
122
+ data-slot="title"
123
+ :class="resolvedClasses.title"
124
+ >
125
+ <slot name="title">
126
+ {{ title }}
127
+ </slot>
128
+ </component>
78
129
 
79
- <div v-if="description" :class="resolvedClasses.description">
80
- {{ description }}
81
- </div>
130
+ <div v-if="description" data-slot="description" :class="resolvedClasses.description">
131
+ <slot name="description">
132
+ {{ description }}
133
+ </slot>
134
+ </div>
135
+ </slot>
82
136
  </div>
83
137
 
84
- <div :class="resolvedClasses.body">
138
+ <div v-if="$slots.body" data-slot="body" :class="resolvedClasses.body">
85
139
  <slot name="body" />
86
140
  </div>
87
141
 
88
- <div :class="resolvedClasses.footer">
89
- <slot name="links" />
142
+ <div
143
+ v-if="$slots.footer || $slots.links || links?.length"
144
+ data-slot="footer"
145
+ :class="resolvedClasses.footer"
146
+ >
147
+ <slot name="footer">
148
+ <div
149
+ v-if="links?.length || $slots.links"
150
+ data-slot="links"
151
+ :class="resolvedClasses.links"
152
+ >
153
+ <RLVButton v-for="(link, index) in links" :key="index" size="lg" v-bind="link" />
154
+ <slot name="links" />
155
+ </div>
156
+ </slot>
90
157
  </div>
91
158
  </div>
92
159
 
93
- <slot />
160
+ <slot v-if="$slots.default" />
161
+ <div v-else-if="orientation === 'horizontal'" class="hidden lg:block" />
94
162
  </div>
95
163
 
96
164
  <slot name="bottom" />
97
- </div>
165
+ </component>
98
166
  </template>
@@ -37,28 +37,28 @@ export default defineTheme({
37
37
  size: {
38
38
  xs: {
39
39
  root: "h-7 px-2xs text-xs [&_svg]:size-3.5",
40
- leadingIcon: "[&_svg]:size-3.5",
41
- trailingIcon: "[&_svg]:size-3.5"
40
+ leadingIcon: "[&_svg]:size-3.5 [&_span]:size-3.5",
41
+ trailingIcon: "[&_svg]:size-3.5 [&_span]:size-3.5"
42
42
  },
43
43
  sm: {
44
44
  root: "h-8 px-xs text-sm [&_svg]:size-4",
45
- leadingIcon: "[&_svg]:size-4",
46
- trailingIcon: "[&_svg]:size-4"
45
+ leadingIcon: "[&_svg]:size-4 [&_span]:size-4",
46
+ trailingIcon: "[&_svg]:size-4 [&_span]:size-4"
47
47
  },
48
48
  md: {
49
49
  root: "h-9 px-sm text-sm [&_svg]:size-4",
50
- leadingIcon: "[&_svg]:size-4",
51
- trailingIcon: "[&_svg]:size-4"
50
+ leadingIcon: "[&_svg]:size-4 [&_span]:size-4",
51
+ trailingIcon: "[&_svg]:size-4 [&_span]:size-4"
52
52
  },
53
53
  lg: {
54
54
  root: "h-10 px-md text-base [&_svg]:size-4.5",
55
- leadingIcon: "[&_svg]:size-4.5",
56
- trailingIcon: "[&_svg]:size-4.5"
55
+ leadingIcon: "[&_svg]:size-4.5 [&_span]:size-4.5",
56
+ trailingIcon: "[&_svg]:size-4.5 [&_span]:size-4.5"
57
57
  },
58
58
  xl: {
59
59
  root: "h-11 px-lg text-base [&_svg]:size-5",
60
- leadingIcon: "[&_svg]:size-5",
61
- trailingIcon: "[&_svg]:size-5"
60
+ leadingIcon: "[&_svg]:size-5 [&_span]:size-5",
61
+ trailingIcon: "[&_svg]:size-5 [&_span]:size-5"
62
62
  }
63
63
  },
64
64
  block: {
@@ -13,70 +13,53 @@ export default defineTheme({
13
13
  "title",
14
14
  "description",
15
15
  "body",
16
- "features",
17
16
  "footer",
18
17
  "links"
19
18
  ],
20
19
  base: {
21
20
  root: "relative isolate",
22
21
  background: "absolute inset-0 -z-1 overflow-hidden",
23
- container: "flex flex-col lg:grid gap-8 sm:gap-16",
22
+ container: "mx-auto w-full max-w-90rem px-md flex flex-col lg:grid",
24
23
  wrapper: "",
25
24
  header: "",
26
25
  leading: "flex items-center mb-6",
27
26
  leadingIcon: "size-10 shrink-0 text-primary",
28
- headline: "mb-3",
27
+ headline: "",
29
28
  title: "text-pretty tracking-tight font-bold text-highlighted",
30
29
  description: "text-muted",
31
- body: "mt-8",
32
- features: "grid gap-8",
33
- footer: "mt-8",
34
- links: "flex flex-wrap gap-x-6 gap-y-3"
30
+ body: "",
31
+ footer: "",
32
+ links: "flex flex-wrap"
35
33
  },
36
34
  variants: {
37
35
  variant: {
38
36
  default: {
39
- container: "py-16 sm:py-24 lg:py-32",
37
+ container: "py-16 sm:py-24 lg:py-32 gap-8 sm:gap-16",
38
+ headline: "mb-3",
40
39
  title: "text-3xl sm:text-4xl lg:text-5xl",
41
40
  description: "text-base sm:text-lg",
42
- features: "sm:grid-cols-2 lg:grid-cols-3"
41
+ body: "mt-8",
42
+ footer: "mt-8",
43
+ links: "gap-x-6 gap-y-3"
43
44
  },
44
45
  hero: {
45
46
  container: "py-24 sm:py-32 lg:py-40 gap-16 sm:gap-y-24",
47
+ headline: "mb-4",
46
48
  title: "text-5xl sm:text-7xl",
47
49
  description: "text-lg sm:text-xl/8",
48
- headline: "mb-4",
49
50
  leading: "mb-6",
50
51
  body: "mt-10",
51
52
  footer: "mt-10",
52
- links: "mt-10"
53
+ links: "gap-x-6 gap-y-3"
53
54
  },
54
55
  cta: {
55
56
  root: "rounded-xl overflow-hidden",
56
- container: "px-6 py-12 sm:px-12 sm:py-24 lg:px-16 lg:py-24 gap-8 sm:gap-16",
57
+ container: "lg:grid px-6 py-12 sm:px-12 sm:py-24 lg:px-16 lg:py-24 gap-8 sm:gap-16",
57
58
  title: "text-3xl sm:text-4xl",
58
- description: "text-base sm:text-lg"
59
- }
60
- },
61
- orientation: {
62
- horizontal: {
63
- container: "lg:grid-cols-2 lg:items-center",
64
- description: "text-pretty",
65
- features: "gap-4"
66
- },
67
- vertical: {
68
- container: "",
69
- headline: "justify-center",
70
- leading: "justify-center",
71
- title: "text-center",
72
- description: "text-center text-balance",
73
- links: "justify-center",
74
- features: ""
75
- }
76
- },
77
- reverse: {
78
- true: {
79
- wrapper: "order-last"
59
+ description: "text-base sm:text-lg text-muted",
60
+ body: "mt-8",
61
+ footer: "mt-8",
62
+ links: "gap-x-6 gap-y-3"
80
63
  }
81
64
  },
82
65
  ctaVariant: {
@@ -101,6 +84,25 @@ export default defineTheme({
101
84
  description: "text-muted"
102
85
  }
103
86
  },
87
+ orientation: {
88
+ horizontal: {
89
+ container: "lg:grid-cols-2 lg:items-center",
90
+ description: "text-pretty"
91
+ },
92
+ vertical: {
93
+ container: "",
94
+ headline: "justify-center",
95
+ leading: "justify-center",
96
+ title: "text-center",
97
+ description: "text-center text-balance",
98
+ links: "justify-center"
99
+ }
100
+ },
101
+ reverse: {
102
+ true: {
103
+ wrapper: "order-last"
104
+ }
105
+ },
104
106
  headline: {
105
107
  true: {
106
108
  headline: "font-semibold text-primary flex items-center gap-1.5"
@@ -180,6 +182,6 @@ export default defineTheme({
180
182
  defaultVariants: {
181
183
  variant: "default",
182
184
  orientation: "vertical",
183
- ctaVariant: "outline"
185
+ ctaVariant: "solid"
184
186
  }
185
187
  })
@@ -8,3 +8,7 @@ export type ComponentVariants<T extends { variants?: Record<string, Record<strin
8
8
  : keyof T["variants"][K]
9
9
  }
10
10
  : never
11
+
12
+ export type ComponentSlots<T extends { slots: readonly string[] }> = Partial<
13
+ Record<T["slots"][number], string>
14
+ >