@nikala-ui/core 0.9.11 → 0.9.12

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.
@@ -2,6 +2,8 @@ import { splitProps, type Component, type JSX, type ValidComponent, Show } from
2
2
  import * as DialogPrimitive from "@kobalte/core/dialog";
3
3
  import type { PolymorphicProps } from "@kobalte/core/polymorphic";
4
4
  import { cva, type VariantProps } from "class-variance-authority";
5
+ import { X } from "lucide-solid";
6
+ import { ScrollArea } from "./scroll-area";
5
7
  import { cn } from "@/lib/cn";
6
8
 
7
9
  // Global CSS Keyframe Animations specifically designed for Kobalte animationend DOM events
@@ -13,7 +15,7 @@ const sheetStyles = `
13
15
  @keyframes sheet-slide-in-top { from { transform: translateY(-100%); } to { transform: translateY(0); } }
14
16
  @keyframes sheet-slide-out-top { from { transform: translateY(0); } to { transform: translateY(-100%); } }
15
17
  @keyframes sheet-slide-in-bottom { from { transform: translateY(100%); } to { transform: translateY(0); } }
16
- @keyframes sheet-slide-out-bottom { from { transform: translateY(0); } to { transform: translateY(100%); } }
18
+ @keyframes sheet-slide-out-bottom { from { transform: translateY(0); } to { transform: translateY(-100%); } }
17
19
  @keyframes sheet-fade-in { from { opacity: 0; } to { opacity: 1; } }
18
20
  @keyframes sheet-fade-out { from { opacity: 1; } to { opacity: 0; } }
19
21
  `;
@@ -26,10 +28,12 @@ export const sheetVariants = cva(
26
28
  {
27
29
  variants: {
28
30
  side: {
29
- left: "fixed top-0 bottom-0 left-0 w-3/4 border-r border-border sm:max-w-sm data-[expanded]:animate-[sheet-slide-in-left_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-left_300ms_ease-in-out]",
30
- right: "fixed top-0 bottom-0 right-0 w-3/4 border-l border-border sm:max-w-sm data-[expanded]:animate-[sheet-slide-in-right_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-right_300ms_ease-in-out]",
31
- top: "fixed top-0 left-0 right-0 border-b border-border data-[expanded]:animate-[sheet-slide-in-top_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-top_300ms_ease-in-out]",
32
- bottom: "fixed bottom-0 left-0 right-0 border-t border-border data-[expanded]:animate-[sheet-slide-in-bottom_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-bottom_300ms_ease-in-out]",
31
+ top: "inset-x-0 top-0 border-b data-[expanded]:animate-[sheet-slide-in-top_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-top_300ms_ease-in-out]",
32
+ bottom:
33
+ "inset-x-0 bottom-0 border-t data-[expanded]:animate-[sheet-slide-in-bottom_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-bottom_300ms_ease-in-out]",
34
+ left: "inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm data-[expanded]:animate-[sheet-slide-in-left_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-left_300ms_ease-in-out]",
35
+ right:
36
+ "inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm data-[expanded]:animate-[sheet-slide-in-right_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-right_300ms_ease-in-out]",
33
37
  },
34
38
  },
35
39
  defaultVariants: {
@@ -38,23 +42,20 @@ export const sheetVariants = cva(
38
42
  }
39
43
  );
40
44
 
41
- export type SheetRootProps = DialogPrimitive.DialogRootProps;
42
-
43
- export const Sheet: Component<SheetRootProps> = (props) => {
44
- return <DialogPrimitive.Root {...props} />;
45
- };
46
-
45
+ export const Sheet = DialogPrimitive.Root;
47
46
  export const SheetTrigger = DialogPrimitive.Trigger;
48
47
  export const SheetClose = DialogPrimitive.CloseButton;
48
+ export const SheetPortal = DialogPrimitive.Portal;
49
49
 
50
- export interface SheetOverlayProps<T extends ValidComponent = "div"> {
51
- /** Whether to apply background blur effect or keep transparent (default: true) */
52
- blur?: boolean;
53
- class?: string;
54
- }
50
+ export type SheetOverlayProps<T extends ValidComponent = "div"> =
51
+ DialogPrimitive.DialogOverlayProps<T> & {
52
+ /** Whether to apply backdrop blur (default: true) */
53
+ blur?: boolean;
54
+ class?: string;
55
+ };
55
56
 
56
57
  /**
57
- * Backdrop overlay wrapper with fade-in and fade-out animations.
58
+ * Fullscreen dark backdrop with fade keyframe animation.
58
59
  */
59
60
  export const SheetOverlay = <T extends ValidComponent = "div">(
60
61
  props: PolymorphicProps<T, SheetOverlayProps<T>>
@@ -64,8 +65,8 @@ export const SheetOverlay = <T extends ValidComponent = "div">(
64
65
  return (
65
66
  <DialogPrimitive.Overlay
66
67
  class={cn(
67
- "fixed inset-0 z-50 data-[expanded]:animate-[sheet-fade-in_300ms_ease-in-out] data-[closed]:animate-[sheet-fade-out_300ms_ease-in-out]",
68
- local.blur !== false ? "bg-black/80 backdrop-blur-sm" : "bg-transparent",
68
+ "fixed inset-0 z-50 transition-all duration-200 data-[expanded]:animate-[sheet-fade-in_300ms_ease-in-out] data-[closed]:animate-[sheet-fade-out_300ms_ease-in-out]",
69
+ local.blur !== false ? "bg-black/80 backdrop-blur-sm" : "bg-black/80",
69
70
  local.class
70
71
  )}
71
72
  {...(rest as any)}
@@ -75,32 +76,28 @@ export const SheetOverlay = <T extends ValidComponent = "div">(
75
76
 
76
77
  export type SheetContentProps<T extends ValidComponent = "div"> =
77
78
  DialogPrimitive.DialogContentProps<T> &
78
- VariantProps<typeof sheetVariants> & {
79
- /** Direction from which the sheet slides out: top, bottom, left, right */
80
- side?: "top" | "bottom" | "left" | "right";
81
- /** Whether to display the top-right close (X) button (default: true) */
82
- showCloseButton?: boolean;
83
- /** Whether clicking outside closes the sheet (default: true) */
84
- closeOnOutsideClick?: boolean;
85
- /** Whether to apply background backdrop blur (default: true) */
86
- blur?: boolean;
87
- class?: string;
88
- children?: JSX.Element;
89
- };
79
+ VariantProps<typeof sheetVariants> & {
80
+ side?: "top" | "bottom" | "left" | "right";
81
+ showCloseButton?: boolean;
82
+ closeOnOutsideClick?: boolean;
83
+ blur?: boolean;
84
+ class?: string;
85
+ children?: JSX.Element;
86
+ };
90
87
 
91
88
  /**
92
- * Main sheet container with smooth CSS keyframe slide animations.
89
+ * Slide-out panel container with ScrollArea and animation support.
93
90
  */
94
91
  export const SheetContent = <T extends ValidComponent = "div">(
95
92
  props: PolymorphicProps<T, SheetContentProps<T>>
96
93
  ) => {
97
94
  const [local, rest] = splitProps(props as SheetContentProps, [
95
+ "class",
96
+ "children",
98
97
  "side",
99
98
  "showCloseButton",
100
99
  "closeOnOutsideClick",
101
100
  "blur",
102
- "class",
103
- "children",
104
101
  "onPointerDownOutside",
105
102
  "onInteractOutside",
106
103
  ]);
@@ -126,26 +123,28 @@ export const SheetContent = <T extends ValidComponent = "div">(
126
123
  };
127
124
 
128
125
  return (
129
- <DialogPrimitive.Portal>
126
+ <SheetPortal>
130
127
  <style>{sheetStyles}</style>
131
128
  <SheetOverlay blur={local.blur} />
132
129
  <DialogPrimitive.Content
133
130
  onPointerDownOutside={handlePointerDownOutside}
134
131
  onInteractOutside={handleInteractOutside}
135
- class={cn(sheetVariants({ side: side() }), local.class)}
132
+ class={cn(sheetVariants({ side: side() }), "p-0", local.class)}
136
133
  {...(rest as any)}
137
134
  >
138
- {local.children}
135
+ <ScrollArea class="h-full w-full">
136
+ <div class="p-6 space-y-4">
137
+ {local.children}
138
+ </div>
139
+ </ScrollArea>
139
140
  <Show when={local.showCloseButton !== false}>
140
- <DialogPrimitive.CloseButton class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none cursor-pointer">
141
- <svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
142
- <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
143
- </svg>
141
+ <DialogPrimitive.CloseButton class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none cursor-pointer z-50">
142
+ <X class="h-4 w-4" />
144
143
  <span class="sr-only">Close</span>
145
144
  </DialogPrimitive.CloseButton>
146
145
  </Show>
147
146
  </DialogPrimitive.Content>
148
- </DialogPrimitive.Portal>
147
+ </SheetPortal>
149
148
  );
150
149
  };
151
150
 
@@ -173,44 +172,44 @@ export const SheetFooter: Component<SheetFooterProps> = (props) => {
173
172
 
174
173
  return (
175
174
  <div
176
- class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", local.class)}
175
+ class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 pt-4", local.class)}
177
176
  {...rest}
178
177
  />
179
178
  );
180
179
  };
181
180
 
182
- export type SheetTitleProps<T extends ValidComponent = "h2"> =
183
- DialogPrimitive.DialogTitleProps<T> & {
184
- class?: string;
185
- };
181
+ export interface SheetTitleProps {
182
+ class?: string;
183
+ children?: JSX.Element;
184
+ }
186
185
 
187
- export const SheetTitle = <T extends ValidComponent = "h2">(
188
- props: PolymorphicProps<T, SheetTitleProps<T>>
189
- ) => {
190
- const [local, rest] = splitProps(props as SheetTitleProps, ["class"]);
186
+ export const SheetTitle: Component<SheetTitleProps> = (props) => {
187
+ const [local, rest] = splitProps(props, ["class", "children"]);
191
188
 
192
189
  return (
193
190
  <DialogPrimitive.Title
194
191
  class={cn("text-lg font-semibold text-foreground", local.class)}
195
- {...(rest as any)}
196
- />
192
+ {...rest}
193
+ >
194
+ {local.children}
195
+ </DialogPrimitive.Title>
197
196
  );
198
197
  };
199
198
 
200
- export type SheetDescriptionProps<T extends ValidComponent = "p"> =
201
- DialogPrimitive.DialogDescriptionProps<T> & {
202
- class?: string;
203
- };
199
+ export interface SheetDescriptionProps {
200
+ class?: string;
201
+ children?: JSX.Element;
202
+ }
204
203
 
205
- export const SheetDescription = <T extends ValidComponent = "p">(
206
- props: PolymorphicProps<T, SheetDescriptionProps<T>>
207
- ) => {
208
- const [local, rest] = splitProps(props as SheetDescriptionProps, ["class"]);
204
+ export const SheetDescription: Component<SheetDescriptionProps> = (props) => {
205
+ const [local, rest] = splitProps(props, ["class", "children"]);
209
206
 
210
207
  return (
211
208
  <DialogPrimitive.Description
212
209
  class={cn("text-sm text-muted-foreground", local.class)}
213
- {...(rest as any)}
214
- />
210
+ {...rest}
211
+ >
212
+ {local.children}
213
+ </DialogPrimitive.Description>
215
214
  );
216
215
  };
@@ -121,10 +121,11 @@ export const ThemeToggle: Component<ThemeToggleProps> = (props) => {
121
121
  }
122
122
  >
123
123
  {/* Max Mode: Full Theme Customizer Panel */}
124
- <DropdownMenuContent class="w-64 p-3">
125
- <DropdownMenuLabel class="px-0 pt-0 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
126
- Theme Mode
127
- </DropdownMenuLabel>
124
+ <DropdownMenuContent class="w-64">
125
+ <div class="p-2 space-y-2">
126
+ <DropdownMenuLabel class="px-0 pt-0 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
127
+ Theme Mode
128
+ </DropdownMenuLabel>
128
129
  <div class="grid grid-cols-3 gap-1 my-1.5">
129
130
  <Button
130
131
  variant={theme() === "light" ? "default" : "outline"}
@@ -193,6 +194,7 @@ export const ThemeToggle: Component<ThemeToggleProps> = (props) => {
193
194
  )}
194
195
  </For>
195
196
  </div>
197
+ </div>
196
198
  </DropdownMenuContent>
197
199
  </Show>
198
200
  </DropdownMenu>
@@ -0,0 +1,101 @@
1
+ import { splitProps, type Component, type JSX } from "solid-js";
2
+ import { ToggleButton as KobalteToggle } from "@kobalte/core/toggle-button";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+ import { cn } from "@/lib/cn";
5
+
6
+ export const toggleVariants = cva(
7
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-accent data-[pressed]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-transparent",
12
+ outline:
13
+ "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground data-[pressed]:bg-accent data-[pressed]:text-accent-foreground",
14
+ },
15
+ size: {
16
+ default: "h-9 px-3 min-w-9",
17
+ sm: "h-8 px-2 text-xs min-w-8",
18
+ lg: "h-10 px-3 min-w-10",
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ variant: "default",
23
+ size: "default",
24
+ },
25
+ }
26
+ );
27
+
28
+ export interface ToggleProps
29
+ extends JSX.ButtonHTMLAttributes<HTMLButtonElement>,
30
+ VariantProps<typeof toggleVariants> {
31
+ pressed?: boolean;
32
+ defaultPressed?: boolean;
33
+ onPressedChange?: (pressed: boolean) => void;
34
+ disabled?: boolean;
35
+ class?: string;
36
+ children?: JSX.Element;
37
+ }
38
+
39
+ export const Toggle: Component<ToggleProps> = (props) => {
40
+ const [local, rest] = splitProps(props, [
41
+ "variant",
42
+ "size",
43
+ "class",
44
+ "children",
45
+ "pressed",
46
+ "defaultPressed",
47
+ "onPressedChange",
48
+ "disabled",
49
+ "onChange",
50
+ ]);
51
+
52
+ return (
53
+ <KobalteToggle
54
+ isPressed={local.pressed}
55
+ defaultIsPressed={local.defaultPressed}
56
+ onChange={local.onPressedChange}
57
+ disabled={local.disabled}
58
+ class={cn(
59
+ toggleVariants({ variant: local.variant, size: local.size }),
60
+ local.class
61
+ )}
62
+ {...rest}
63
+ >
64
+ {local.children}
65
+ </KobalteToggle>
66
+ );
67
+ };
68
+
69
+ export interface ToggleGroupProps extends JSX.HTMLAttributes<HTMLDivElement> {
70
+ type?: "single" | "multiple";
71
+ value?: string | string[];
72
+ defaultValue?: string | string[];
73
+ onChange?: (value: any) => void;
74
+ disabled?: boolean;
75
+ class?: string;
76
+ children?: JSX.Element;
77
+ }
78
+
79
+ export const ToggleGroup: Component<ToggleGroupProps> = (props) => {
80
+ const [local, rest] = splitProps(props, [
81
+ "type",
82
+ "value",
83
+ "defaultValue",
84
+ "onChange",
85
+ "disabled",
86
+ "class",
87
+ "children",
88
+ ]);
89
+
90
+ return (
91
+ <div
92
+ class={cn(
93
+ "flex items-center justify-center gap-1 rounded-md border border-border/40 p-1 bg-background",
94
+ local.class
95
+ )}
96
+ {...rest}
97
+ >
98
+ {local.children}
99
+ </div>
100
+ );
101
+ };
@@ -74,11 +74,13 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
74
74
  title: "Select",
75
75
  description: "Displays a list of options for the user to pick from, built on Kobalte primitives.",
76
76
  dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
77
+ registryDependencies: ["scroll-area"],
77
78
  },
78
79
  combobox: {
79
80
  title: "Combobox",
80
81
  description: "Searchable autocomplete dropdown with single/multi-selection tags, avatars, group headers, and customizable clear controls.",
81
82
  dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
83
+ registryDependencies: ["scroll-area"],
82
84
  },
83
85
  tabs: {
84
86
  title: "Tabs",
@@ -104,16 +106,19 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
104
106
  title: "Dialog",
105
107
  description: "A modal window overlaying the main content, built on Kobalte primitives with blur and outside-click options.",
106
108
  dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
109
+ registryDependencies: ["scroll-area"],
107
110
  },
108
111
  sheet: {
109
112
  title: "Sheet / Drawer",
110
113
  description: "Extends the dialog component to display content that slides in from screen edges.",
111
114
  dependencies: ["clsx", "tailwind-merge", "class-variance-authority", "@kobalte/core"],
115
+ registryDependencies: ["scroll-area"],
112
116
  },
113
117
  "dropdown-menu": {
114
118
  title: "Dropdown Menu",
115
119
  description: "Displays a menu to the user—such as a set of actions or functions—triggered by a button or avatar.",
116
120
  dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
121
+ registryDependencies: ["scroll-area"],
117
122
  },
118
123
  "theme-manager": {
119
124
  title: "Theme Manager",
@@ -152,7 +157,7 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
152
157
  "lucide-solid",
153
158
  "@kobalte/core",
154
159
  ],
155
- registryDependencies: ["kbd", "input-group", "list"],
160
+ registryDependencies: ["kbd", "input-group", "list", "scroll-area"],
156
161
  },
157
162
  toast: {
158
163
  title: "Toast / Sonner",
@@ -179,6 +184,45 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
179
184
  description: "Numeric range selection slider supporting single/dual thumbs, custom steps, vertical orientation, and formatted value labels, built on Kobalte primitives.",
180
185
  dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
181
186
  },
187
+ collapsible: {
188
+ title: "Collapsible",
189
+ description: "An interactive component that expands and collapses content panels with smooth height animations, built on Kobalte primitives.",
190
+ dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
191
+ },
192
+ "aspect-ratio": {
193
+ title: "Aspect Ratio",
194
+ description: "Displays content within a specific aspect ratio using CSS aspect-ratio while preventing layout shifts.",
195
+ dependencies: ["clsx", "tailwind-merge"],
196
+ },
197
+ toggle: {
198
+ title: "Toggle",
199
+ description: "A two-state interactive button component built on Kobalte primitives.",
200
+ dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
201
+ },
202
+ "number-input": {
203
+ title: "Number Input",
204
+ description: "A numeric stepper input component supporting min, max, step, negative values, and long-press auto-repeat, built on Kobalte primitives.",
205
+ dependencies: ["clsx", "tailwind-merge", "@kobalte/core", "lucide-solid"],
206
+ registryDependencies: ["input", "button", "create-long-press"],
207
+ },
208
+ "context-menu": {
209
+ title: "Context Menu",
210
+ description: "Displays a contextual popup menu triggered by right-clicking target areas, built on Kobalte primitives.",
211
+ dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
212
+ registryDependencies: ["separator", "kbd", "create-click-outside", "scroll-area"],
213
+ },
214
+ resizable: {
215
+ title: "Resizable",
216
+ description: "Accessible resizable panel layout component supporting drag-to-resize handles.",
217
+ dependencies: ["clsx", "tailwind-merge", "lucide-solid"],
218
+ registryDependencies: ["create-resize-observer"],
219
+ },
220
+ "scroll-area": {
221
+ title: "Scroll Area",
222
+ description: "Augments native scroll functionality with custom styled scrollbars and reactive scroll tracking.",
223
+ dependencies: ["clsx", "tailwind-merge"],
224
+ registryDependencies: ["create-scroll-position", "create-resize-observer"],
225
+ },
182
226
  "pin-input": {
183
227
  title: "Pin Input",
184
228
  description: "Interactive multi-slot PIN/OTP input component for SMS and 2FA authentication verification codes.",