@zvk/ui 0.1.3 → 0.1.5

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 (42) hide show
  1. package/dist/components/alert-dialog/alert-dialog.d.ts +8 -5
  2. package/dist/components/alert-dialog/alert-dialog.js +21 -8
  3. package/dist/components/button/button.d.ts +3 -2
  4. package/dist/components/button/button.js +5 -1
  5. package/dist/components/calendar/calendar.d.ts +40 -5
  6. package/dist/components/calendar/calendar.js +17 -5
  7. package/dist/components/calendar/index.d.ts +1 -1
  8. package/dist/components/collapsible/collapsible.d.ts +3 -2
  9. package/dist/components/collapsible/collapsible.js +5 -1
  10. package/dist/components/command/command.d.ts +11 -4
  11. package/dist/components/command/command.js +27 -16
  12. package/dist/components/command/index.d.ts +1 -1
  13. package/dist/components/context-menu/context-menu.d.ts +17 -6
  14. package/dist/components/context-menu/context-menu.js +139 -36
  15. package/dist/components/dialog/dialog.d.ts +6 -4
  16. package/dist/components/dialog/dialog.js +14 -4
  17. package/dist/components/dropdown-menu/dropdown-menu.d.ts +13 -7
  18. package/dist/components/dropdown-menu/dropdown-menu.js +127 -72
  19. package/dist/components/hover-card/hover-card.d.ts +8 -2
  20. package/dist/components/hover-card/hover-card.js +8 -5
  21. package/dist/components/index.d.ts +7 -7
  22. package/dist/components/index.js +1 -1
  23. package/dist/components/menubar/menubar.d.ts +24 -5
  24. package/dist/components/menubar/menubar.js +182 -33
  25. package/dist/components/popover/popover.d.ts +8 -3
  26. package/dist/components/popover/popover.js +14 -5
  27. package/dist/components/sheet/sheet.d.ts +6 -4
  28. package/dist/components/sheet/sheet.js +21 -8
  29. package/dist/components/toast/index.d.ts +2 -2
  30. package/dist/components/toast/index.js +1 -1
  31. package/dist/components/toast/toast.d.ts +16 -2
  32. package/dist/components/toast/toast.js +44 -2
  33. package/dist/components/tooltip/tooltip.d.ts +8 -2
  34. package/dist/components/tooltip/tooltip.js +8 -5
  35. package/dist/internal/floating/placement-aliases.d.ts +7 -0
  36. package/dist/internal/floating/placement-aliases.js +13 -0
  37. package/dist/internal/slot/index.d.ts +2 -0
  38. package/dist/internal/slot/index.js +1 -0
  39. package/dist/internal/slot/slot.d.ts +6 -0
  40. package/dist/internal/slot/slot.js +53 -0
  41. package/dist/styles.css +21 -1
  42. package/package.json +2 -2
@@ -1,12 +1,14 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { composeEventHandlers } from "../../utils/compose-event-handlers.js";
5
5
  import { cn } from "../../utils/cn.js";
6
6
  import { useControllableState } from "../../hooks/use-controllable-state.js";
7
7
  import { createCollection } from "../../internal/collection/index.js";
8
8
  import { DismissableLayer } from "../../internal/dismissable-layer/index.js";
9
+ import { placementFromSideAlign, placementParts } from "../../internal/floating/placement-aliases.js";
9
10
  import { Portal } from "../../internal/portal/index.js";
11
+ import { Slot } from "../../internal/slot/index.js";
10
12
  const MenubarContext = React.createContext(null);
11
13
  const MenuContext = React.createContext(null);
12
14
  function useMenubarContext(calledBy) {
@@ -44,6 +46,18 @@ function activeIndex(records) {
44
46
  const enabled = records.filter((record) => record.data.disabled !== true && record.data.ref !== null);
45
47
  return enabled.findIndex((record) => record.data.ref === document.activeElement);
46
48
  }
49
+ function setComposedRef(internalRef, externalRef, node) {
50
+ internalRef.current = node;
51
+ if (typeof externalRef === "function") {
52
+ externalRef(node);
53
+ }
54
+ else if (externalRef !== undefined && externalRef !== null) {
55
+ externalRef.current = node;
56
+ }
57
+ }
58
+ function isActivationKey(key) {
59
+ return key === "Enter" || key === " " || key === "Space" || key === "Spacebar";
60
+ }
47
61
  function MenubarRoot({ children, className, defaultValue, onKeyDown, onValueChange, ref, value, ...props }) {
48
62
  const [openValue, setOpenValue] = useControllableState({
49
63
  ...(value !== undefined ? { value } : {}),
@@ -112,7 +126,7 @@ function MenubarMenu({ children, value }) {
112
126
  }, [getItems, open]);
113
127
  return _jsx(MenuContext.Provider, { value: contextValue, children: children });
114
128
  }
115
- function MenubarTrigger({ children, className, disabled, onClick, onKeyDown, ref, type = "button", ...props }) {
129
+ function MenubarTrigger({ asChild = false, children, className, disabled, onClick, onKeyDown, ref, type = "button", ...props }) {
116
130
  const menubar = useMenubarContext("Menubar.Trigger");
117
131
  const menu = useMenuContext("Menubar.Trigger");
118
132
  const triggerRef = React.useRef(null);
@@ -123,32 +137,50 @@ function MenubarTrigger({ children, className, disabled, onClick, onKeyDown, ref
123
137
  menubar.registerTrigger(itemId, { disabled, ref: triggerRef.current, value: menu.value });
124
138
  return () => menubar.unregisterTrigger(itemId);
125
139
  }, [disabled, itemId, label, menu, menubar]);
140
+ const handleClick = () => {
141
+ if (!disabled) {
142
+ menubar.setOpenValue(menu.open ? undefined : menu.value);
143
+ }
144
+ };
145
+ const handleKeyDown = (event) => {
146
+ if (event.key === "ArrowDown" || isActivationKey(event.key)) {
147
+ event.preventDefault();
148
+ menubar.setOpenValue(menu.value);
149
+ }
150
+ };
151
+ const triggerProps = {
152
+ ...props,
153
+ ref: (node) => {
154
+ setComposedRef(triggerRef, ref, node);
155
+ },
156
+ id: menu.triggerId,
157
+ role: "menuitem",
158
+ "aria-controls": menu.contentId,
159
+ "aria-disabled": disabled ? true : undefined,
160
+ "aria-expanded": menu.open,
161
+ "aria-haspopup": "menu",
162
+ className: cn("liano-menubar__trigger", className),
163
+ "data-disabled": disabled ? "true" : undefined,
164
+ "data-state": menu.open ? "open" : "closed",
165
+ onClick: composeEventHandlers(onClick, handleClick),
166
+ onKeyDown: composeEventHandlers(onKeyDown, handleKeyDown)
167
+ };
168
+ if (asChild) {
169
+ return _jsx(Slot, { ...triggerProps, children: children });
170
+ }
126
171
  return (_jsx("button", { ...props, ref: (node) => {
127
- triggerRef.current = node;
128
- if (typeof ref === "function") {
129
- ref(node);
130
- }
131
- else if (ref) {
132
- ref.current = node;
133
- }
134
- }, id: menu.triggerId, type: type, role: "menuitem", disabled: disabled, "aria-controls": menu.contentId, "aria-expanded": menu.open ? "true" : "false", "aria-haspopup": "menu", className: cn("liano-menubar__trigger", className), "data-state": menu.open ? "open" : "closed", onClick: composeEventHandlers(onClick, () => {
135
- if (!disabled) {
136
- menubar.setOpenValue(menu.open ? undefined : menu.value);
137
- }
138
- }), onKeyDown: composeEventHandlers(onKeyDown, (event) => {
139
- if (event.key === "ArrowDown" || event.key === "Enter" || event.key === " ") {
140
- event.preventDefault();
141
- menubar.setOpenValue(menu.value);
142
- }
143
- }), children: children }));
172
+ setComposedRef(triggerRef, ref, node);
173
+ }, id: menu.triggerId, type: type, role: "menuitem", disabled: disabled, "aria-controls": menu.contentId, "aria-expanded": menu.open ? "true" : "false", "aria-haspopup": "menu", className: cn("liano-menubar__trigger", className), "data-disabled": disabled ? "true" : undefined, "data-state": menu.open ? "open" : "closed", onClick: triggerProps.onClick, onKeyDown: triggerProps.onKeyDown, children: children }));
144
174
  }
145
- function MenubarContent({ children, className, onKeyDown, ref, ...props }) {
175
+ function MenubarContent({ align, alignOffset: _alignOffset, children, className, onKeyDown, ref, side, sideOffset: _sideOffset, ...props }) {
146
176
  const menubar = useMenubarContext("Menubar.Content");
147
177
  const menu = useMenuContext("Menubar.Content");
178
+ const contentPlacement = placementFromSideAlign(side, align, "bottom-start");
179
+ const contentPlacementParts = placementParts(contentPlacement);
148
180
  if (!menu.open) {
149
181
  return null;
150
182
  }
151
- return (_jsx(Portal, { children: _jsx(DismissableLayer, { open: menu.open, onDismiss: () => menubar.setOpenValue(undefined), children: _jsx("div", { ...props, ref: ref, id: menu.contentId, role: "menu", "aria-label": menu.label, "aria-labelledby": menu.triggerId, className: cn("liano-menubar__content", className), onKeyDown: composeEventHandlers(onKeyDown, (event) => {
183
+ return (_jsx(Portal, { children: _jsx(DismissableLayer, { open: menu.open, onDismiss: () => menubar.setOpenValue(undefined), children: _jsx("div", { ...props, ref: ref, id: menu.contentId, role: "menu", "aria-label": menu.label, "aria-labelledby": menu.triggerId, className: cn("liano-menubar__content", className), "data-align": contentPlacementParts.align, "data-side": contentPlacementParts.side, onKeyDown: composeEventHandlers(onKeyDown, (event) => {
152
184
  const items = menu.getItems();
153
185
  const index = activeIndex(items);
154
186
  if (event.key === "ArrowDown") {
@@ -166,7 +198,7 @@ function MenubarContent({ children, className, onKeyDown, ref, ...props }) {
166
198
  }
167
199
  }), children: children }) }) }));
168
200
  }
169
- function MenubarItem({ children, className, disabled, onClick, onKeyDown, onSelect, ref, type = "button", ...props }) {
201
+ function MenubarItem({ asChild = false, children, className, disabled, onClick, onKeyDown, onSelect, ref, type = "button", ...props }) {
170
202
  const menubar = useMenubarContext("Menubar.Item");
171
203
  const menu = useMenuContext("Menubar.Item");
172
204
  const { getItems, open, registerItem, unregisterItem } = menu;
@@ -185,22 +217,137 @@ function MenubarItem({ children, className, disabled, onClick, onKeyDown, onSele
185
217
  return;
186
218
  }
187
219
  onSelect?.(event);
188
- menubar.setOpenValue(undefined);
220
+ if (!event.defaultPrevented) {
221
+ menubar.setOpenValue(undefined);
222
+ }
189
223
  };
190
- return (_jsx("button", { ...props, ref: (node) => {
191
- itemRef.current = node;
192
- if (typeof ref === "function") {
193
- ref(node);
194
- }
195
- else if (ref) {
196
- ref.current = node;
224
+ const itemProps = {
225
+ ...props,
226
+ ref: (node) => {
227
+ setComposedRef(itemRef, ref, node);
228
+ },
229
+ role: "menuitem",
230
+ "aria-disabled": disabled ? true : undefined,
231
+ className: cn("liano-menubar__item", className),
232
+ "data-disabled": disabled ? "true" : undefined,
233
+ onClick: composeEventHandlers(onClick, select),
234
+ onKeyDown: composeEventHandlers(onKeyDown, (event) => {
235
+ if (isActivationKey(event.key)) {
236
+ select(event);
237
+ event.preventDefault();
197
238
  }
198
- }, type: type, role: "menuitem", disabled: disabled, "aria-disabled": disabled ? "true" : undefined, className: cn("liano-menubar__item", className), "data-disabled": disabled ? "true" : undefined, onClick: composeEventHandlers(onClick, select), onKeyDown: composeEventHandlers(onKeyDown, (event) => {
199
- if (event.key === "Enter" || event.key === " ") {
239
+ })
240
+ };
241
+ if (asChild) {
242
+ return _jsx(Slot, { ...itemProps, children: children });
243
+ }
244
+ return (_jsx("button", { ...props, ref: (node) => {
245
+ setComposedRef(itemRef, ref, node);
246
+ }, type: type, role: "menuitem", disabled: disabled, "aria-disabled": itemProps["aria-disabled"], className: itemProps.className, "data-disabled": itemProps["data-disabled"], onClick: itemProps.onClick, onKeyDown: itemProps.onKeyDown, children: children }));
247
+ }
248
+ function MenubarCheckboxItem({ asChild = false, checked, children, className, defaultChecked = false, disabled, onCheckedChange, onClick, onKeyDown, onSelect, ref, type = "button", ...props }) {
249
+ const menubar = useMenubarContext("Menubar.CheckboxItem");
250
+ const menu = useMenuContext("Menubar.CheckboxItem");
251
+ const { getItems, open, registerItem, unregisterItem } = menu;
252
+ const itemId = React.useId();
253
+ const itemRef = React.useRef(null);
254
+ const [currentChecked, setCurrentChecked] = useControllableState({
255
+ ...(checked !== undefined ? { value: checked } : {}),
256
+ defaultValue: defaultChecked,
257
+ ...(onCheckedChange ? { onChange: onCheckedChange } : {})
258
+ });
259
+ React.useLayoutEffect(() => {
260
+ registerItem(itemId, { disabled, ref: itemRef.current });
261
+ const firstEnabled = getItems().find((item) => item.data.disabled !== true && item.data.ref !== null);
262
+ if (open && firstEnabled?.id === itemId) {
263
+ itemRef.current?.focus();
264
+ }
265
+ return () => unregisterItem(itemId);
266
+ }, [disabled, getItems, itemId, open, registerItem, unregisterItem]);
267
+ const select = (event) => {
268
+ if (disabled) {
269
+ return;
270
+ }
271
+ onSelect?.(event);
272
+ if (!event.defaultPrevented) {
273
+ setCurrentChecked((value) => !value);
274
+ menubar.setOpenValue(undefined);
275
+ }
276
+ };
277
+ const itemProps = {
278
+ ...props,
279
+ ref: (node) => {
280
+ setComposedRef(itemRef, ref, node);
281
+ },
282
+ role: "menuitemcheckbox",
283
+ "aria-checked": currentChecked,
284
+ "aria-disabled": disabled ? true : undefined,
285
+ className: cn("liano-menubar__item", "liano-menubar__checkbox-item", className),
286
+ "data-checked": currentChecked ? "true" : undefined,
287
+ "data-disabled": disabled ? "true" : undefined,
288
+ onClick: composeEventHandlers(onClick, select),
289
+ onKeyDown: composeEventHandlers(onKeyDown, (event) => {
290
+ if (isActivationKey(event.key)) {
291
+ select(event);
200
292
  event.preventDefault();
293
+ }
294
+ })
295
+ };
296
+ if (asChild) {
297
+ return _jsx(Slot, { ...itemProps, children: children });
298
+ }
299
+ return (_jsxs("button", { ...props, ref: (node) => {
300
+ setComposedRef(itemRef, ref, node);
301
+ }, type: type, role: "menuitemcheckbox", disabled: disabled, "aria-checked": itemProps["aria-checked"], "aria-disabled": itemProps["aria-disabled"], className: itemProps.className, "data-checked": itemProps["data-checked"], "data-disabled": itemProps["data-disabled"], onClick: itemProps.onClick, onKeyDown: itemProps.onKeyDown, children: [_jsx("span", { className: "liano-menubar__item-indicator", "aria-hidden": "true", children: currentChecked ? "✓" : "" }), _jsx("span", { className: "liano-menubar__item-label", children: children })] }));
302
+ }
303
+ function MenubarRadioItem({ asChild = false, checked = false, children, className, disabled, onClick, onKeyDown, onSelect, ref, type = "button", ...props }) {
304
+ const menubar = useMenubarContext("Menubar.RadioItem");
305
+ const menu = useMenuContext("Menubar.RadioItem");
306
+ const { getItems, open, registerItem, unregisterItem } = menu;
307
+ const itemId = React.useId();
308
+ const itemRef = React.useRef(null);
309
+ React.useLayoutEffect(() => {
310
+ registerItem(itemId, { disabled, ref: itemRef.current });
311
+ const firstEnabled = getItems().find((item) => item.data.disabled !== true && item.data.ref !== null);
312
+ if (open && firstEnabled?.id === itemId) {
313
+ itemRef.current?.focus();
314
+ }
315
+ return () => unregisterItem(itemId);
316
+ }, [disabled, getItems, itemId, open, registerItem, unregisterItem]);
317
+ const select = (event) => {
318
+ if (disabled) {
319
+ return;
320
+ }
321
+ onSelect?.(event);
322
+ if (!event.defaultPrevented) {
323
+ menubar.setOpenValue(undefined);
324
+ }
325
+ };
326
+ const itemProps = {
327
+ ...props,
328
+ ref: (node) => {
329
+ setComposedRef(itemRef, ref, node);
330
+ },
331
+ role: "menuitemradio",
332
+ "aria-checked": checked,
333
+ "aria-disabled": disabled ? true : undefined,
334
+ className: cn("liano-menubar__item", "liano-menubar__radio-item", className),
335
+ "data-checked": checked ? "true" : undefined,
336
+ "data-disabled": disabled ? "true" : undefined,
337
+ onClick: composeEventHandlers(onClick, select),
338
+ onKeyDown: composeEventHandlers(onKeyDown, (event) => {
339
+ if (isActivationKey(event.key)) {
201
340
  select(event);
341
+ event.preventDefault();
202
342
  }
203
- }), children: children }));
343
+ })
344
+ };
345
+ if (asChild) {
346
+ return _jsx(Slot, { ...itemProps, children: children });
347
+ }
348
+ return (_jsxs("button", { ...props, ref: (node) => {
349
+ setComposedRef(itemRef, ref, node);
350
+ }, type: type, role: "menuitemradio", disabled: disabled, "aria-checked": itemProps["aria-checked"], "aria-disabled": itemProps["aria-disabled"], className: itemProps.className, "data-checked": itemProps["data-checked"], "data-disabled": itemProps["data-disabled"], onClick: itemProps.onClick, onKeyDown: itemProps.onKeyDown, children: [_jsx("span", { className: "liano-menubar__item-indicator", "aria-hidden": "true", children: checked ? "●" : "" }), _jsx("span", { className: "liano-menubar__item-label", children: children })] }));
204
351
  }
205
352
  function MenubarSeparator({ className, ref, ...props }) {
206
353
  return _jsx("div", { ...props, ref: ref, role: "separator", "aria-hidden": "true", className: cn("liano-menubar__separator", className) });
@@ -212,10 +359,12 @@ function MenubarShortcut({ className, ref, ...props }) {
212
359
  return _jsx("span", { ...props, ref: ref, className: cn("liano-menubar__shortcut", className) });
213
360
  }
214
361
  export const Menubar = Object.assign(MenubarRoot, {
362
+ CheckboxItem: MenubarCheckboxItem,
215
363
  Content: MenubarContent,
216
364
  Item: MenubarItem,
217
365
  Label: MenubarLabel,
218
366
  Menu: MenubarMenu,
367
+ RadioItem: MenubarRadioItem,
219
368
  Separator: MenubarSeparator,
220
369
  Shortcut: MenubarShortcut,
221
370
  Trigger: MenubarTrigger
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import type { PortalProps } from "../../internal/portal/index.js";
3
3
  import type { FloatingPlacement } from "../../internal/floating/floating-types.js";
4
+ import type { FloatingAlign, FloatingSide } from "../../internal/floating/placement-aliases.js";
4
5
  export interface PopoverProps extends React.HTMLAttributes<HTMLDivElement> {
5
6
  open?: boolean;
6
7
  defaultOpen?: boolean;
@@ -10,10 +11,14 @@ export interface PopoverProps extends React.HTMLAttributes<HTMLDivElement> {
10
11
  ref?: React.Ref<HTMLDivElement>;
11
12
  }
12
13
  export interface PopoverTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
13
- ref?: React.Ref<HTMLButtonElement>;
14
+ asChild?: boolean;
15
+ ref?: React.Ref<HTMLButtonElement | HTMLElement>;
14
16
  }
15
17
  export interface PopoverContentProps extends React.HTMLAttributes<HTMLDivElement> {
16
18
  placement?: FloatingPlacement;
19
+ side?: FloatingSide;
20
+ align?: FloatingAlign;
21
+ alignOffset?: number;
17
22
  sideOffset?: number;
18
23
  collisionPadding?: number;
19
24
  matchTriggerWidth?: boolean;
@@ -24,8 +29,8 @@ export interface PopoverContentProps extends React.HTMLAttributes<HTMLDivElement
24
29
  ref?: React.Ref<HTMLDivElement>;
25
30
  }
26
31
  declare function PopoverRoot({ children, className, defaultOpen, modal, onOpenChange, open, placement, ref, ...props }: PopoverProps): React.JSX.Element;
27
- declare function PopoverTrigger({ className, onClick, ref, type, ...props }: PopoverTriggerProps): React.JSX.Element;
28
- declare function PopoverContent({ className, container, forceMount, id, disableEscapeKeyDown, disableOutsidePointerDown, ref, placement, sideOffset, collisionPadding, matchTriggerWidth, style, ...props }: PopoverContentProps): React.JSX.Element | null;
32
+ declare function PopoverTrigger({ asChild, className, disabled, onClick, ref, type, ...props }: PopoverTriggerProps): React.JSX.Element;
33
+ declare function PopoverContent({ align, alignOffset: _alignOffset, className, container, forceMount, id, disableEscapeKeyDown, disableOutsidePointerDown, ref, placement, side, sideOffset, collisionPadding, matchTriggerWidth, style, ...props }: PopoverContentProps): React.JSX.Element | null;
29
34
  export declare const Popover: typeof PopoverRoot & {
30
35
  Trigger: typeof PopoverTrigger;
31
36
  Content: typeof PopoverContent;
@@ -7,6 +7,8 @@ import { cn } from "../../utils/cn.js";
7
7
  import { Portal } from "../../internal/portal/index.js";
8
8
  import { DismissableLayer } from "../../internal/dismissable-layer/index.js";
9
9
  import { useFloatingPosition } from "../../internal/floating/index.js";
10
+ import { placementFromSideAlign } from "../../internal/floating/placement-aliases.js";
11
+ import { Slot } from "../../internal/slot/index.js";
10
12
  const defaultPositioning = {
11
13
  sideOffset: 0,
12
14
  collisionPadding: 0,
@@ -97,18 +99,24 @@ function PopoverRoot({ children, className, defaultOpen = false, modal = false,
97
99
  updateContentPositioning
98
100
  }, children: _jsx("div", { ...props, ref: handleRef, className: cn("liano-popover", className), "data-state": isOpen ? "open" : "closed", children: children }) }));
99
101
  }
100
- function PopoverTrigger({ className, onClick, ref, type = "button", ...props }) {
102
+ function PopoverTrigger({ asChild = false, className, disabled, onClick, ref, type = "button", ...props }) {
101
103
  const context = usePopoverContext("Popover.Trigger");
102
104
  const handleClick = () => {
105
+ if (disabled) {
106
+ return;
107
+ }
103
108
  context.setOpen((value) => !value);
104
109
  };
105
110
  const handleRef = React.useCallback((node) => {
106
111
  context.referenceRef(node);
107
112
  mergeRef(ref, node);
108
113
  }, [context.referenceRef, ref]);
109
- return (_jsx("button", { ...props, ref: handleRef, type: type, className: cn("liano-popover__trigger", className), "aria-expanded": context.open, "aria-controls": context.contentId, "aria-haspopup": "dialog", "data-state": context.open ? "open" : "closed", onClick: composeEventHandlers(onClick, handleClick) }));
114
+ if (asChild) {
115
+ return (_jsx(Slot, { ...props, ref: handleRef, "aria-controls": context.contentId, "aria-disabled": disabled ? true : undefined, "aria-expanded": context.open, "aria-haspopup": "dialog", className: cn("liano-popover__trigger", className), "data-disabled": disabled ? "true" : undefined, "data-state": context.open ? "open" : "closed", onClick: composeEventHandlers(onClick, handleClick), children: props.children }));
116
+ }
117
+ return (_jsx("button", { ...props, ref: handleRef, type: type, disabled: disabled, className: cn("liano-popover__trigger", className), "aria-expanded": context.open, "aria-controls": context.contentId, "aria-haspopup": "dialog", "data-state": context.open ? "open" : "closed", onClick: composeEventHandlers(onClick, handleClick) }));
110
118
  }
111
- function PopoverContent({ className, container, forceMount = false, id, disableEscapeKeyDown = false, disableOutsidePointerDown = false, ref, placement, sideOffset = 0, collisionPadding = 0, matchTriggerWidth = false, style, ...props }) {
119
+ function PopoverContent({ align, alignOffset: _alignOffset, className, container, forceMount = false, id, disableEscapeKeyDown = false, disableOutsidePointerDown = false, ref, placement, side, sideOffset = 0, collisionPadding = 0, matchTriggerWidth = false, style, ...props }) {
112
120
  const context = usePopoverContext("Popover.Content");
113
121
  const { defaultContentId, setContentId } = context;
114
122
  const transformOrigin = getTransformOrigin(context.floatingPlacement);
@@ -140,8 +148,9 @@ function PopoverContent({ className, container, forceMount = false, id, disableE
140
148
  }
141
149
  }, [context.referenceElement]);
142
150
  React.useEffect(() => {
151
+ const resolvedPlacement = side === undefined ? placement : placementFromSideAlign(side, align, placement ?? "bottom");
143
152
  context.updateContentPositioning({
144
- ...(placement === undefined ? {} : { placement }),
153
+ ...(resolvedPlacement === undefined ? {} : { placement: resolvedPlacement }),
145
154
  sideOffset,
146
155
  collisionPadding,
147
156
  matchTriggerWidth
@@ -149,7 +158,7 @@ function PopoverContent({ className, container, forceMount = false, id, disableE
149
158
  return () => {
150
159
  context.updateContentPositioning(defaultPositioning);
151
160
  };
152
- }, [context.updateContentPositioning, collisionPadding, matchTriggerWidth, placement, sideOffset]);
161
+ }, [align, context.updateContentPositioning, collisionPadding, matchTriggerWidth, placement, side, sideOffset]);
153
162
  if (!forceMount && !context.open) {
154
163
  return null;
155
164
  }
@@ -12,7 +12,8 @@ export interface SheetProps extends React.HTMLAttributes<HTMLDivElement> {
12
12
  ref?: React.Ref<HTMLDivElement>;
13
13
  }
14
14
  export interface SheetTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
15
- ref?: React.Ref<HTMLButtonElement>;
15
+ asChild?: boolean;
16
+ ref?: React.Ref<HTMLButtonElement | HTMLElement>;
16
17
  }
17
18
  export interface SheetContentProps extends React.HTMLAttributes<HTMLDivElement> {
18
19
  forceMount?: boolean;
@@ -31,16 +32,17 @@ export interface SheetFooterProps extends React.HTMLAttributes<HTMLDivElement> {
31
32
  ref?: React.Ref<HTMLDivElement>;
32
33
  }
33
34
  export interface SheetCloseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
34
- ref?: React.Ref<HTMLButtonElement>;
35
+ asChild?: boolean;
36
+ ref?: React.Ref<HTMLButtonElement | HTMLElement>;
35
37
  }
36
38
  declare function SheetRoot({ children, className, container, defaultOpen, disableEscapeKeyDown, disableOutsidePointerDown, onOpenChange, open: openProp, ref, side, ...props }: SheetProps): React.JSX.Element;
37
- declare function SheetTrigger({ className, disabled, onClick, ref, type, ...props }: SheetTriggerProps): React.JSX.Element;
39
+ declare function SheetTrigger({ asChild, className, disabled, onClick, ref, type, ...props }: SheetTriggerProps): React.JSX.Element;
38
40
  declare function SheetContent({ children, className, forceMount, ref, ...props }: SheetContentProps): React.JSX.Element | null;
39
41
  declare function SheetHeader({ className, ref, ...props }: SheetHeaderProps): React.JSX.Element;
40
42
  declare function SheetTitle({ className, ref, ...props }: SheetTitleProps): React.JSX.Element;
41
43
  declare function SheetDescription({ className, ref, ...props }: SheetDescriptionProps): React.JSX.Element;
42
44
  declare function SheetFooter({ className, ref, ...props }: SheetFooterProps): React.JSX.Element;
43
- declare function SheetClose({ className, onClick, ref, type, ...props }: SheetCloseProps): React.JSX.Element;
45
+ declare function SheetClose({ asChild, className, disabled, onClick, ref, type, ...props }: SheetCloseProps): React.JSX.Element;
44
46
  type SheetComponent = typeof SheetRoot & {
45
47
  Close: typeof SheetClose;
46
48
  Content: typeof SheetContent;
@@ -8,6 +8,7 @@ import { DismissableLayer } from "../../internal/dismissable-layer/index.js";
8
8
  import { FocusScope } from "../../internal/focus/index.js";
9
9
  import { Portal } from "../../internal/portal/index.js";
10
10
  import { lockScroll, unlockScroll } from "../../internal/scroll-lock/index.js";
11
+ import { Slot } from "../../internal/slot/index.js";
11
12
  const SheetContext = React.createContext(null);
12
13
  function useSheetContext(calledBy) {
13
14
  const context = React.useContext(SheetContext);
@@ -71,13 +72,17 @@ function SheetRoot({ children, className, container, defaultOpen = false, disabl
71
72
  triggerRef
72
73
  }, children: _jsx("div", { ...props, ref: ref, className: cn("liano-sheet", className), "data-state": open ? "open" : "closed", children: children }) }));
73
74
  }
74
- function SheetTrigger({ className, disabled, onClick, ref, type = "button", ...props }) {
75
+ function SheetTrigger({ asChild = false, className, disabled, onClick, ref, type = "button", ...props }) {
75
76
  const { contentId, open, setOpen, triggerRef } = useSheetContext("Sheet.Trigger");
76
- return (_jsx("button", { ...props, ref: composeRefs(ref, triggerRef), type: type, disabled: disabled, "aria-controls": contentId, "aria-expanded": open ? "true" : "false", className: cn("liano-sheet__trigger", className), "data-state": open ? "open" : "closed", onClick: composeEventHandlers(onClick, () => {
77
- if (!disabled) {
78
- setOpen(true);
79
- }
80
- }) }));
77
+ const handleClick = () => {
78
+ if (!disabled) {
79
+ setOpen(true);
80
+ }
81
+ };
82
+ if (asChild) {
83
+ return (_jsx(Slot, { ...props, ref: composeRefs(ref, triggerRef), "aria-controls": contentId, "aria-disabled": disabled ? true : undefined, "aria-expanded": open ? "true" : "false", className: cn("liano-sheet__trigger", className), "data-disabled": disabled ? "true" : undefined, "data-state": open ? "open" : "closed", onClick: composeEventHandlers(onClick, handleClick), children: props.children }));
84
+ }
85
+ return (_jsx("button", { ...props, ref: composeRefs(ref, triggerRef), type: type, disabled: disabled, "aria-controls": contentId, "aria-expanded": open ? "true" : "false", className: cn("liano-sheet__trigger", className), "data-state": open ? "open" : "closed", onClick: composeEventHandlers(onClick, handleClick) }));
81
86
  }
82
87
  function SheetContent({ children, className, forceMount = false, ref, ...props }) {
83
88
  const { close, container, contentId, describedBy, disableEscapeKeyDown, disableOutsidePointerDown, labelledBy, open, side } = useSheetContext("Sheet.Content");
@@ -108,9 +113,17 @@ function SheetDescription({ className, ref, ...props }) {
108
113
  function SheetFooter({ className, ref, ...props }) {
109
114
  return _jsx("div", { ...props, ref: ref, className: cn("liano-sheet__footer", className) });
110
115
  }
111
- function SheetClose({ className, onClick, ref, type = "button", ...props }) {
116
+ function SheetClose({ asChild = false, className, disabled, onClick, ref, type = "button", ...props }) {
112
117
  const { close } = useSheetContext("Sheet.Close");
113
- return (_jsx("button", { ...props, ref: ref, type: type, className: cn("liano-sheet__close", className), onClick: composeEventHandlers(onClick, close) }));
118
+ const handleClick = () => {
119
+ if (!disabled) {
120
+ close();
121
+ }
122
+ };
123
+ if (asChild) {
124
+ return (_jsx(Slot, { ...props, ref: ref, "aria-disabled": disabled ? true : undefined, className: cn("liano-sheet__close", className), "data-disabled": disabled ? "true" : undefined, onClick: composeEventHandlers(onClick, handleClick), children: props.children }));
125
+ }
126
+ return (_jsx("button", { ...props, ref: ref, type: type, disabled: disabled, className: cn("liano-sheet__close", className), onClick: composeEventHandlers(onClick, handleClick) }));
114
127
  }
115
128
  export const Sheet = Object.assign(SheetRoot, {
116
129
  Close: SheetClose,
@@ -1,2 +1,2 @@
1
- export { createToastController, Toast, ToastProvider, ToastViewport, useToast } from "./toast.js";
2
- export type { ToastActionProps, ToastCloseProps, ToastController, ToastInput, ToastOptions, ToastPlacement, ToastProviderProps, ToastProps, ToastTextProps, ToastTone, ToastViewportProps } from "./toast.js";
1
+ export { createToastController, toast, Toast, Toaster, ToastProvider, ToastViewport, useToast } from "./toast.js";
2
+ export type { ToasterPosition, ToasterProps, ToastActionInput, ToastActionProps, ToastCloseProps, ToastController, ToastInput, ToastOptions, ToastPlacement, ToastProviderProps, ToastProps, ToastTextProps, ToastTone, ToastViewportProps } from "./toast.js";
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- export { createToastController, Toast, ToastProvider, ToastViewport, useToast } from "./toast.js";
2
+ export { createToastController, toast, Toast, Toaster, ToastProvider, ToastViewport, useToast } from "./toast.js";
@@ -1,16 +1,21 @@
1
1
  import * as React from "react";
2
2
  export type ToastTone = "neutral" | "success" | "warning" | "destructive" | "info";
3
3
  export type ToastPlacement = "top-right" | "top-left" | "bottom-right" | "bottom-left";
4
+ export type ToasterPosition = "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right";
4
5
  export type ToastInput = string | {
5
6
  title?: React.ReactNode;
6
7
  description?: React.ReactNode;
7
8
  };
9
+ export type ToastActionInput = React.ReactNode | {
10
+ label: React.ReactNode;
11
+ onClick: () => void;
12
+ };
8
13
  export type ToastOptions = {
9
14
  id?: string;
10
15
  description?: React.ReactNode;
11
16
  duration?: number;
12
- action?: React.ReactNode;
13
- cancel?: React.ReactNode;
17
+ action?: ToastActionInput;
18
+ cancel?: ToastActionInput;
14
19
  };
15
20
  export type ToastController = {
16
21
  (input: ToastInput, options?: ToastOptions): string;
@@ -41,10 +46,19 @@ export interface ToastProviderProps extends Omit<ToastViewportProps, "children">
41
46
  children?: React.ReactNode;
42
47
  controller?: ToastController;
43
48
  }
49
+ export interface ToasterProps extends Omit<ToastProviderProps, "placement"> {
50
+ position?: ToasterPosition;
51
+ richColors?: boolean;
52
+ expand?: boolean;
53
+ offset?: number | string;
54
+ toastOptions?: ToastOptions;
55
+ }
44
56
  export declare function ToastViewport({ className, placement, ref, ...props }: ToastViewportProps): React.ReactElement;
45
57
  export declare function createToastController(): ToastController;
58
+ export declare const toast: ToastController;
46
59
  export declare function useToast(): ToastController;
47
60
  export declare function ToastProvider({ children, controller, placement, ref, ...viewportProps }: ToastProviderProps): React.ReactElement;
61
+ export declare function Toaster({ controller, expand: _expand, offset, position, richColors: _richColors, style, toastOptions: _toastOptions, ...props }: ToasterProps): React.ReactElement;
48
62
  declare function ToastRoot({ className, ref, role, tone, ...props }: ToastProps): React.JSX.Element;
49
63
  declare function ToastTitle({ className, ref, ...props }: ToastTextProps): React.JSX.Element;
50
64
  declare function ToastDescription({ className, ref, ...props }: ToastTextProps): React.JSX.Element;
@@ -27,6 +27,36 @@ function resolveToastContent(input, options) {
27
27
  description: options.description ?? input.description
28
28
  };
29
29
  }
30
+ function mapToPlacement(position) {
31
+ if (position === "top-center") {
32
+ return "top-right";
33
+ }
34
+ if (position === "bottom-center") {
35
+ return "bottom-right";
36
+ }
37
+ return position;
38
+ }
39
+ function toastTypeFromTone(tone) {
40
+ if (tone === "destructive") {
41
+ return "error";
42
+ }
43
+ if (tone === "neutral") {
44
+ return "default";
45
+ }
46
+ return tone;
47
+ }
48
+ function isToastActionObject(input) {
49
+ return typeof input === "object" && input !== null && !React.isValidElement(input) && "label" in input && "onClick" in input;
50
+ }
51
+ function renderToastControl(input) {
52
+ if (input === undefined) {
53
+ return null;
54
+ }
55
+ if (isToastActionObject(input)) {
56
+ return _jsx(Toast.Action, { onClick: input.onClick, children: input.label });
57
+ }
58
+ return input;
59
+ }
30
60
  export function ToastViewport({ className, placement = "top-right", ref, ...props }) {
31
61
  return (_jsx("div", { ...props, ref: ref, "aria-label": props["aria-label"] ?? "Notifications", className: cn("liano-toast-viewport", className), "data-placement": placement, role: "region" }));
32
62
  }
@@ -76,6 +106,7 @@ export function createToastController() {
76
106
  });
77
107
  return controller;
78
108
  }
109
+ export const toast = createToastController();
79
110
  export function useToast() {
80
111
  const controller = React.useContext(ToastControllerContext);
81
112
  if (!controller) {
@@ -94,6 +125,16 @@ export function ToastProvider({ children, controller, placement = "top-right", r
94
125
  const viewportRefProps = ref ? { ref } : {};
95
126
  return (_jsxs(ToastControllerContext.Provider, { value: activeController, children: [children, _jsx(ToastViewport, { ...viewportProps, ...viewportRefProps, placement: placement, children: toasts.map((toast) => (_jsx(ToastProviderItem, { toast: toast, onDismiss: dismissToast }, toast.id))) })] }));
96
127
  }
128
+ export function Toaster({ controller = toast, expand: _expand, offset, position = "top-right", richColors: _richColors, style, toastOptions: _toastOptions, ...props }) {
129
+ const placement = mapToPlacement(position);
130
+ const offsetStyle = offset === undefined
131
+ ? style
132
+ : {
133
+ ...style,
134
+ "--liano-toast-viewport-inset": typeof offset === "number" ? `${offset}px` : offset
135
+ };
136
+ return (_jsx(ToastProvider, { ...props, controller: controller, placement: placement, ...(offsetStyle === undefined ? {} : { style: offsetStyle }) }));
137
+ }
97
138
  function ToastProviderItem({ onDismiss, toast }) {
98
139
  React.useEffect(() => {
99
140
  if (toast.duration === Infinity) {
@@ -102,10 +143,11 @@ function ToastProviderItem({ onDismiss, toast }) {
102
143
  const timeout = window.setTimeout(() => onDismiss(toast.id), toast.duration);
103
144
  return () => window.clearTimeout(timeout);
104
145
  }, [onDismiss, toast.duration, toast.id, toast.version]);
105
- return (_jsxs(Toast, { tone: toast.tone, children: [(toast.title || toast.description) && (_jsxs("div", { className: "liano-toast__content", children: [toast.title && _jsx(Toast.Title, { children: toast.title }), toast.description && _jsx(Toast.Description, { children: toast.description })] })), (toast.action || toast.cancel) && (_jsxs("div", { className: "liano-toast__controls", children: [toast.action, toast.cancel] })), _jsx(Toast.Close, { "aria-label": "Dismiss notification", onClick: () => onDismiss(toast.id) })] }));
146
+ return (_jsxs(Toast, { tone: toast.tone, children: [(toast.title || toast.description) && (_jsxs("div", { className: "liano-toast__content", children: [toast.title && _jsx(Toast.Title, { children: toast.title }), toast.description && _jsx(Toast.Description, { children: toast.description })] })), (toast.action || toast.cancel) && (_jsxs("div", { className: "liano-toast__controls", children: [renderToastControl(toast.action), renderToastControl(toast.cancel)] })), _jsx(Toast.Close, { "aria-label": "Dismiss notification", onClick: () => onDismiss(toast.id) })] }));
106
147
  }
107
148
  function ToastRoot({ className, ref, role, tone = "neutral", ...props }) {
108
- return (_jsx("div", { ...props, ref: ref, className: cn("liano-toast", className), "data-tone": tone, role: role ?? (tone === "destructive" ? "alert" : "status") }));
149
+ const toastType = toastTypeFromTone(tone);
150
+ return (_jsx("div", { ...props, ref: ref, className: cn("liano-toast", className), "data-sonner-toast": "", "data-tone": tone, "data-type": toastType, "data-visible": "true", role: role ?? (tone === "destructive" ? "alert" : "status") }));
109
151
  }
110
152
  function ToastTitle({ className, ref, ...props }) {
111
153
  return _jsx("div", { ...props, ref: ref, className: cn("liano-toast__title", className) });
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import type { PortalProps } from "../../internal/portal/index.js";
3
3
  import type { FloatingPlacement } from "../../internal/floating/index.js";
4
+ import type { FloatingAlign, FloatingSide } from "../../internal/floating/placement-aliases.js";
4
5
  export interface TooltipProps {
5
6
  children: React.ReactElement;
6
7
  content: React.ReactNode;
@@ -23,9 +24,14 @@ export interface TooltipRootProps {
23
24
  onOpenChange?: (open: boolean) => void;
24
25
  }
25
26
  export interface TooltipTriggerProps {
27
+ asChild?: boolean;
26
28
  children: React.ReactElement;
27
29
  }
28
30
  export interface TooltipContentProps extends React.HTMLAttributes<HTMLSpanElement> {
31
+ placement?: FloatingPlacement;
32
+ side?: FloatingSide;
33
+ align?: FloatingAlign;
34
+ alignOffset?: number;
29
35
  sideOffset?: number;
30
36
  collisionPadding?: number;
31
37
  forceMount?: boolean;
@@ -34,8 +40,8 @@ export interface TooltipContentProps extends React.HTMLAttributes<HTMLSpanElemen
34
40
  }
35
41
  declare function TooltipProvider({ children, delayDuration }: TooltipProviderProps): React.JSX.Element;
36
42
  declare function TooltipRoot({ children, defaultOpen, delay, disabled, onOpenChange, open: openProp, placement }: TooltipRootProps): React.JSX.Element;
37
- declare function TooltipTrigger({ children }: TooltipTriggerProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
38
- declare function TooltipContent({ children, className, collisionPadding, container, forceMount, ref, sideOffset, style, ...props }: TooltipContentProps): React.JSX.Element | null;
43
+ declare function TooltipTrigger({ children, asChild: _asChild }: TooltipTriggerProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
44
+ declare function TooltipContent({ align, alignOffset: _alignOffset, children, className, collisionPadding, container, forceMount, placement, ref, side, sideOffset, style, ...props }: TooltipContentProps): React.JSX.Element | null;
39
45
  declare function TooltipWrapper({ children, content, delay, disabled, placement }: TooltipProps): React.JSX.Element;
40
46
  export declare const Tooltip: typeof TooltipWrapper & {
41
47
  Content: typeof TooltipContent;