@pixpilot/shadcn-ui 0.35.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,82 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const require_svg = require('./utils/svg.cjs');
3
+ let __pixpilot_shadcn = require("@pixpilot/shadcn");
4
+ __pixpilot_shadcn = require_rolldown_runtime.__toESM(__pixpilot_shadcn);
5
+ let react = require("react");
6
+ react = require_rolldown_runtime.__toESM(react);
7
+ let react_jsx_runtime = require("react/jsx-runtime");
8
+ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
9
+
10
+ //#region src/IconToggle.tsx
11
+ /**
12
+ * IconToggle - A toggle button component with customizable icons for checked/unchecked states.
13
+ * Perfect for visibility toggles, theme switches, or any boolean state with visual feedback.
14
+ * Icons can be React components (like lucide-react icons) or SVG markup strings.
15
+ */
16
+ const IconToggle = react.default.forwardRef(({ checked: controlledChecked, defaultChecked = false, onCheckedChange, onChange, checkedIcon, uncheckedIcon, size = "default", variant = "default", className, disabled,...props }, ref) => {
17
+ const [uncontrolledChecked, setUncontrolledChecked] = react.default.useState(defaultChecked);
18
+ const isControlled = controlledChecked !== void 0;
19
+ const checked = isControlled ? controlledChecked : uncontrolledChecked;
20
+ const handleClick = (0, react.useCallback)((e) => {
21
+ if (disabled) return;
22
+ const newChecked = !checked;
23
+ if (!isControlled) setUncontrolledChecked(newChecked);
24
+ onCheckedChange?.(newChecked);
25
+ onChange?.(newChecked);
26
+ props.onClick?.(e);
27
+ }, [
28
+ checked,
29
+ disabled,
30
+ isControlled,
31
+ onChange,
32
+ onCheckedChange,
33
+ props
34
+ ]);
35
+ const renderIcon = (icon) => {
36
+ if (icon === void 0 || icon === null) return null;
37
+ if (require_svg.isSvgMarkupString(icon)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38
+ "data-slot": "svg-mask",
39
+ "aria-hidden": "true",
40
+ className: "inline-block h-4 w-4",
41
+ style: {
42
+ backgroundColor: "currentColor",
43
+ WebkitMaskImage: require_svg.svgMarkupToMaskUrl(icon),
44
+ maskImage: require_svg.svgMarkupToMaskUrl(icon),
45
+ WebkitMaskRepeat: "no-repeat",
46
+ maskRepeat: "no-repeat",
47
+ WebkitMaskPosition: "center",
48
+ maskPosition: "center",
49
+ WebkitMaskSize: "contain",
50
+ maskSize: "contain"
51
+ }
52
+ });
53
+ return icon;
54
+ };
55
+ const sizeClasses = {
56
+ sm: "size-7",
57
+ default: "size-9",
58
+ lg: "size-11"
59
+ };
60
+ const variantClasses = {
61
+ default: "bg-background border border-input hover:bg-accent hover:text-accent-foreground data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:hover:bg-primary/90",
62
+ outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground data-[state=checked]:border-primary data-[state=checked]:text-primary",
63
+ ghost: "hover:bg-accent hover:text-accent-foreground data-[state=checked]:bg-primary/10 data-[state=checked]:text-primary"
64
+ };
65
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
66
+ ref,
67
+ type: "button",
68
+ role: "switch",
69
+ "aria-checked": checked,
70
+ "data-state": checked ? "checked" : "unchecked",
71
+ "data-slot": "icon-toggle",
72
+ disabled,
73
+ className: (0, __pixpilot_shadcn.cn)("inline-flex items-center justify-center rounded-md text-sm font-medium transition-all outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50", "[&_svg]:pointer-events-none [&_svg:not([class*=\"size-\"])]:size-4 [&_svg]:shrink-0", sizeClasses[size], variantClasses[variant], className),
74
+ onClick: handleClick,
75
+ ...props,
76
+ children: checked ? renderIcon(checkedIcon) : renderIcon(uncheckedIcon)
77
+ });
78
+ });
79
+ IconToggle.displayName = "IconToggle";
80
+
81
+ //#endregion
82
+ exports.IconToggle = IconToggle;
@@ -0,0 +1,49 @@
1
+ import React from "react";
2
+
3
+ //#region src/IconToggle.d.ts
4
+ interface IconToggleProps extends Omit<React.ComponentProps<'button'>, 'onChange'> {
5
+ /**
6
+ * The checked/toggled state
7
+ */
8
+ checked?: boolean;
9
+ /**
10
+ * Default checked state for uncontrolled usage
11
+ */
12
+ defaultChecked?: boolean;
13
+ /**
14
+ * Called when the toggle state changes (controlled)
15
+ */
16
+ onCheckedChange?: (checked: boolean) => void;
17
+ /**
18
+ * Called when the toggle state changes (alternative handler)
19
+ */
20
+ onChange?: (checked: boolean) => void;
21
+ /**
22
+ * Icon to show when checked (true state)
23
+ * Can be a React component (like lucide-react icons) or SVG markup string
24
+ */
25
+ checkedIcon?: React.ReactNode | string;
26
+ /**
27
+ * Icon to show when unchecked (false state)
28
+ * Can be a React component (like lucide-react icons) or SVG markup string
29
+ */
30
+ uncheckedIcon?: React.ReactNode | string;
31
+ /**
32
+ * Size variant of the toggle button
33
+ * @default 'default'
34
+ */
35
+ size?: 'sm' | 'default' | 'lg';
36
+ /**
37
+ * Visual variant of the toggle button
38
+ * @default 'default'
39
+ */
40
+ variant?: 'default' | 'outline' | 'ghost';
41
+ }
42
+ /**
43
+ * IconToggle - A toggle button component with customizable icons for checked/unchecked states.
44
+ * Perfect for visibility toggles, theme switches, or any boolean state with visual feedback.
45
+ * Icons can be React components (like lucide-react icons) or SVG markup strings.
46
+ */
47
+ declare const IconToggle: React.ForwardRefExoticComponent<Omit<IconToggleProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
48
+ //#endregion
49
+ export { IconToggle, IconToggleProps };
@@ -0,0 +1,49 @@
1
+ import React from "react";
2
+
3
+ //#region src/IconToggle.d.ts
4
+ interface IconToggleProps extends Omit<React.ComponentProps<'button'>, 'onChange'> {
5
+ /**
6
+ * The checked/toggled state
7
+ */
8
+ checked?: boolean;
9
+ /**
10
+ * Default checked state for uncontrolled usage
11
+ */
12
+ defaultChecked?: boolean;
13
+ /**
14
+ * Called when the toggle state changes (controlled)
15
+ */
16
+ onCheckedChange?: (checked: boolean) => void;
17
+ /**
18
+ * Called when the toggle state changes (alternative handler)
19
+ */
20
+ onChange?: (checked: boolean) => void;
21
+ /**
22
+ * Icon to show when checked (true state)
23
+ * Can be a React component (like lucide-react icons) or SVG markup string
24
+ */
25
+ checkedIcon?: React.ReactNode | string;
26
+ /**
27
+ * Icon to show when unchecked (false state)
28
+ * Can be a React component (like lucide-react icons) or SVG markup string
29
+ */
30
+ uncheckedIcon?: React.ReactNode | string;
31
+ /**
32
+ * Size variant of the toggle button
33
+ * @default 'default'
34
+ */
35
+ size?: 'sm' | 'default' | 'lg';
36
+ /**
37
+ * Visual variant of the toggle button
38
+ * @default 'default'
39
+ */
40
+ variant?: 'default' | 'outline' | 'ghost';
41
+ }
42
+ /**
43
+ * IconToggle - A toggle button component with customizable icons for checked/unchecked states.
44
+ * Perfect for visibility toggles, theme switches, or any boolean state with visual feedback.
45
+ * Icons can be React components (like lucide-react icons) or SVG markup strings.
46
+ */
47
+ declare const IconToggle: React.ForwardRefExoticComponent<Omit<IconToggleProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
48
+ //#endregion
49
+ export { IconToggle, IconToggleProps };
@@ -0,0 +1,78 @@
1
+ import { isSvgMarkupString, svgMarkupToMaskUrl } from "./utils/svg.js";
2
+ import { cn } from "@pixpilot/shadcn";
3
+ import React, { useCallback } from "react";
4
+ import { jsx } from "react/jsx-runtime";
5
+
6
+ //#region src/IconToggle.tsx
7
+ /**
8
+ * IconToggle - A toggle button component with customizable icons for checked/unchecked states.
9
+ * Perfect for visibility toggles, theme switches, or any boolean state with visual feedback.
10
+ * Icons can be React components (like lucide-react icons) or SVG markup strings.
11
+ */
12
+ const IconToggle = React.forwardRef(({ checked: controlledChecked, defaultChecked = false, onCheckedChange, onChange, checkedIcon, uncheckedIcon, size = "default", variant = "default", className, disabled,...props }, ref) => {
13
+ const [uncontrolledChecked, setUncontrolledChecked] = React.useState(defaultChecked);
14
+ const isControlled = controlledChecked !== void 0;
15
+ const checked = isControlled ? controlledChecked : uncontrolledChecked;
16
+ const handleClick = useCallback((e) => {
17
+ if (disabled) return;
18
+ const newChecked = !checked;
19
+ if (!isControlled) setUncontrolledChecked(newChecked);
20
+ onCheckedChange?.(newChecked);
21
+ onChange?.(newChecked);
22
+ props.onClick?.(e);
23
+ }, [
24
+ checked,
25
+ disabled,
26
+ isControlled,
27
+ onChange,
28
+ onCheckedChange,
29
+ props
30
+ ]);
31
+ const renderIcon = (icon) => {
32
+ if (icon === void 0 || icon === null) return null;
33
+ if (isSvgMarkupString(icon)) return /* @__PURE__ */ jsx("span", {
34
+ "data-slot": "svg-mask",
35
+ "aria-hidden": "true",
36
+ className: "inline-block h-4 w-4",
37
+ style: {
38
+ backgroundColor: "currentColor",
39
+ WebkitMaskImage: svgMarkupToMaskUrl(icon),
40
+ maskImage: svgMarkupToMaskUrl(icon),
41
+ WebkitMaskRepeat: "no-repeat",
42
+ maskRepeat: "no-repeat",
43
+ WebkitMaskPosition: "center",
44
+ maskPosition: "center",
45
+ WebkitMaskSize: "contain",
46
+ maskSize: "contain"
47
+ }
48
+ });
49
+ return icon;
50
+ };
51
+ const sizeClasses = {
52
+ sm: "size-7",
53
+ default: "size-9",
54
+ lg: "size-11"
55
+ };
56
+ const variantClasses = {
57
+ default: "bg-background border border-input hover:bg-accent hover:text-accent-foreground data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:hover:bg-primary/90",
58
+ outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground data-[state=checked]:border-primary data-[state=checked]:text-primary",
59
+ ghost: "hover:bg-accent hover:text-accent-foreground data-[state=checked]:bg-primary/10 data-[state=checked]:text-primary"
60
+ };
61
+ return /* @__PURE__ */ jsx("button", {
62
+ ref,
63
+ type: "button",
64
+ role: "switch",
65
+ "aria-checked": checked,
66
+ "data-state": checked ? "checked" : "unchecked",
67
+ "data-slot": "icon-toggle",
68
+ disabled,
69
+ className: cn("inline-flex items-center justify-center rounded-md text-sm font-medium transition-all outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50", "[&_svg]:pointer-events-none [&_svg:not([class*=\"size-\"])]:size-4 [&_svg]:shrink-0", sizeClasses[size], variantClasses[variant], className),
70
+ onClick: handleClick,
71
+ ...props,
72
+ children: checked ? renderIcon(checkedIcon) : renderIcon(uncheckedIcon)
73
+ });
74
+ });
75
+ IconToggle.displayName = "IconToggle";
76
+
77
+ //#endregion
78
+ export { IconToggle };
package/dist/index.cjs CHANGED
@@ -31,6 +31,8 @@ require('./input/index.cjs');
31
31
  const require_LoadingOverlay = require('./LoadingOverlay.cjs');
32
32
  const require_IconPicker = require('./icon-selector/IconPicker.cjs');
33
33
  require('./icon-selector/index.cjs');
34
+ const require_svg = require('./utils/svg.cjs');
35
+ const require_IconToggle = require('./IconToggle.cjs');
34
36
  const require_Layout = require('./layout/Layout.cjs');
35
37
  const require_LayoutFooter = require('./layout/LayoutFooter.cjs');
36
38
  const require_LayoutHeader = require('./layout/LayoutHeader.cjs');
@@ -84,6 +86,7 @@ exports.DialogProvider = require_DialogProvider.DialogProvider;
84
86
  exports.FileUpload = require_FileUpload.FileUpload;
85
87
  exports.FileUploadInline = require_FileUploadInline.FileUploadInline;
86
88
  exports.IconPicker = require_IconPicker.IconPicker;
89
+ exports.IconToggle = require_IconToggle.IconToggle;
87
90
  exports.Input = require_Input.Input;
88
91
  exports.Layout = require_Layout.Layout;
89
92
  exports.LayoutFooter = require_LayoutFooter.LayoutFooter;
@@ -110,7 +113,9 @@ exports.ThemeModeToggleButton = require_ThemeModeToggleButton.ThemeModeToggleBut
110
113
  exports.ThemeProvider = require_ThemeProvider.ThemeProvider;
111
114
  exports.Toaster = require_ToastProvider.Toaster;
112
115
  exports.cn = __pixpilot_shadcn.cn;
116
+ exports.isSvgMarkupString = require_svg.isSvgMarkupString;
113
117
  exports.showConfirmDialog = require_confirmation_dialogs.showConfirmDialog;
118
+ exports.svgMarkupToMaskUrl = require_svg.svgMarkupToMaskUrl;
114
119
  exports.toast = require_toast.toast;
115
120
  exports.toastError = require_toast.toastError;
116
121
  exports.toastInfo = require_toast.toastInfo;
package/dist/index.d.cts CHANGED
@@ -30,6 +30,7 @@ import "./hooks/index.cjs";
30
30
  import { IconProvider, IconProviderLoader, IconProviderProps } from "./icon-selector/types.cjs";
31
31
  import { IconPicker, IconPickerProps, IconPickerVariant } from "./icon-selector/IconPicker.cjs";
32
32
  import "./icon-selector/index.cjs";
33
+ import { IconToggle, IconToggleProps } from "./IconToggle.cjs";
33
34
  import { Input, InputProps } from "./input/Input.cjs";
34
35
  import "./input/index.cjs";
35
36
  import { Layout, LayoutProps } from "./layout/Layout.cjs";
@@ -66,5 +67,6 @@ import "./theme-toggle/index.cjs";
66
67
  import { DEFAULT_ALERT_DURATION, ToastMessage, toast, toastError, toastInfo, toastSuccess, toastWarning } from "./toast/toast.cjs";
67
68
  import { Toaster } from "./toast/ToastProvider.cjs";
68
69
  import "./toast/index.cjs";
70
+ import { isSvgMarkupString, svgMarkupToMaskUrl } from "./utils/svg.cjs";
69
71
  import { cn } from "@pixpilot/shadcn";
70
- export { AbsoluteFill, Alert, AlertBaseProps, AlertProps, AlertVariant, AvatarUpload, AvatarUploadProps, BaseTabsTriggerProps, Button, ButtonLoaderProps, ButtonProps, CircleLoader, CircleLoaderProps, CloseButtonAbsolute, CloseButtonRounded, CloseButtonRoundedProps, ColorPicker, ColorPickerBase, ColorPickerBaseProps, ColorPickerBaseSection, ColorPickerProps, ColorSelect, ColorSelectOption, BaseColorSelectProps as ColorSelectProps, Combobox, ConfirmationDialogProps, ContentCard, DEFAULT_ALERT_DURATION, DatePicker, DatePickerProps, DialogProvider, DialogProviderProps, type FileMetadata, FileUpload, FileUploadBaseProps, FileUploadInline, FileUploadInlineBaseProps, FileUploadInlineProps, type FileUploadProgressCallBacks, type FileUploadProps, IconPicker, IconPickerProps, IconPickerVariant, IconProvider, IconProviderLoader, IconProviderProps, Input, InputProps, Layout, LayoutFooter, LayoutFooterProps, LayoutHeader, LayoutHeaderProps, LayoutMain, LayoutMainProps, LayoutProps, LoaderProps, LoadingOverlay, MultiFileUploadProps, OnChangeMultipleFiles, OnChangeSingleFile, Pagination, PaginationProps, PopoverCloseButtonProps, PresetColor, RichTextEditor, RichTextEditorProps, RichTextEditorSlots, ScaledPreview, ScaledPreviewProps, ScaledPreviewSize, Select, SelectOption, SingleFileUploadProps, Slider, SliderInput, SliderInputProps, SliderProps, SliderSelect, SliderSelectOption, SliderSelectProps, SliderSelectValue, Tabs, TabsContent, TabsContext, TabsContextValue, TabsList, TabsListProps, TabsTrigger, TabsTriggerProps, TabsVariant, TagsInput, TagsInputProps, ThemeModeDropdown, ThemeModeDropdownProps, ThemeModeSwitchInside, ThemeModeSwitchInsideProps, ThemeModeSwitchInsideSize, ThemeModeSwitchOutside, ThemeModeSwitchOutsideProps, ThemeModeToggleButton, ThemeModeToggleButtonProps, ThemeProvider, ThemeProviderProps, ToastMessage, Toaster, ToolbarItems, cn, showConfirmDialog, toast, toastError, toastInfo, toastSuccess, toastWarning, useMediaQuery, useSelectKeyboard, useTabsContext, useTheme };
72
+ export { AbsoluteFill, Alert, AlertBaseProps, AlertProps, AlertVariant, AvatarUpload, AvatarUploadProps, BaseTabsTriggerProps, Button, ButtonLoaderProps, ButtonProps, CircleLoader, CircleLoaderProps, CloseButtonAbsolute, CloseButtonRounded, CloseButtonRoundedProps, ColorPicker, ColorPickerBase, ColorPickerBaseProps, ColorPickerBaseSection, ColorPickerProps, ColorSelect, ColorSelectOption, BaseColorSelectProps as ColorSelectProps, Combobox, ConfirmationDialogProps, ContentCard, DEFAULT_ALERT_DURATION, DatePicker, DatePickerProps, DialogProvider, DialogProviderProps, type FileMetadata, FileUpload, FileUploadBaseProps, FileUploadInline, FileUploadInlineBaseProps, FileUploadInlineProps, type FileUploadProgressCallBacks, type FileUploadProps, IconPicker, IconPickerProps, IconPickerVariant, IconProvider, IconProviderLoader, IconProviderProps, IconToggle, IconToggleProps, Input, InputProps, Layout, LayoutFooter, LayoutFooterProps, LayoutHeader, LayoutHeaderProps, LayoutMain, LayoutMainProps, LayoutProps, LoaderProps, LoadingOverlay, MultiFileUploadProps, OnChangeMultipleFiles, OnChangeSingleFile, Pagination, PaginationProps, PopoverCloseButtonProps, PresetColor, RichTextEditor, RichTextEditorProps, RichTextEditorSlots, ScaledPreview, ScaledPreviewProps, ScaledPreviewSize, Select, SelectOption, SingleFileUploadProps, Slider, SliderInput, SliderInputProps, SliderProps, SliderSelect, SliderSelectOption, SliderSelectProps, SliderSelectValue, Tabs, TabsContent, TabsContext, TabsContextValue, TabsList, TabsListProps, TabsTrigger, TabsTriggerProps, TabsVariant, TagsInput, TagsInputProps, ThemeModeDropdown, ThemeModeDropdownProps, ThemeModeSwitchInside, ThemeModeSwitchInsideProps, ThemeModeSwitchInsideSize, ThemeModeSwitchOutside, ThemeModeSwitchOutsideProps, ThemeModeToggleButton, ThemeModeToggleButtonProps, ThemeProvider, ThemeProviderProps, ToastMessage, Toaster, ToolbarItems, cn, isSvgMarkupString, showConfirmDialog, svgMarkupToMaskUrl, toast, toastError, toastInfo, toastSuccess, toastWarning, useMediaQuery, useSelectKeyboard, useTabsContext, useTheme };
package/dist/index.d.ts CHANGED
@@ -32,6 +32,7 @@ import "./hooks/index.js";
32
32
  import { IconProvider, IconProviderLoader, IconProviderProps } from "./icon-selector/types.js";
33
33
  import { IconPicker, IconPickerProps, IconPickerVariant } from "./icon-selector/IconPicker.js";
34
34
  import "./icon-selector/index.js";
35
+ import { IconToggle, IconToggleProps } from "./IconToggle.js";
35
36
  import { Input, InputProps } from "./input/Input.js";
36
37
  import "./input/index.js";
37
38
  import { Layout, LayoutProps } from "./layout/Layout.js";
@@ -68,5 +69,6 @@ import "./theme-toggle/index.js";
68
69
  import { DEFAULT_ALERT_DURATION, ToastMessage, toast, toastError, toastInfo, toastSuccess, toastWarning } from "./toast/toast.js";
69
70
  import { Toaster } from "./toast/ToastProvider.js";
70
71
  import "./toast/index.js";
72
+ import { isSvgMarkupString, svgMarkupToMaskUrl } from "./utils/svg.js";
71
73
  import { cn } from "@pixpilot/shadcn";
72
- export { AbsoluteFill, Alert, AlertBaseProps, AlertProps, AlertVariant, AvatarUpload, AvatarUploadProps, BaseTabsTriggerProps, Button, ButtonLoaderProps, ButtonProps, CircleLoader, CircleLoaderProps, CloseButtonAbsolute, CloseButtonRounded, CloseButtonRoundedProps, ColorPicker, ColorPickerBase, ColorPickerBaseProps, ColorPickerBaseSection, ColorPickerProps, ColorSelect, ColorSelectOption, BaseColorSelectProps as ColorSelectProps, Combobox, ConfirmationDialogProps, ContentCard, DEFAULT_ALERT_DURATION, DatePicker, DatePickerProps, DialogProvider, DialogProviderProps, type FileMetadata, FileUpload, FileUploadBaseProps, FileUploadInline, FileUploadInlineBaseProps, FileUploadInlineProps, type FileUploadProgressCallBacks, type FileUploadProps, IconPicker, IconPickerProps, IconPickerVariant, IconProvider, IconProviderLoader, IconProviderProps, Input, InputProps, Layout, LayoutFooter, LayoutFooterProps, LayoutHeader, LayoutHeaderProps, LayoutMain, LayoutMainProps, LayoutProps, LoaderProps, LoadingOverlay, MultiFileUploadProps, OnChangeMultipleFiles, OnChangeSingleFile, Pagination, PaginationProps, PopoverCloseButtonProps, PresetColor, RichTextEditor, RichTextEditorProps, RichTextEditorSlots, ScaledPreview, ScaledPreviewProps, ScaledPreviewSize, Select, SelectOption, SingleFileUploadProps, Slider, SliderInput, SliderInputProps, SliderProps, SliderSelect, SliderSelectOption, SliderSelectProps, SliderSelectValue, Tabs, TabsContent, TabsContext, TabsContextValue, TabsList, TabsListProps, TabsTrigger, TabsTriggerProps, TabsVariant, TagsInput, TagsInputProps, ThemeModeDropdown, ThemeModeDropdownProps, ThemeModeSwitchInside, ThemeModeSwitchInsideProps, ThemeModeSwitchInsideSize, ThemeModeSwitchOutside, ThemeModeSwitchOutsideProps, ThemeModeToggleButton, ThemeModeToggleButtonProps, ThemeProvider, ThemeProviderProps, ToastMessage, Toaster, ToolbarItems, cn, showConfirmDialog, toast, toastError, toastInfo, toastSuccess, toastWarning, useMediaQuery, useSelectKeyboard, useTabsContext, useTheme };
74
+ export { AbsoluteFill, Alert, AlertBaseProps, AlertProps, AlertVariant, AvatarUpload, AvatarUploadProps, BaseTabsTriggerProps, Button, ButtonLoaderProps, ButtonProps, CircleLoader, CircleLoaderProps, CloseButtonAbsolute, CloseButtonRounded, CloseButtonRoundedProps, ColorPicker, ColorPickerBase, ColorPickerBaseProps, ColorPickerBaseSection, ColorPickerProps, ColorSelect, ColorSelectOption, BaseColorSelectProps as ColorSelectProps, Combobox, ConfirmationDialogProps, ContentCard, DEFAULT_ALERT_DURATION, DatePicker, DatePickerProps, DialogProvider, DialogProviderProps, type FileMetadata, FileUpload, FileUploadBaseProps, FileUploadInline, FileUploadInlineBaseProps, FileUploadInlineProps, type FileUploadProgressCallBacks, type FileUploadProps, IconPicker, IconPickerProps, IconPickerVariant, IconProvider, IconProviderLoader, IconProviderProps, IconToggle, IconToggleProps, Input, InputProps, Layout, LayoutFooter, LayoutFooterProps, LayoutHeader, LayoutHeaderProps, LayoutMain, LayoutMainProps, LayoutProps, LoaderProps, LoadingOverlay, MultiFileUploadProps, OnChangeMultipleFiles, OnChangeSingleFile, Pagination, PaginationProps, PopoverCloseButtonProps, PresetColor, RichTextEditor, RichTextEditorProps, RichTextEditorSlots, ScaledPreview, ScaledPreviewProps, ScaledPreviewSize, Select, SelectOption, SingleFileUploadProps, Slider, SliderInput, SliderInputProps, SliderProps, SliderSelect, SliderSelectOption, SliderSelectProps, SliderSelectValue, Tabs, TabsContent, TabsContext, TabsContextValue, TabsList, TabsListProps, TabsTrigger, TabsTriggerProps, TabsVariant, TagsInput, TagsInputProps, ThemeModeDropdown, ThemeModeDropdownProps, ThemeModeSwitchInside, ThemeModeSwitchInsideProps, ThemeModeSwitchInsideSize, ThemeModeSwitchOutside, ThemeModeSwitchOutsideProps, ThemeModeToggleButton, ThemeModeToggleButtonProps, ThemeProvider, ThemeProviderProps, ToastMessage, Toaster, ToolbarItems, cn, isSvgMarkupString, showConfirmDialog, svgMarkupToMaskUrl, toast, toastError, toastInfo, toastSuccess, toastWarning, useMediaQuery, useSelectKeyboard, useTabsContext, useTheme };
package/dist/index.js CHANGED
@@ -30,6 +30,8 @@ import "./input/index.js";
30
30
  import { LoadingOverlay } from "./LoadingOverlay.js";
31
31
  import { IconPicker } from "./icon-selector/IconPicker.js";
32
32
  import "./icon-selector/index.js";
33
+ import { isSvgMarkupString, svgMarkupToMaskUrl } from "./utils/svg.js";
34
+ import { IconToggle } from "./IconToggle.js";
33
35
  import { Layout } from "./layout/Layout.js";
34
36
  import { LayoutFooter } from "./layout/LayoutFooter.js";
35
37
  import { LayoutHeader } from "./layout/LayoutHeader.js";
@@ -64,4 +66,4 @@ import { Toaster } from "./toast/ToastProvider.js";
64
66
  import "./toast/index.js";
65
67
  import { cn } from "@pixpilot/shadcn";
66
68
 
67
- export { AbsoluteFill, Alert, AvatarUpload, Button, CircleLoader, CloseButtonAbsolute, CloseButtonRounded, ColorPicker, ColorPickerBase, ColorSelect, Combobox, ContentCard, DEFAULT_ALERT_DURATION, DatePicker, DialogProvider, FileUpload, FileUploadInline, IconPicker, Input, Layout, LayoutFooter, LayoutHeader, LayoutMain, LoadingOverlay, Pagination, RichTextEditor, ScaledPreview, Select, Slider, SliderInput, SliderSelect, Tabs, TabsContent, TabsContext, TabsList, TabsTrigger, TagsInput, ThemeModeDropdown, ThemeModeSwitchInside, ThemeModeSwitchOutside, ThemeModeToggleButton, ThemeProvider, Toaster, cn, showConfirmDialog, toast, toastError, toastInfo, toastSuccess, toastWarning, useMediaQuery, useSelectKeyboard, useTabsContext, useTheme };
69
+ export { AbsoluteFill, Alert, AvatarUpload, Button, CircleLoader, CloseButtonAbsolute, CloseButtonRounded, ColorPicker, ColorPickerBase, ColorSelect, Combobox, ContentCard, DEFAULT_ALERT_DURATION, DatePicker, DialogProvider, FileUpload, FileUploadInline, IconPicker, IconToggle, Input, Layout, LayoutFooter, LayoutHeader, LayoutMain, LoadingOverlay, Pagination, RichTextEditor, ScaledPreview, Select, Slider, SliderInput, SliderSelect, Tabs, TabsContent, TabsContext, TabsList, TabsTrigger, TagsInput, ThemeModeDropdown, ThemeModeSwitchInside, ThemeModeSwitchOutside, ThemeModeToggleButton, ThemeProvider, Toaster, cn, isSvgMarkupString, showConfirmDialog, svgMarkupToMaskUrl, toast, toastError, toastInfo, toastSuccess, toastWarning, useMediaQuery, useSelectKeyboard, useTabsContext, useTheme };
@@ -6,6 +6,10 @@ let react = require("react");
6
6
  react = require_rolldown_runtime.__toESM(react);
7
7
  let react_jsx_runtime = require("react/jsx-runtime");
8
8
  react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
9
+ let __tiptap_extension_link = require("@tiptap/extension-link");
10
+ __tiptap_extension_link = require_rolldown_runtime.__toESM(__tiptap_extension_link);
11
+ let __tiptap_extension_text_align = require("@tiptap/extension-text-align");
12
+ __tiptap_extension_text_align = require_rolldown_runtime.__toESM(__tiptap_extension_text_align);
9
13
  let __tiptap_react = require("@tiptap/react");
10
14
  __tiptap_react = require_rolldown_runtime.__toESM(__tiptap_react);
11
15
  let __tiptap_starter_kit = require("@tiptap/starter-kit");
@@ -17,9 +21,14 @@ const defaultToolbarItems = [
17
21
  "bold",
18
22
  "italic",
19
23
  "underline",
24
+ "link",
20
25
  "strike",
21
26
  "code",
22
27
  "|",
28
+ "alignLeft",
29
+ "alignCenter",
30
+ "alignRight",
31
+ "|",
23
32
  "heading1",
24
33
  "heading2",
25
34
  "heading3",
@@ -31,7 +40,7 @@ const defaultToolbarItems = [
31
40
  "codeBlock"
32
41
  ];
33
42
  function useEditorProps(slots, customEditorProps) {
34
- const defaultEditorProps = react.default.useMemo(() => ({ attributes: { class: (0, __pixpilot_shadcn.cn)("min-h-[200px] p-4 text-sm leading-relaxed focus:outline-none", "[&_h1]:text-3xl [&_h1]:font-bold [&_h1]:leading-tight [&_h1]:mt-8 [&_h1]:mb-4 [&_h1:first-child]:mt-0", "[&_h2]:text-2xl [&_h2]:font-bold [&_h2]:leading-tight [&_h2]:mt-6 [&_h2]:mb-3 [&_h2:first-child]:mt-0", "[&_h3]:text-xl [&_h3]:font-bold [&_h3]:leading-tight [&_h3]:mt-4 [&_h3]:mb-2 [&_h3:first-child]:mt-0", "[&_p]:mb-3", "[&_ul]:list-disc [&_ul]:pl-6 [&_ul]:mb-3", "[&_ol]:list-decimal [&_ol]:pl-6 [&_ol]:mb-3", "[&_blockquote]:border-l-4 [&_blockquote]:border-border [&_blockquote]:pl-4 [&_blockquote]:mb-4 [&_blockquote]:italic [&_blockquote:first-child]:mt-0", "[&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-[0.875em] [&_code]:font-mono", "[&_pre]:bg-muted [&_pre]:p-4 [&_pre]:rounded [&_pre]:overflow-x-auto [&_pre]:font-mono [&_pre]:mb-4", "[&_*:last-child]:mb-0", slots?.content?.className) } }), [slots]);
43
+ const defaultEditorProps = react.default.useMemo(() => ({ attributes: { class: (0, __pixpilot_shadcn.cn)("min-h-[200px] p-4 text-sm leading-relaxed focus:outline-none", "[&_h1]:text-3xl [&_h1]:font-bold [&_h1]:leading-tight [&_h1]:mt-8 [&_h1]:mb-4 [&_h1:first-child]:mt-0", "[&_h2]:text-2xl [&_h2]:font-bold [&_h2]:leading-tight [&_h2]:mt-6 [&_h2]:mb-3 [&_h2:first-child]:mt-0", "[&_h3]:text-xl [&_h3]:font-bold [&_h3]:leading-tight [&_h3]:mt-4 [&_h3]:mb-2 [&_h3:first-child]:mt-0", "[&_p]:mb-3", "[&_ul]:list-disc [&_ul]:pl-6 [&_ul]:mb-3", "[&_ol]:list-decimal [&_ol]:pl-6 [&_ol]:mb-3", "[&_blockquote]:border-l-4 [&_blockquote]:border-border [&_blockquote]:pl-4 [&_blockquote]:mb-4 [&_blockquote]:italic [&_blockquote:first-child]:mt-0", "[&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-[0.875em] [&_code]:font-mono", "[&_pre]:bg-muted [&_pre]:p-4 [&_pre]:rounded [&_pre]:overflow-x-auto [&_pre]:font-mono [&_pre]:mb-4", "[&_a]:text-blue-500 [&_a]:hover:text-blue-600 [&_a]:cursor-pointer [&_a]:underline [&_a]:underline-offset-2 ", "[&_*:last-child]:mb-0", slots?.content?.className) } }), [slots]);
35
44
  return react.default.useMemo(() => ({
36
45
  ...defaultEditorProps,
37
46
  ...customEditorProps,
@@ -51,7 +60,11 @@ const RichTextEditor = ({ value, onChange, extensions = defaultExtensions, edita
51
60
  onChangeRef.current?.(props.editor.getHTML());
52
61
  }, []);
53
62
  const editorInstance = (0, __tiptap_react.useEditor)({
54
- extensions: [__tiptap_starter_kit.default].concat(extensions),
63
+ extensions: react.default.useMemo(() => [
64
+ __tiptap_starter_kit.default,
65
+ __tiptap_extension_link.default,
66
+ __tiptap_extension_text_align.default.configure({ types: ["heading", "paragraph"] })
67
+ ].concat(extensions), [extensions]),
55
68
  content: value,
56
69
  editable,
57
70
  onUpdate: handleChange,
@@ -2,6 +2,8 @@ import { RichTextEditorToolbar } from "./RichTextEditorToolbar.js";
2
2
  import { cn } from "@pixpilot/shadcn";
3
3
  import React from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
+ import Link from "@tiptap/extension-link";
6
+ import TextAlign from "@tiptap/extension-text-align";
5
7
  import { EditorContent, useEditor } from "@tiptap/react";
6
8
  import StarterKit from "@tiptap/starter-kit";
7
9
 
@@ -11,9 +13,14 @@ const defaultToolbarItems = [
11
13
  "bold",
12
14
  "italic",
13
15
  "underline",
16
+ "link",
14
17
  "strike",
15
18
  "code",
16
19
  "|",
20
+ "alignLeft",
21
+ "alignCenter",
22
+ "alignRight",
23
+ "|",
17
24
  "heading1",
18
25
  "heading2",
19
26
  "heading3",
@@ -25,7 +32,7 @@ const defaultToolbarItems = [
25
32
  "codeBlock"
26
33
  ];
27
34
  function useEditorProps(slots, customEditorProps) {
28
- const defaultEditorProps = React.useMemo(() => ({ attributes: { class: cn("min-h-[200px] p-4 text-sm leading-relaxed focus:outline-none", "[&_h1]:text-3xl [&_h1]:font-bold [&_h1]:leading-tight [&_h1]:mt-8 [&_h1]:mb-4 [&_h1:first-child]:mt-0", "[&_h2]:text-2xl [&_h2]:font-bold [&_h2]:leading-tight [&_h2]:mt-6 [&_h2]:mb-3 [&_h2:first-child]:mt-0", "[&_h3]:text-xl [&_h3]:font-bold [&_h3]:leading-tight [&_h3]:mt-4 [&_h3]:mb-2 [&_h3:first-child]:mt-0", "[&_p]:mb-3", "[&_ul]:list-disc [&_ul]:pl-6 [&_ul]:mb-3", "[&_ol]:list-decimal [&_ol]:pl-6 [&_ol]:mb-3", "[&_blockquote]:border-l-4 [&_blockquote]:border-border [&_blockquote]:pl-4 [&_blockquote]:mb-4 [&_blockquote]:italic [&_blockquote:first-child]:mt-0", "[&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-[0.875em] [&_code]:font-mono", "[&_pre]:bg-muted [&_pre]:p-4 [&_pre]:rounded [&_pre]:overflow-x-auto [&_pre]:font-mono [&_pre]:mb-4", "[&_*:last-child]:mb-0", slots?.content?.className) } }), [slots]);
35
+ const defaultEditorProps = React.useMemo(() => ({ attributes: { class: cn("min-h-[200px] p-4 text-sm leading-relaxed focus:outline-none", "[&_h1]:text-3xl [&_h1]:font-bold [&_h1]:leading-tight [&_h1]:mt-8 [&_h1]:mb-4 [&_h1:first-child]:mt-0", "[&_h2]:text-2xl [&_h2]:font-bold [&_h2]:leading-tight [&_h2]:mt-6 [&_h2]:mb-3 [&_h2:first-child]:mt-0", "[&_h3]:text-xl [&_h3]:font-bold [&_h3]:leading-tight [&_h3]:mt-4 [&_h3]:mb-2 [&_h3:first-child]:mt-0", "[&_p]:mb-3", "[&_ul]:list-disc [&_ul]:pl-6 [&_ul]:mb-3", "[&_ol]:list-decimal [&_ol]:pl-6 [&_ol]:mb-3", "[&_blockquote]:border-l-4 [&_blockquote]:border-border [&_blockquote]:pl-4 [&_blockquote]:mb-4 [&_blockquote]:italic [&_blockquote:first-child]:mt-0", "[&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-[0.875em] [&_code]:font-mono", "[&_pre]:bg-muted [&_pre]:p-4 [&_pre]:rounded [&_pre]:overflow-x-auto [&_pre]:font-mono [&_pre]:mb-4", "[&_a]:text-blue-500 [&_a]:hover:text-blue-600 [&_a]:cursor-pointer [&_a]:underline [&_a]:underline-offset-2 ", "[&_*:last-child]:mb-0", slots?.content?.className) } }), [slots]);
29
36
  return React.useMemo(() => ({
30
37
  ...defaultEditorProps,
31
38
  ...customEditorProps,
@@ -45,7 +52,11 @@ const RichTextEditor = ({ value, onChange, extensions = defaultExtensions, edita
45
52
  onChangeRef.current?.(props.editor.getHTML());
46
53
  }, []);
47
54
  const editorInstance = useEditor({
48
- extensions: [StarterKit].concat(extensions),
55
+ extensions: React.useMemo(() => [
56
+ StarterKit,
57
+ Link,
58
+ TextAlign.configure({ types: ["heading", "paragraph"] })
59
+ ].concat(extensions), [extensions]),
49
60
  content: value,
50
61
  editable,
51
62
  onUpdate: handleChange,
@@ -1,4 +1,5 @@
1
1
  const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_svg = require('../utils/svg.cjs');
2
3
  let __pixpilot_shadcn = require("@pixpilot/shadcn");
3
4
  __pixpilot_shadcn = require_rolldown_runtime.__toESM(__pixpilot_shadcn);
4
5
  let react = require("react");
@@ -7,14 +8,6 @@ let react_jsx_runtime = require("react/jsx-runtime");
7
8
  react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
8
9
 
9
10
  //#region src/rich-text-editor/ToolbarButton.tsx
10
- function isSvgMarkupString(value) {
11
- if (typeof value !== "string") return false;
12
- const trimmed = value.trim();
13
- return trimmed.startsWith("<svg") && trimmed.endsWith("</svg>");
14
- }
15
- function svgMarkupToMaskUrl(svgMarkup) {
16
- return `url("data:image/svg+xml,${encodeURIComponent(svgMarkup).replace(/'/gu, "%27").replace(/"/gu, "%22")}")`;
17
- }
18
11
  const ToolbarButton = ({ onClick, isActive, disabled, className, children, tooltip }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.TooltipTrigger, {
19
12
  asChild: true,
20
13
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
@@ -27,14 +20,14 @@ const ToolbarButton = ({ onClick, isActive, disabled, className, children, toolt
27
20
  onClick,
28
21
  disabled,
29
22
  className: (0, __pixpilot_shadcn.cn)("h-8 w-8 p-0", className),
30
- children: isSvgMarkupString(children) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
23
+ children: require_svg.isSvgMarkupString(children) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
31
24
  "data-slot": "svg-mask",
32
25
  "aria-hidden": "true",
33
26
  className: "inline-block h-4 w-4",
34
27
  style: {
35
28
  backgroundColor: "currentColor",
36
- WebkitMaskImage: svgMarkupToMaskUrl(children),
37
- maskImage: svgMarkupToMaskUrl(children),
29
+ WebkitMaskImage: require_svg.svgMarkupToMaskUrl(children),
30
+ maskImage: require_svg.svgMarkupToMaskUrl(children),
38
31
  WebkitMaskRepeat: "no-repeat",
39
32
  maskRepeat: "no-repeat",
40
33
  WebkitMaskPosition: "center",
@@ -1,16 +1,9 @@
1
+ import { isSvgMarkupString, svgMarkupToMaskUrl } from "../utils/svg.js";
1
2
  import { Button, Tooltip, TooltipContent, TooltipTrigger, cn } from "@pixpilot/shadcn";
2
3
  import React from "react";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
 
5
6
  //#region src/rich-text-editor/ToolbarButton.tsx
6
- function isSvgMarkupString(value) {
7
- if (typeof value !== "string") return false;
8
- const trimmed = value.trim();
9
- return trimmed.startsWith("<svg") && trimmed.endsWith("</svg>");
10
- }
11
- function svgMarkupToMaskUrl(svgMarkup) {
12
- return `url("data:image/svg+xml,${encodeURIComponent(svgMarkup).replace(/'/gu, "%27").replace(/"/gu, "%22")}")`;
13
- }
14
7
  const ToolbarButton = ({ onClick, isActive, disabled, className, children, tooltip }) => /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
15
8
  asChild: true,
16
9
  children: /* @__PURE__ */ jsx(Button, {
@@ -24,6 +24,12 @@ const predefinedToolbarItems = {
24
24
  onClick: (editor) => editor.chain().focus().toggleUnderline().run(),
25
25
  isActive: (editor) => editor.isActive("underline")
26
26
  },
27
+ link: {
28
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Link, { className: "h-4 w-4" }),
29
+ tooltip: "Link",
30
+ onClick: (editor) => editor.chain().focus().toggleLink().run(),
31
+ isActive: (editor) => editor.isActive("link")
32
+ },
27
33
  strike: {
28
34
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Strikethrough, { className: "h-4 w-4" }),
29
35
  tooltip: "Strikethrough",
@@ -77,6 +83,24 @@ const predefinedToolbarItems = {
77
83
  tooltip: "Code Block",
78
84
  onClick: (editor) => editor.chain().focus().toggleCodeBlock().run(),
79
85
  isActive: (editor) => editor.isActive("codeBlock")
86
+ },
87
+ alignLeft: {
88
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.AlignLeft, { className: "h-4 w-4" }),
89
+ tooltip: "Align Left",
90
+ onClick: (editor) => editor.chain().focus().setTextAlign("left").run(),
91
+ isActive: (editor) => editor.isActive({ textAlign: "left" })
92
+ },
93
+ alignCenter: {
94
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.AlignCenter, { className: "h-4 w-4" }),
95
+ tooltip: "Align Center",
96
+ onClick: (editor) => editor.chain().focus().setTextAlign("center").run(),
97
+ isActive: (editor) => editor.isActive({ textAlign: "center" })
98
+ },
99
+ alignRight: {
100
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.AlignRight, { className: "h-4 w-4" }),
101
+ tooltip: "Align Right",
102
+ onClick: (editor) => editor.chain().focus().setTextAlign("right").run(),
103
+ isActive: (editor) => editor.isActive({ textAlign: "right" })
80
104
  }
81
105
  };
82
106
 
@@ -1,4 +1,4 @@
1
- import { Bold, Code, Code2, Heading1, Heading2, Heading3, Italic, List, ListOrdered, Quote, Strikethrough, Underline } from "lucide-react";
1
+ import { AlignCenter, AlignLeft, AlignRight, Bold, Code, Code2, Heading1, Heading2, Heading3, Italic, Link, List, ListOrdered, Quote, Strikethrough, Underline } from "lucide-react";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
 
4
4
  //#region src/rich-text-editor/predefined-toolbar-items.tsx
@@ -21,6 +21,12 @@ const predefinedToolbarItems = {
21
21
  onClick: (editor) => editor.chain().focus().toggleUnderline().run(),
22
22
  isActive: (editor) => editor.isActive("underline")
23
23
  },
24
+ link: {
25
+ icon: /* @__PURE__ */ jsx(Link, { className: "h-4 w-4" }),
26
+ tooltip: "Link",
27
+ onClick: (editor) => editor.chain().focus().toggleLink().run(),
28
+ isActive: (editor) => editor.isActive("link")
29
+ },
24
30
  strike: {
25
31
  icon: /* @__PURE__ */ jsx(Strikethrough, { className: "h-4 w-4" }),
26
32
  tooltip: "Strikethrough",
@@ -74,6 +80,24 @@ const predefinedToolbarItems = {
74
80
  tooltip: "Code Block",
75
81
  onClick: (editor) => editor.chain().focus().toggleCodeBlock().run(),
76
82
  isActive: (editor) => editor.isActive("codeBlock")
83
+ },
84
+ alignLeft: {
85
+ icon: /* @__PURE__ */ jsx(AlignLeft, { className: "h-4 w-4" }),
86
+ tooltip: "Align Left",
87
+ onClick: (editor) => editor.chain().focus().setTextAlign("left").run(),
88
+ isActive: (editor) => editor.isActive({ textAlign: "left" })
89
+ },
90
+ alignCenter: {
91
+ icon: /* @__PURE__ */ jsx(AlignCenter, { className: "h-4 w-4" }),
92
+ tooltip: "Align Center",
93
+ onClick: (editor) => editor.chain().focus().setTextAlign("center").run(),
94
+ isActive: (editor) => editor.isActive({ textAlign: "center" })
95
+ },
96
+ alignRight: {
97
+ icon: /* @__PURE__ */ jsx(AlignRight, { className: "h-4 w-4" }),
98
+ tooltip: "Align Right",
99
+ onClick: (editor) => editor.chain().focus().setTextAlign("right").run(),
100
+ isActive: (editor) => editor.isActive({ textAlign: "right" })
77
101
  }
78
102
  };
79
103
 
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime9 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime10 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/theme-toggle/ThemeModeDropdown.d.ts
4
4
  interface ThemeModeDropdownProps {
@@ -17,7 +17,7 @@ interface ThemeModeDropdownProps {
17
17
  * Provides Light / Dark / System options.
18
18
  * Pure component - requires themeValue and onChange props.
19
19
  */
20
- declare function ThemeModeDropdown(props: ThemeModeDropdownProps): react_jsx_runtime9.JSX.Element;
20
+ declare function ThemeModeDropdown(props: ThemeModeDropdownProps): react_jsx_runtime10.JSX.Element;
21
21
  declare namespace ThemeModeDropdown {
22
22
  var displayName: string;
23
23
  }
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime10 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime11 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/theme-toggle/ThemeModeSwitchInside.d.ts
4
4
  type ThemeModeSwitchInsideSize = 'sm' | 'md' | 'lg';
@@ -25,7 +25,7 @@ interface ThemeModeSwitchInsideProps {
25
25
  * Icons are embedded within the switch control.
26
26
  * Pure component - requires value and onChange props.
27
27
  */
28
- declare function ThemeModeSwitchInside(props: ThemeModeSwitchInsideProps): react_jsx_runtime10.JSX.Element;
28
+ declare function ThemeModeSwitchInside(props: ThemeModeSwitchInsideProps): react_jsx_runtime11.JSX.Element;
29
29
  declare namespace ThemeModeSwitchInside {
30
30
  var displayName: string;
31
31
  }
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime11 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime12 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/theme-toggle/ThemeModeSwitchOutside.d.ts
4
4
  interface ThemeModeSwitchOutsideProps {
@@ -22,7 +22,7 @@ interface ThemeModeSwitchOutsideProps {
22
22
  * Icons flank the switch control on either side.
23
23
  * Pure component - requires value and onChange props.
24
24
  */
25
- declare function ThemeModeSwitchOutside(props: ThemeModeSwitchOutsideProps): react_jsx_runtime11.JSX.Element;
25
+ declare function ThemeModeSwitchOutside(props: ThemeModeSwitchOutsideProps): react_jsx_runtime12.JSX.Element;
26
26
  declare namespace ThemeModeSwitchOutside {
27
27
  var displayName: string;
28
28
  }
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime12 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime9 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/theme-toggle/ThemeModeToggleButton.d.ts
4
4
  interface ThemeModeToggleButtonProps {
@@ -13,7 +13,7 @@ interface ThemeModeToggleButtonProps {
13
13
  * Light/Dark toggle button.
14
14
  * Pure component - toggles between light and dark.
15
15
  */
16
- declare function ThemeModeToggleButton(props: ThemeModeToggleButtonProps): react_jsx_runtime12.JSX.Element;
16
+ declare function ThemeModeToggleButton(props: ThemeModeToggleButtonProps): react_jsx_runtime9.JSX.Element;
17
17
  declare namespace ThemeModeToggleButton {
18
18
  var displayName: string;
19
19
  }
@@ -0,0 +1,25 @@
1
+
2
+ //#region src/utils/svg.ts
3
+ /**
4
+ * Checks if a value is an SVG markup string
5
+ * @param value - The value to check
6
+ * @returns True if the value is a string starting with '<svg' and ending with '</svg>'
7
+ */
8
+ function isSvgMarkupString(value) {
9
+ if (typeof value !== "string") return false;
10
+ const trimmed = value.trim();
11
+ return trimmed.startsWith("<svg") && trimmed.endsWith("</svg>");
12
+ }
13
+ /**
14
+ * Converts SVG markup string to a CSS mask-image data URL
15
+ * Useful for rendering SVG strings as masked icons that inherit currentColor
16
+ * @param svgMarkup - The SVG markup string
17
+ * @returns A CSS url() value for use in mask-image properties
18
+ */
19
+ function svgMarkupToMaskUrl(svgMarkup) {
20
+ return `url("data:image/svg+xml,${encodeURIComponent(svgMarkup).replace(/'/gu, "%27").replace(/"/gu, "%22")}")`;
21
+ }
22
+
23
+ //#endregion
24
+ exports.isSvgMarkupString = isSvgMarkupString;
25
+ exports.svgMarkupToMaskUrl = svgMarkupToMaskUrl;
@@ -0,0 +1,16 @@
1
+ //#region src/utils/svg.d.ts
2
+ /**
3
+ * Checks if a value is an SVG markup string
4
+ * @param value - The value to check
5
+ * @returns True if the value is a string starting with '<svg' and ending with '</svg>'
6
+ */
7
+ declare function isSvgMarkupString(value: unknown): value is string;
8
+ /**
9
+ * Converts SVG markup string to a CSS mask-image data URL
10
+ * Useful for rendering SVG strings as masked icons that inherit currentColor
11
+ * @param svgMarkup - The SVG markup string
12
+ * @returns A CSS url() value for use in mask-image properties
13
+ */
14
+ declare function svgMarkupToMaskUrl(svgMarkup: string): string;
15
+ //#endregion
16
+ export { isSvgMarkupString, svgMarkupToMaskUrl };
@@ -0,0 +1,16 @@
1
+ //#region src/utils/svg.d.ts
2
+ /**
3
+ * Checks if a value is an SVG markup string
4
+ * @param value - The value to check
5
+ * @returns True if the value is a string starting with '<svg' and ending with '</svg>'
6
+ */
7
+ declare function isSvgMarkupString(value: unknown): value is string;
8
+ /**
9
+ * Converts SVG markup string to a CSS mask-image data URL
10
+ * Useful for rendering SVG strings as masked icons that inherit currentColor
11
+ * @param svgMarkup - The SVG markup string
12
+ * @returns A CSS url() value for use in mask-image properties
13
+ */
14
+ declare function svgMarkupToMaskUrl(svgMarkup: string): string;
15
+ //#endregion
16
+ export { isSvgMarkupString, svgMarkupToMaskUrl };
@@ -0,0 +1,23 @@
1
+ //#region src/utils/svg.ts
2
+ /**
3
+ * Checks if a value is an SVG markup string
4
+ * @param value - The value to check
5
+ * @returns True if the value is a string starting with '<svg' and ending with '</svg>'
6
+ */
7
+ function isSvgMarkupString(value) {
8
+ if (typeof value !== "string") return false;
9
+ const trimmed = value.trim();
10
+ return trimmed.startsWith("<svg") && trimmed.endsWith("</svg>");
11
+ }
12
+ /**
13
+ * Converts SVG markup string to a CSS mask-image data URL
14
+ * Useful for rendering SVG strings as masked icons that inherit currentColor
15
+ * @param svgMarkup - The SVG markup string
16
+ * @returns A CSS url() value for use in mask-image properties
17
+ */
18
+ function svgMarkupToMaskUrl(svgMarkup) {
19
+ return `url("data:image/svg+xml,${encodeURIComponent(svgMarkup).replace(/'/gu, "%27").replace(/"/gu, "%22")}")`;
20
+ }
21
+
22
+ //#endregion
23
+ export { isSvgMarkupString, svgMarkupToMaskUrl };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pixpilot/shadcn-ui",
3
3
  "type": "module",
4
- "version": "0.35.0",
4
+ "version": "0.37.0",
5
5
  "description": "Custom UI components and utilities built with shadcn/ui.",
6
6
  "author": "m.doaie <m.doaie@hotmail.com>",
7
7
  "license": "MIT",
@@ -34,10 +34,12 @@
34
34
  "@iconify/react": "^6.0.2",
35
35
  "@pixpilot/hash": "^0.0.0",
36
36
  "@tailwindcss/typography": "^0.5.19",
37
- "@tanstack/react-virtual": "^3.13.13",
38
- "@tiptap/core": "^3.13.0",
39
- "@tiptap/react": "^3.13.0",
40
- "@tiptap/starter-kit": "^3.13.0",
37
+ "@tanstack/react-virtual": "^3.13.18",
38
+ "@tiptap/core": "^3.16.0",
39
+ "@tiptap/extension-link": "^3.16.0",
40
+ "@tiptap/extension-text-align": "^3.16.0",
41
+ "@tiptap/react": "^3.16.0",
42
+ "@tiptap/starter-kit": "^3.16.0",
41
43
  "class-variance-authority": "^0.7.1",
42
44
  "lucide-react": "0.553.0",
43
45
  "next-themes": "0.4.6",
@@ -57,9 +59,9 @@
57
59
  "react-dom": "19.2.0",
58
60
  "tsdown": "^0.15.12",
59
61
  "typescript": "^5.9.3",
62
+ "@internal/eslint-config": "0.3.0",
60
63
  "@internal/hooks": "0.0.0",
61
64
  "@internal/prettier-config": "0.0.1",
62
- "@internal/eslint-config": "0.3.0",
63
65
  "@internal/tsconfig": "0.1.0",
64
66
  "@internal/tsdown-config": "0.1.0",
65
67
  "@internal/vitest-config": "0.1.0"