@opensite/ui 0.0.4 → 0.0.6

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 (43) hide show
  1. package/dist/button.cjs +14 -13
  2. package/dist/button.cjs.map +1 -1
  3. package/dist/button.d.cts +1 -1
  4. package/dist/button.d.ts +1 -1
  5. package/dist/button.js +14 -13
  6. package/dist/button.js.map +1 -1
  7. package/dist/components.cjs +45 -15
  8. package/dist/components.cjs.map +1 -1
  9. package/dist/components.d.cts +1 -0
  10. package/dist/components.d.ts +1 -0
  11. package/dist/components.js +45 -16
  12. package/dist/components.js.map +1 -1
  13. package/dist/dynamic-icon.cjs +37 -0
  14. package/dist/dynamic-icon.cjs.map +1 -0
  15. package/dist/dynamic-icon.d.cts +46 -0
  16. package/dist/dynamic-icon.d.ts +46 -0
  17. package/dist/dynamic-icon.js +35 -0
  18. package/dist/dynamic-icon.js.map +1 -0
  19. package/dist/feature-showcase.cjs +418 -0
  20. package/dist/feature-showcase.cjs.map +1 -0
  21. package/dist/feature-showcase.d.cts +46 -0
  22. package/dist/feature-showcase.d.ts +46 -0
  23. package/dist/feature-showcase.js +394 -0
  24. package/dist/feature-showcase.js.map +1 -0
  25. package/dist/index.cjs +45 -15
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +2 -1
  28. package/dist/index.d.ts +2 -1
  29. package/dist/index.js +45 -16
  30. package/dist/index.js.map +1 -1
  31. package/dist/page-hero-banner.cjs +7 -2
  32. package/dist/page-hero-banner.cjs.map +1 -1
  33. package/dist/page-hero-banner.d.cts +1 -1
  34. package/dist/page-hero-banner.d.ts +1 -1
  35. package/dist/page-hero-banner.js +7 -2
  36. package/dist/page-hero-banner.js.map +1 -1
  37. package/dist/registry.cjs +461 -4
  38. package/dist/registry.cjs.map +1 -1
  39. package/dist/registry.js +442 -3
  40. package/dist/registry.js.map +1 -1
  41. package/dist/types.d.cts +68 -1
  42. package/dist/types.d.ts +68 -1
  43. package/package.json +12 -2
@@ -0,0 +1,418 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
6
+ var useEmblaCarousel = require('embla-carousel-react');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+ var reactSlot = require('@radix-ui/react-slot');
9
+ var classVarianceAuthority = require('class-variance-authority');
10
+
11
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
+
13
+ function _interopNamespace(e) {
14
+ if (e && e.__esModule) return e;
15
+ var n = Object.create(null);
16
+ if (e) {
17
+ Object.keys(e).forEach(function (k) {
18
+ if (k !== 'default') {
19
+ var d = Object.getOwnPropertyDescriptor(e, k);
20
+ Object.defineProperty(n, k, d.get ? d : {
21
+ enumerable: true,
22
+ get: function () { return e[k]; }
23
+ });
24
+ }
25
+ });
26
+ }
27
+ n.default = e;
28
+ return Object.freeze(n);
29
+ }
30
+
31
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
32
+ var useEmblaCarousel__default = /*#__PURE__*/_interopDefault(useEmblaCarousel);
33
+
34
+ // components/blocks/features/feature-showcase.tsx
35
+ function cn(...inputs) {
36
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
37
+ }
38
+ var ArrowLeft = ({
39
+ size = 24,
40
+ className,
41
+ strokeWidth = 2,
42
+ ...props
43
+ }) => {
44
+ return /* @__PURE__ */ jsxRuntime.jsx(
45
+ "svg",
46
+ {
47
+ xmlns: "http://www.w3.org/2000/svg",
48
+ width: size,
49
+ height: size,
50
+ viewBox: "0 0 24 24",
51
+ fill: "none",
52
+ stroke: "currentColor",
53
+ strokeWidth,
54
+ strokeLinecap: "round",
55
+ strokeLinejoin: "round",
56
+ className,
57
+ ...props,
58
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m12 19l-7-7l7-7m7 7H5" })
59
+ }
60
+ );
61
+ };
62
+ var ArrowRight = ({
63
+ size = 24,
64
+ className,
65
+ strokeWidth = 2,
66
+ ...props
67
+ }) => {
68
+ return /* @__PURE__ */ jsxRuntime.jsx(
69
+ "svg",
70
+ {
71
+ xmlns: "http://www.w3.org/2000/svg",
72
+ width: size,
73
+ height: size,
74
+ viewBox: "0 0 24 24",
75
+ fill: "none",
76
+ stroke: "currentColor",
77
+ strokeWidth,
78
+ strokeLinecap: "round",
79
+ strokeLinejoin: "round",
80
+ className,
81
+ ...props,
82
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14m-7-7l7 7l-7 7" })
83
+ }
84
+ );
85
+ };
86
+ var buttonVariants = classVarianceAuthority.cva(
87
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-button text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
88
+ {
89
+ variants: {
90
+ variant: {
91
+ default: "bg-[var(--button-default-bg,hsl(var(--primary)))] text-[var(--button-default-fg,hsl(var(--primary-foreground)))] hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
92
+ destructive: "bg-[var(--button-destructive-bg,hsl(var(--destructive)))] text-[var(--button-destructive-fg,white)] hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))] focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
93
+ outline: "border-[var(--button-outline-border-width,1px)] border-[var(--button-outline-border,hsl(var(--border)))] bg-[var(--button-outline-bg,hsl(var(--background)))] text-[var(--button-outline-fg,inherit)] shadow-xs hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))] dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
94
+ secondary: "bg-[var(--button-secondary-bg,hsl(var(--secondary)))] text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))] hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
95
+ ghost: "bg-[var(--button-ghost-bg,transparent)] text-[var(--button-ghost-fg,inherit)] hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))] dark:hover:bg-accent/50",
96
+ link: "text-[var(--button-link-fg,hsl(var(--primary)))] underline-offset-4 hover:underline"
97
+ },
98
+ size: {
99
+ default: "h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]",
100
+ sm: "h-[var(--button-height-sm,2rem)] rounded-button gap-1.5 px-[var(--button-padding-x-sm,0.75rem)] has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]",
101
+ md: "h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]",
102
+ lg: "h-[var(--button-height-lg,2.5rem)] rounded-button px-[var(--button-padding-x-lg,1.5rem)] has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]",
103
+ icon: "size-[var(--button-height-md,2.25rem)]",
104
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
105
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
106
+ }
107
+ },
108
+ defaultVariants: {
109
+ variant: "default",
110
+ size: "default"
111
+ }
112
+ }
113
+ );
114
+ function Button({
115
+ className,
116
+ variant = "default",
117
+ size = "default",
118
+ asChild = false,
119
+ ...props
120
+ }) {
121
+ const Comp = asChild ? reactSlot.Slot : "button";
122
+ return /* @__PURE__ */ jsxRuntime.jsx(
123
+ Comp,
124
+ {
125
+ "data-slot": "button",
126
+ "data-variant": variant,
127
+ "data-size": size,
128
+ className: cn(buttonVariants({ variant, size, className })),
129
+ ...props
130
+ }
131
+ );
132
+ }
133
+ var CarouselContext = React__namespace.createContext(null);
134
+ function useCarousel() {
135
+ const context = React__namespace.useContext(CarouselContext);
136
+ if (!context) {
137
+ throw new Error("useCarousel must be used within a <Carousel />");
138
+ }
139
+ return context;
140
+ }
141
+ function Carousel({
142
+ orientation = "horizontal",
143
+ opts,
144
+ setApi,
145
+ plugins,
146
+ className,
147
+ children,
148
+ ...props
149
+ }) {
150
+ const [carouselRef, api] = useEmblaCarousel__default.default(
151
+ {
152
+ ...opts,
153
+ axis: orientation === "horizontal" ? "x" : "y"
154
+ },
155
+ plugins
156
+ );
157
+ const [canScrollPrev, setCanScrollPrev] = React__namespace.useState(false);
158
+ const [canScrollNext, setCanScrollNext] = React__namespace.useState(false);
159
+ const onSelect = React__namespace.useCallback((api2) => {
160
+ if (!api2) return;
161
+ setCanScrollPrev(api2.canScrollPrev());
162
+ setCanScrollNext(api2.canScrollNext());
163
+ }, []);
164
+ const scrollPrev = React__namespace.useCallback(() => {
165
+ api?.scrollPrev();
166
+ }, [api]);
167
+ const scrollNext = React__namespace.useCallback(() => {
168
+ api?.scrollNext();
169
+ }, [api]);
170
+ const handleKeyDown = React__namespace.useCallback(
171
+ (event) => {
172
+ if (event.key === "ArrowLeft") {
173
+ event.preventDefault();
174
+ scrollPrev();
175
+ } else if (event.key === "ArrowRight") {
176
+ event.preventDefault();
177
+ scrollNext();
178
+ }
179
+ },
180
+ [scrollPrev, scrollNext]
181
+ );
182
+ React__namespace.useEffect(() => {
183
+ if (!api || !setApi) return;
184
+ setApi(api);
185
+ }, [api, setApi]);
186
+ React__namespace.useEffect(() => {
187
+ if (!api) return;
188
+ onSelect(api);
189
+ api.on("reInit", onSelect);
190
+ api.on("select", onSelect);
191
+ return () => {
192
+ api?.off("select", onSelect);
193
+ };
194
+ }, [api, onSelect]);
195
+ return /* @__PURE__ */ jsxRuntime.jsx(
196
+ CarouselContext.Provider,
197
+ {
198
+ value: {
199
+ carouselRef,
200
+ api,
201
+ opts,
202
+ orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
203
+ scrollPrev,
204
+ scrollNext,
205
+ canScrollPrev,
206
+ canScrollNext
207
+ },
208
+ children: /* @__PURE__ */ jsxRuntime.jsx(
209
+ "div",
210
+ {
211
+ onKeyDownCapture: handleKeyDown,
212
+ className: cn("relative", className),
213
+ role: "region",
214
+ "aria-roledescription": "carousel",
215
+ "data-slot": "carousel",
216
+ ...props,
217
+ children
218
+ }
219
+ )
220
+ }
221
+ );
222
+ }
223
+ function CarouselContent({ className, ...props }) {
224
+ const { carouselRef, orientation } = useCarousel();
225
+ return /* @__PURE__ */ jsxRuntime.jsx(
226
+ "div",
227
+ {
228
+ ref: carouselRef,
229
+ className: "overflow-hidden",
230
+ "data-slot": "carousel-content",
231
+ children: /* @__PURE__ */ jsxRuntime.jsx(
232
+ "div",
233
+ {
234
+ className: cn(
235
+ "flex",
236
+ orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
237
+ className
238
+ ),
239
+ ...props
240
+ }
241
+ )
242
+ }
243
+ );
244
+ }
245
+ function CarouselItem({ className, ...props }) {
246
+ const { orientation } = useCarousel();
247
+ return /* @__PURE__ */ jsxRuntime.jsx(
248
+ "div",
249
+ {
250
+ role: "group",
251
+ "aria-roledescription": "slide",
252
+ "data-slot": "carousel-item",
253
+ className: cn(
254
+ "min-w-0 shrink-0 grow-0 basis-full",
255
+ orientation === "horizontal" ? "pl-4" : "pt-4",
256
+ className
257
+ ),
258
+ ...props
259
+ }
260
+ );
261
+ }
262
+ function CarouselPrevious({
263
+ className,
264
+ variant = "outline",
265
+ size = "icon",
266
+ ...props
267
+ }) {
268
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel();
269
+ return /* @__PURE__ */ jsxRuntime.jsxs(
270
+ Button,
271
+ {
272
+ "data-slot": "carousel-previous",
273
+ variant,
274
+ size,
275
+ className: cn(
276
+ "absolute size-8 rounded-full",
277
+ orientation === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
278
+ className
279
+ ),
280
+ disabled: !canScrollPrev,
281
+ onClick: scrollPrev,
282
+ ...props,
283
+ children: [
284
+ /* @__PURE__ */ jsxRuntime.jsx(ArrowLeft, {}),
285
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Previous slide" })
286
+ ]
287
+ }
288
+ );
289
+ }
290
+ function CarouselNext({
291
+ className,
292
+ variant = "outline",
293
+ size = "icon",
294
+ ...props
295
+ }) {
296
+ const { orientation, scrollNext, canScrollNext } = useCarousel();
297
+ return /* @__PURE__ */ jsxRuntime.jsxs(
298
+ Button,
299
+ {
300
+ "data-slot": "carousel-next",
301
+ variant,
302
+ size,
303
+ className: cn(
304
+ "absolute size-8 rounded-full",
305
+ orientation === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
306
+ className
307
+ ),
308
+ disabled: !canScrollNext,
309
+ onClick: scrollNext,
310
+ ...props,
311
+ children: [
312
+ /* @__PURE__ */ jsxRuntime.jsx(ArrowRight, {}),
313
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Next slide" })
314
+ ]
315
+ }
316
+ );
317
+ }
318
+ function FeatureShowcase({
319
+ items,
320
+ children,
321
+ className,
322
+ carouselClassName,
323
+ slideClassName,
324
+ contentClassName,
325
+ mediaClassName,
326
+ arrowClassName,
327
+ equalizeOnMobile = true,
328
+ stretchMediaOnMobile = true
329
+ }) {
330
+ const baseArrowClassName = "bottom-4 top-auto size-12 translate-y-0 rounded-full border border-current bg-transparent text-current shadow-sm focus:ring-current focus:ring-offset-2 focus:ring-offset-transparent hover:bg-current/10 md:bottom-6";
331
+ const [mobileSlideHeight, setMobileSlideHeight] = React.useState(
332
+ null
333
+ );
334
+ const slideRefs = React.useRef([]);
335
+ const mediaWrapperClassName = equalizeOnMobile && stretchMediaOnMobile ? "flex-1 min-h-0 md:flex-none" : "";
336
+ React.useEffect(() => {
337
+ if (!equalizeOnMobile) {
338
+ setMobileSlideHeight(null);
339
+ return;
340
+ }
341
+ const updateHeights = () => {
342
+ if (typeof window === "undefined") return;
343
+ const isMobile = window.innerWidth < 768;
344
+ if (!isMobile) {
345
+ setMobileSlideHeight(null);
346
+ return;
347
+ }
348
+ const heights = slideRefs.current.slice(0, items.length).map((node) => node?.offsetHeight ?? 0);
349
+ const maxHeight = Math.max(...heights, 0);
350
+ if (maxHeight > 0) {
351
+ setMobileSlideHeight(
352
+ (prev) => prev === maxHeight ? prev : maxHeight
353
+ );
354
+ }
355
+ };
356
+ updateHeights();
357
+ window.addEventListener("resize", updateHeights);
358
+ let resizeObserver = null;
359
+ if (typeof ResizeObserver !== "undefined") {
360
+ resizeObserver = new ResizeObserver(updateHeights);
361
+ slideRefs.current.slice(0, items.length).forEach((node) => {
362
+ if (node) resizeObserver?.observe(node);
363
+ });
364
+ }
365
+ return () => {
366
+ window.removeEventListener("resize", updateHeights);
367
+ resizeObserver?.disconnect();
368
+ };
369
+ }, [equalizeOnMobile, items.length]);
370
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
371
+ children,
372
+ /* @__PURE__ */ jsxRuntime.jsxs(Carousel, { className: carouselClassName, children: [
373
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-18 md:pb-24", children: /* @__PURE__ */ jsxRuntime.jsx(CarouselContent, { className: "ease-in", children: items.map((item, itemIndex) => /* @__PURE__ */ jsxRuntime.jsx(CarouselItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(
374
+ "div",
375
+ {
376
+ ref: (node) => {
377
+ slideRefs.current[itemIndex] = node;
378
+ },
379
+ style: equalizeOnMobile && mobileSlideHeight ? { minHeight: mobileSlideHeight } : void 0,
380
+ className: cn(
381
+ "flex flex-col gap-8 md:gap-14 md:flex-row md:items-center md:justify-between",
382
+ slideClassName
383
+ ),
384
+ children: [
385
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full", contentClassName), children: item.content }),
386
+ /* @__PURE__ */ jsxRuntime.jsx(
387
+ "div",
388
+ {
389
+ className: cn(
390
+ "w-full",
391
+ mediaWrapperClassName,
392
+ mediaClassName
393
+ ),
394
+ children: item.mediaComponent
395
+ }
396
+ )
397
+ ]
398
+ }
399
+ ) }, `slide-${itemIndex}`)) }) }),
400
+ /* @__PURE__ */ jsxRuntime.jsx(
401
+ CarouselPrevious,
402
+ {
403
+ className: cn(baseArrowClassName, "left-4 md:left-6", arrowClassName)
404
+ }
405
+ ),
406
+ /* @__PURE__ */ jsxRuntime.jsx(
407
+ CarouselNext,
408
+ {
409
+ className: cn(baseArrowClassName, "right-4 md:right-6", arrowClassName)
410
+ }
411
+ )
412
+ ] })
413
+ ] });
414
+ }
415
+
416
+ exports.FeatureShowcase = FeatureShowcase;
417
+ //# sourceMappingURL=feature-showcase.cjs.map
418
+ //# sourceMappingURL=feature-showcase.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../lib/utils.ts","../icons/arrow-left.tsx","../icons/arrow-right.tsx","../components/ui/button.tsx","../components/ui/carousel.tsx","../components/blocks/features/feature-showcase.tsx"],"names":["twMerge","clsx","jsx","cva","Slot","React","useEmblaCarousel","api","jsxs","useState","useRef","useEffect"],"mappings":"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","file":"feature-showcase.cjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { SVGProps } from \"react\";\n\nexport interface IconProps extends SVGProps<SVGSVGElement> {\n size?: number | string;\n}\n\nexport const ArrowLeft = ({\n size = 24,\n className,\n strokeWidth = 2,\n ...props\n}: IconProps) => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n {...props}\n >\n <path d=\"m12 19l-7-7l7-7m7 7H5\" />\n </svg>\n );\n};\n","import type { SVGProps } from \"react\";\n\nexport interface IconProps extends SVGProps<SVGSVGElement> {\n size?: number | string;\n}\n\nexport const ArrowRight = ({\n size = 24,\n className,\n strokeWidth = 2,\n ...props\n}: IconProps) => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n {...props}\n >\n <path d=\"M5 12h14m-7-7l7 7l-7 7\" />\n </svg>\n );\n};\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-button text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-[var(--button-default-bg,hsl(var(--primary)))] text-[var(--button-default-fg,hsl(var(--primary-foreground)))] hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]\",\n destructive:\n \"bg-[var(--button-destructive-bg,hsl(var(--destructive)))] text-[var(--button-destructive-fg,white)] hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))] focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border-[var(--button-outline-border-width,1px)] border-[var(--button-outline-border,hsl(var(--border)))] bg-[var(--button-outline-bg,hsl(var(--background)))] text-[var(--button-outline-fg,inherit)] shadow-xs hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))] dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-[var(--button-secondary-bg,hsl(var(--secondary)))] text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))] hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]\",\n ghost:\n \"bg-[var(--button-ghost-bg,transparent)] text-[var(--button-ghost-fg,inherit)] hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))] dark:hover:bg-accent/50\",\n link: \"text-[var(--button-link-fg,hsl(var(--primary)))] underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n sm: \"h-[var(--button-height-sm,2rem)] rounded-button gap-1.5 px-[var(--button-padding-x-sm,0.75rem)] has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]\",\n md: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n lg: \"h-[var(--button-height-lg,2.5rem)] rounded-button px-[var(--button-padding-x-lg,1.5rem)] has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]\",\n icon: \"size-[var(--button-height-md,2.25rem)]\",\n \"icon-sm\": \"size-[var(--button-height-sm,2rem)]\",\n \"icon-lg\": \"size-[var(--button-height-lg,2.5rem)]\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\"\nimport { ArrowLeft } from \"../../icons/arrow-left\"\nimport { ArrowRight } from \"../../icons/arrow-right\"\n\nimport { cn } from \"../../lib/utils\"\nimport { Button } from \"./button\"\n\ntype CarouselApi = UseEmblaCarouselType[1]\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\ntype CarouselOptions = UseCarouselParameters[0]\ntype CarouselPlugin = UseCarouselParameters[1]\n\ntype CarouselProps = {\n opts?: CarouselOptions\n plugins?: CarouselPlugin\n orientation?: \"horizontal\" | \"vertical\"\n setApi?: (api: CarouselApi) => void\n}\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0]\n api: ReturnType<typeof useEmblaCarousel>[1]\n scrollPrev: () => void\n scrollNext: () => void\n canScrollPrev: boolean\n canScrollNext: boolean\n} & CarouselProps\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext)\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\")\n }\n\n return context\n}\n\nfunction Carousel({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins\n )\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\n const [canScrollNext, setCanScrollNext] = React.useState(false)\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n if (!api) return\n setCanScrollPrev(api.canScrollPrev())\n setCanScrollNext(api.canScrollNext())\n }, [])\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev()\n }, [api])\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext()\n }, [api])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault()\n scrollPrev()\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault()\n scrollNext()\n }\n },\n [scrollPrev, scrollNext]\n )\n\n React.useEffect(() => {\n if (!api || !setApi) return\n setApi(api)\n }, [api, setApi])\n\n React.useEffect(() => {\n if (!api) return\n onSelect(api)\n api.on(\"reInit\", onSelect)\n api.on(\"select\", onSelect)\n\n return () => {\n api?.off(\"select\", onSelect)\n }\n }, [api, onSelect])\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n )\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n const { carouselRef, orientation } = useCarousel()\n\n return (\n <div\n ref={carouselRef}\n className=\"overflow-hidden\"\n data-slot=\"carousel-content\"\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel()\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -left-12 -translate-y-1/2\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <ArrowLeft />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n )\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollNext, canScrollNext } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -right-12 -translate-y-1/2\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <ArrowRight />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n )\n}\n\nexport {\n type CarouselApi,\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselPrevious,\n CarouselNext,\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport {\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n} from \"../../ui/carousel\";\n\nexport interface FeatureShowcaseItem {\n content: ReactNode;\n mediaComponent: ReactNode;\n}\n\nexport interface FeatureShowcaseProps {\n items: FeatureShowcaseItem[];\n children?: ReactNode;\n className?: string;\n carouselClassName?: string;\n slideClassName?: string;\n contentClassName?: string;\n mediaClassName?: string;\n arrowClassName?: string;\n equalizeOnMobile?: boolean;\n stretchMediaOnMobile?: boolean;\n}\n\n/**\n * Feature Showcase component with carousel navigation\n *\n * Displays feature content with media in a carousel format. Each slide shows\n * content (text, headings) alongside media (images, videos). Features mobile\n * height equalization for consistent slide heights and customizable styling.\n *\n * @example\n * ```tsx\n * <FeatureShowcase\n * items={[\n * {\n * content: <div><h3>Feature 1</h3><p>Description</p></div>,\n * mediaComponent: <img src=\"/feature1.jpg\" alt=\"Feature 1\" />\n * },\n * {\n * content: <div><h3>Feature 2</h3><p>Description</p></div>,\n * mediaComponent: <img src=\"/feature2.jpg\" alt=\"Feature 2\" />\n * }\n * ]}\n * />\n * ```\n */\nexport function FeatureShowcase({\n items,\n children,\n className,\n carouselClassName,\n slideClassName,\n contentClassName,\n mediaClassName,\n arrowClassName,\n equalizeOnMobile = true,\n stretchMediaOnMobile = true,\n}: FeatureShowcaseProps) {\n const baseArrowClassName =\n \"bottom-4 top-auto size-12 translate-y-0 rounded-full border border-current bg-transparent text-current shadow-sm focus:ring-current focus:ring-offset-2 focus:ring-offset-transparent hover:bg-current/10 md:bottom-6\";\n const [mobileSlideHeight, setMobileSlideHeight] = useState<number | null>(\n null\n );\n const slideRefs = useRef<Array<HTMLDivElement | null>>([]);\n const mediaWrapperClassName =\n equalizeOnMobile && stretchMediaOnMobile\n ? \"flex-1 min-h-0 md:flex-none\"\n : \"\";\n\n useEffect(() => {\n if (!equalizeOnMobile) {\n setMobileSlideHeight(null);\n return;\n }\n\n const updateHeights = () => {\n if (typeof window === \"undefined\") return;\n const isMobile = window.innerWidth < 768;\n\n if (!isMobile) {\n setMobileSlideHeight(null);\n return;\n }\n\n const heights = slideRefs.current\n .slice(0, items.length)\n .map((node) => node?.offsetHeight ?? 0);\n const maxHeight = Math.max(...heights, 0);\n\n if (maxHeight > 0) {\n setMobileSlideHeight((prev) =>\n prev === maxHeight ? prev : maxHeight\n );\n }\n };\n\n updateHeights();\n window.addEventListener(\"resize\", updateHeights);\n\n let resizeObserver: ResizeObserver | null = null;\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver = new ResizeObserver(updateHeights);\n slideRefs.current.slice(0, items.length).forEach((node) => {\n if (node) resizeObserver?.observe(node);\n });\n }\n\n return () => {\n window.removeEventListener(\"resize\", updateHeights);\n resizeObserver?.disconnect();\n };\n }, [equalizeOnMobile, items.length]);\n\n return (\n <div className={className}>\n {children}\n <Carousel className={carouselClassName}>\n <div className=\"pb-18 md:pb-24\">\n <CarouselContent className=\"ease-in\">\n {items.map((item, itemIndex) => (\n <CarouselItem key={`slide-${itemIndex}`}>\n <div\n ref={(node) => {\n slideRefs.current[itemIndex] = node;\n }}\n style={\n equalizeOnMobile && mobileSlideHeight\n ? { minHeight: mobileSlideHeight }\n : undefined\n }\n className={cn(\n \"flex flex-col gap-8 md:gap-14 md:flex-row md:items-center md:justify-between\",\n slideClassName\n )}\n >\n <div className={cn(\"w-full\", contentClassName)}>\n {item.content}\n </div>\n <div\n className={cn(\n \"w-full\",\n mediaWrapperClassName,\n mediaClassName\n )}\n >\n {item.mediaComponent}\n </div>\n </div>\n </CarouselItem>\n ))}\n </CarouselContent>\n </div>\n <CarouselPrevious\n className={cn(baseArrowClassName, \"left-4 md:left-6\", arrowClassName)}\n />\n <CarouselNext\n className={cn(baseArrowClassName, \"right-4 md:right-6\", arrowClassName)}\n />\n </Carousel>\n </div>\n );\n}\n"]}
@@ -0,0 +1,46 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ export { FeatureShowcaseItem, FeatureShowcaseProps } from './types.cjs';
4
+
5
+ interface FeatureShowcaseItem {
6
+ content: ReactNode;
7
+ mediaComponent: ReactNode;
8
+ }
9
+ interface FeatureShowcaseProps {
10
+ items: FeatureShowcaseItem[];
11
+ children?: ReactNode;
12
+ className?: string;
13
+ carouselClassName?: string;
14
+ slideClassName?: string;
15
+ contentClassName?: string;
16
+ mediaClassName?: string;
17
+ arrowClassName?: string;
18
+ equalizeOnMobile?: boolean;
19
+ stretchMediaOnMobile?: boolean;
20
+ }
21
+ /**
22
+ * Feature Showcase component with carousel navigation
23
+ *
24
+ * Displays feature content with media in a carousel format. Each slide shows
25
+ * content (text, headings) alongside media (images, videos). Features mobile
26
+ * height equalization for consistent slide heights and customizable styling.
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * <FeatureShowcase
31
+ * items={[
32
+ * {
33
+ * content: <div><h3>Feature 1</h3><p>Description</p></div>,
34
+ * mediaComponent: <img src="/feature1.jpg" alt="Feature 1" />
35
+ * },
36
+ * {
37
+ * content: <div><h3>Feature 2</h3><p>Description</p></div>,
38
+ * mediaComponent: <img src="/feature2.jpg" alt="Feature 2" />
39
+ * }
40
+ * ]}
41
+ * />
42
+ * ```
43
+ */
44
+ declare function FeatureShowcase({ items, children, className, carouselClassName, slideClassName, contentClassName, mediaClassName, arrowClassName, equalizeOnMobile, stretchMediaOnMobile, }: FeatureShowcaseProps): react_jsx_runtime.JSX.Element;
45
+
46
+ export { FeatureShowcase };
@@ -0,0 +1,46 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ export { FeatureShowcaseItem, FeatureShowcaseProps } from './types.js';
4
+
5
+ interface FeatureShowcaseItem {
6
+ content: ReactNode;
7
+ mediaComponent: ReactNode;
8
+ }
9
+ interface FeatureShowcaseProps {
10
+ items: FeatureShowcaseItem[];
11
+ children?: ReactNode;
12
+ className?: string;
13
+ carouselClassName?: string;
14
+ slideClassName?: string;
15
+ contentClassName?: string;
16
+ mediaClassName?: string;
17
+ arrowClassName?: string;
18
+ equalizeOnMobile?: boolean;
19
+ stretchMediaOnMobile?: boolean;
20
+ }
21
+ /**
22
+ * Feature Showcase component with carousel navigation
23
+ *
24
+ * Displays feature content with media in a carousel format. Each slide shows
25
+ * content (text, headings) alongside media (images, videos). Features mobile
26
+ * height equalization for consistent slide heights and customizable styling.
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * <FeatureShowcase
31
+ * items={[
32
+ * {
33
+ * content: <div><h3>Feature 1</h3><p>Description</p></div>,
34
+ * mediaComponent: <img src="/feature1.jpg" alt="Feature 1" />
35
+ * },
36
+ * {
37
+ * content: <div><h3>Feature 2</h3><p>Description</p></div>,
38
+ * mediaComponent: <img src="/feature2.jpg" alt="Feature 2" />
39
+ * }
40
+ * ]}
41
+ * />
42
+ * ```
43
+ */
44
+ declare function FeatureShowcase({ items, children, className, carouselClassName, slideClassName, contentClassName, mediaClassName, arrowClassName, equalizeOnMobile, stretchMediaOnMobile, }: FeatureShowcaseProps): react_jsx_runtime.JSX.Element;
45
+
46
+ export { FeatureShowcase };