@ckc-net/puck-extended 0.2.1 → 0.3.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.
package/dist/index.js CHANGED
@@ -1,36 +1,87 @@
1
- import React, { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
1
+ import React, { Children, cloneElement, isValidElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { mergeProps } from "@base-ui/react/merge-props";
3
+ import { useRender } from "@base-ui/react/use-render";
4
+ import { cva } from "class-variance-authority";
2
5
  import { clsx } from "clsx";
3
6
  import { twMerge } from "tailwind-merge";
4
- import { AlignCenterIcon, AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, BoldIcon, BoxIcon, CaseLowerIcon, CaseSensitiveIcon, CaseUpperIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleAlertIcon, CircleCheckIcon, FileIcon, FileTextIcon, GripVerticalIcon, InfoIcon, ItalicIcon, LightbulbIcon, Link, Link2Off, Loader2Icon, LoaderCircleIcon, LockIcon, MinusIcon, MoreHorizontalIcon, SearchIcon, StrikethroughIcon, TriangleAlertIcon, UnderlineIcon, UploadIcon, X, XIcon } from "lucide-react";
7
+ import { AlignCenterIcon, AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, BaselineIcon, BoldIcon, BoxIcon, CaseLowerIcon, CaseSensitiveIcon, CaseUpperIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsUpDownIcon, CircleAlertIcon, CircleCheckIcon, DatabaseIcon, FileIcon, FileTextIcon, GripVerticalIcon, InfoIcon, ItalicIcon, LightbulbIcon, LinkIcon, Loader2Icon, LoaderCircleIcon, LockIcon, MinusIcon, MoreHorizontalIcon, PlusIcon, SearchIcon, StrikethroughIcon, Trash2Icon, TriangleAlertIcon, UnderlineIcon, UploadIcon, XIcon } from "lucide-react";
5
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ import { Tooltip as Tooltip$1 } from "@base-ui/react/tooltip";
6
10
  import { Checkbox as Checkbox$1 } from "@base-ui/react/checkbox";
7
11
  import { Input as Input$1 } from "@base-ui/react/input";
8
12
  import { Select as Select$1 } from "@base-ui/react/select";
9
13
  import { Radio } from "@base-ui/react/radio";
10
14
  import { RadioGroup as RadioGroup$1 } from "@base-ui/react/radio-group";
11
15
  import { Field } from "@base-ui/react/field";
12
- import { mergeProps } from "@base-ui/react/merge-props";
13
- import { createUsePuck } from "@puckeditor/core";
16
+ import { AutoField, createUsePuck, walkTree } from "@puckeditor/core";
14
17
  import { Tabs as Tabs$1 } from "@base-ui/react/tabs";
15
- import { Accordion as Accordion$1 } from "@base-ui/react/accordion";
16
- import { Tooltip as Tooltip$1 } from "@base-ui/react/tooltip";
17
- import TiptapLink from "@tiptap/extension-link";
18
- import { useRender } from "@base-ui/react/use-render";
19
- import { cva } from "class-variance-authority";
18
+ import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
20
19
  import { Popover as Popover$1 } from "@base-ui/react/popover";
21
20
  import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
22
- import { ScrollArea } from "@base-ui/react/scroll-area";
21
+ import { ScrollArea as ScrollArea$1 } from "@base-ui/react/scroll-area";
22
+ import { flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table";
23
+ import { Color } from "@tiptap/extension-color";
24
+ import { TextStyle } from "@tiptap/extension-text-style";
25
+ import { HexColorPicker } from "react-colorful";
23
26
  import { Menu as Menu$1 } from "@base-ui/react/menu";
24
27
  import { Separator as Separator$1 } from "@base-ui/react/separator";
25
28
  import { Switch as Switch$1 } from "@base-ui/react/switch";
26
29
  import { Toast } from "@base-ui/react/toast";
27
- import { HexColorPicker } from "react-colorful";
28
30
 
29
31
  //#region src/lib/utils.ts
30
32
  function cn(...inputs) {
31
33
  return twMerge(clsx(inputs));
32
34
  }
33
35
 
36
+ //#endregion
37
+ //#region src/components/ui/button.tsx
38
+ const buttonVariants = cva("[&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 sm:text-sm [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", {
39
+ defaultVariants: {
40
+ size: "default",
41
+ variant: "default"
42
+ },
43
+ variants: {
44
+ size: {
45
+ default: "h-9 px-[calc(--spacing(3)-1px)] sm:h-8",
46
+ icon: "size-9 sm:size-8",
47
+ "icon-lg": "size-10 sm:size-9",
48
+ "icon-sm": "size-8 sm:size-7",
49
+ "icon-xl": "size-11 sm:size-10 [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5",
50
+ "icon-xs": "size-7 rounded-md before:rounded-[calc(var(--radius-md)-1px)] sm:size-6 not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-4 sm:not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-3.5",
51
+ lg: "h-10 px-[calc(--spacing(3.5)-1px)] sm:h-9",
52
+ sm: "h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:h-7",
53
+ xl: "h-11 px-[calc(--spacing(4)-1px)] text-lg sm:h-10 sm:text-base [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5",
54
+ xs: "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-sm before:rounded-[calc(var(--radius-md)-1px)] sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5"
55
+ },
56
+ variant: {
57
+ default: "not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-primary bg-primary text-primary-foreground shadow-primary/24 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-primary/90",
58
+ destructive: "not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-destructive bg-destructive text-white shadow-destructive/24 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-destructive/90",
59
+ "destructive-outline": "border-input bg-transparent not-dark:bg-clip-padding text-destructive-foreground not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:border-destructive/32 [:hover,[data-pressed]]:bg-destructive/4",
60
+ ghost: "border-transparent data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent",
61
+ link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",
62
+ outline: "border-input bg-background not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-accent/50 dark:[:hover,[data-pressed]]:bg-input/64",
63
+ primary: "border-transparent from-primary-600 to-primary-500 hover:from-primary-500 hover:to-primary-600 bg-linear-to-t text-white inset-shadow-[0_2px_0_0] inset-shadow-white/25 hover:text-white",
64
+ secondary: "border-transparent bg-secondary text-secondary-foreground [:active,[data-pressed]]:bg-secondary/80 [:hover,[data-pressed]]:bg-secondary/90"
65
+ }
66
+ }
67
+ });
68
+ function Button({ className, variant, size, render, ...props }) {
69
+ const typeValue = render ? void 0 : "button";
70
+ return useRender({
71
+ defaultTagName: "button",
72
+ props: mergeProps({
73
+ className: cn(buttonVariants({
74
+ className,
75
+ size,
76
+ variant
77
+ })),
78
+ "data-slot": "button",
79
+ type: typeValue
80
+ }, props),
81
+ render
82
+ });
83
+ }
84
+
34
85
  //#endregion
35
86
  //#region src/components/ui/label.tsx
36
87
  function Label$2({ className, readOnly, children, ...props }) {
@@ -43,11 +94,194 @@ function Label$2({ className, readOnly, children, ...props }) {
43
94
  });
44
95
  }
45
96
 
97
+ //#endregion
98
+ //#region src/components/ui/tooltip.tsx
99
+ const cssAnimationPresets = {
100
+ none: "transition-none",
101
+ scale: [`[transition-property:scale,opacity]`, `data-starting-style:scale-80 data-starting-style:opacity-0 data-ending-style:opacity-0 data-ending-style:scale-80`],
102
+ fade: [`[transition-property:opacity,scale]`, `data-starting-style:scale-98 data-starting-style:opacity-0 data-ending-style:opacity-0 data-ending-style:scale-98`],
103
+ slideOutside: [
104
+ `[transition-property:translate,opacity]`,
105
+ `data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:translate-y-[10px] data-[side=bottom]:data-ending-style:translate-y-[10px] data-[side=bottom]:data-ending-style:opacity-0`,
106
+ `data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:translate-y-[-10px] data-[side=top]:data-ending-style:translate-y-[-10px] data-[side=top]:data-ending-style:opacity-0`,
107
+ `data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:translate-x-[-10px] data-[side=left]:data-ending-style:translate-x-[-10px] data-[side=left]:data-ending-style:opacity-0`,
108
+ `data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:translate-x-[10px] data-[side=right]:data-ending-style:translate-x-[10px] data-[side=right]:data-ending-style:opacity-0`,
109
+ `data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:translate-x-[-10px] data-[side=inline-start]:data-ending-style:translate-x-[-10px] data-[side=inline-start]:data-ending-style:opacity-0`,
110
+ `data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:translate-x-[10px] data-[side=inline-end]:data-ending-style:translate-x-[10px] data-[side=inline-end]:data-ending-style:opacity-0`
111
+ ],
112
+ slideInside: [
113
+ `[transition-property:translate,opacity]`,
114
+ `data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:translate-y-[-10px] data-[side=bottom]:data-ending-style:translate-y-[-10px] data-[side=bottom]:data-ending-style:opacity-0`,
115
+ `data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:translate-y-[10px] data-[side=top]:data-ending-style:translate-y-[10px] data-[side=top]:data-ending-style:opacity-0`,
116
+ `data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:translate-x-[10px] data-[side=left]:data-ending-style:translate-x-[10px] data-[side=left]:data-ending-style:opacity-0`,
117
+ `data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:translate-x-[-10px] data-[side=right]:data-ending-style:translate-x-[-10px] data-[side=right]:data-ending-style:opacity-0`,
118
+ `data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:translate-x-[10px] data-[side=inline-start]:data-ending-style:translate-x-[10px] data-[side=inline-start]:data-ending-style:opacity-0`,
119
+ `data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:translate-x-[-10px] data-[side=inline-end]:data-ending-style:translate-x-[-10px] data-[side=inline-end]:data-ending-style:opacity-0`
120
+ ],
121
+ wipe: [
122
+ `[transition-property:clip-path] [will-change:clip-path]`,
123
+ `[clip-path:inset(0_0_0_0_round_var(--radius))] [-webkit-clip-path:inset(0_0_0_0_round_var(--radius))]`,
124
+ `data-[side=bottom]:data-starting-style:[clip-path:inset(0_0_100%_0_round_var(--radius))] data-[side=bottom]:data-ending-style:[clip-path:inset(0_0_100%_0_round_var(--radius))]`,
125
+ `data-[side=top]:data-starting-style:[clip-path:inset(100%_0_0_0_round_var(--radius))] data-[side=top]:data-ending-style:[clip-path:inset(100%_0_0_0_round_var(--radius))]`,
126
+ `data-[side=left]:data-starting-style:[clip-path:inset(0_0_0_100%_round_var(--radius))] data-[side=left]:data-ending-style:[clip-path:inset(0_0_0_100%_round_var(--radius))]`,
127
+ `data-[side=right]:data-starting-style:[clip-path:inset(0_100%_0_0_round_var(--radius))] data-[side=right]:data-ending-style:[clip-path:inset(0_100%_0_0_round_var(--radius))]`,
128
+ `data-[side=inline-start]:data-starting-style:[clip-path:inset(0_0_0_100%_round_var(--radius))] data-[side=inline-start]:data-ending-style:[clip-path:inset(0_0_0_100%_round_var(--radius))]`,
129
+ `data-[side=inline-end]:data-starting-style:[clip-path:inset(0_100%_0_0_round_var(--radius))] data-[side=inline-end]:data-ending-style:[clip-path:inset(0_100%_0_0_round_var(--radius))]`
130
+ ],
131
+ wipeScale: [
132
+ `[transition-property:clip-path,scale] [will-change:clip-path,scale]`,
133
+ `[clip-path:inset(0_0_0_0_round_var(--radius))] [-webkit-clip-path:inset(0_0_0_0_round_var(--radius))]`,
134
+ `data-starting-style:scale-80 data-ending-style:scale-80`,
135
+ `data-[side=bottom]:data-starting-style:[clip-path:inset(0_0_100%_0_round_var(--radius))] data-[side=bottom]:data-ending-style:[clip-path:inset(0_0_100%_0_round_var(--radius))]`,
136
+ `data-[side=top]:data-starting-style:[clip-path:inset(100%_0_0_0_round_var(--radius))] data-[side=top]:data-ending-style:[clip-path:inset(100%_0_0_0_round_var(--radius))]`,
137
+ `data-[side=left]:data-starting-style:[clip-path:inset(0_0_0_100%_round_var(--radius))] data-[side=left]:data-ending-style:[clip-path:inset(0_0_0_100%_round_var(--radius))]`,
138
+ `data-[side=right]:data-starting-style:[clip-path:inset(0_100%_0_0_round_var(--radius))] data-[side=right]:data-ending-style:[clip-path:inset(0_100%_0_0_round_var(--radius))]`,
139
+ `data-[side=inline-start]:data-starting-style:[clip-path:inset(0_0_0_100%_round_var(--radius))] data-[side=inline-start]:data-ending-style:[clip-path:inset(0_0_0_100%_round_var(--radius))]`,
140
+ `data-[side=inline-end]:data-starting-style:[clip-path:inset(0_100%_0_0_round_var(--radius))] data-[side=inline-end]:data-ending-style:[clip-path:inset(0_100%_0_0_round_var(--radius))]`
141
+ ],
142
+ motion: [
143
+ `[transition-property:translate,scale,opacity,rotateX,rotateY,transform] [will-change:translate,scale,opacity,rotateX,rotateY,transform]`,
144
+ `[transform:perspective(1000px)]`,
145
+ `data-[side=bottom]:data-starting-style:translate-y-[7px] data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:scale-[0.26] data-[side=bottom]:data-starting-style:rotate-x-[70deg] data-[side=bottom]:data-ending-style:translate-y-[7px] data-[side=bottom]:data-ending-style:opacity-0 data-[side=bottom]:data-ending-style:scale-[0.26] data-[side=bottom]:data-ending-style:rotate-x-[70deg]`,
146
+ `data-[side=top]:data-starting-style:translate-y-[7px] data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:scale-[0.26] data-[side=top]:data-starting-style:rotate-x-[70deg] data-[side=top]:data-ending-style:translate-y-[7px] data-[side=top]:data-ending-style:opacity-0 data-[side=top]:data-ending-style:scale-[0.26] data-[side=top]:data-ending-style:rotate-x-[70deg]`,
147
+ `data-[side=left]:data-starting-style:translate-x-[-7px] data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:scale-[0.26] data-[side=left]:data-starting-style:rotate-y-[-40deg] data-[side=left]:data-ending-style:translate-x-[-7px] data-[side=left]:data-ending-style:opacity-0 data-[side=left]:data-ending-style:scale-[0.26] data-[side=left]:data-ending-style:rotate-y-[-40deg]`,
148
+ `data-[side=right]:data-starting-style:translate-x-[7px] data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:scale-[0.26] data-[side=right]:data-starting-style:rotate-y-[40deg] data-[side=right]:data-ending-style:translate-x-[7px] data-[side=right]:data-ending-style:opacity-0 data-[side=right]:data-ending-style:scale-[0.26] data-[side=right]:data-ending-style:rotate-y-[40deg]`,
149
+ `data-[side=inline-start]:data-starting-style:translate-x-[-7px] data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:scale-[0.26] data-[side=inline-start]:data-starting-style:rotate-y-[-40deg] data-[side=inline-start]:data-ending-style:translate-x-[-7px] data-[side=inline-start]:data-ending-style:opacity-0 data-[side=inline-start]:data-ending-style:scale-[0.26] data-[side=inline-start]:data-ending-style:rotate-y-[-40deg]`,
150
+ `data-[side=inline-end]:data-starting-style:translate-x-[7px] data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:scale-[0.26] data-[side=inline-end]:data-starting-style:rotate-y-[40deg] data-[side=inline-end]:data-ending-style:translate-x-[7px] data-[side=inline-end]:data-ending-style:opacity-0 data-[side=inline-end]:data-ending-style:scale-[0.26] data-[side=inline-end]:data-ending-style:rotate-y-[40deg]`
151
+ ],
152
+ motionBlur: [
153
+ `[transition-property:translate,scale,opacity,rotateX,rotateY,transform,filter] [will-change:translate,scale,opacity,rotateX,rotateY,transform,filter]`,
154
+ `[transform:perspective(1000px)]`,
155
+ `data-starting-style:blur-[9px] data-ending-style:blur-[9px]`,
156
+ `data-[side=bottom]:data-starting-style:translate-y-[7px] data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:scale-[0.26] data-[side=bottom]:data-starting-style:rotate-x-[70deg] data-[side=bottom]:data-ending-style:translate-y-[7px] data-[side=bottom]:data-ending-style:opacity-0 data-[side=bottom]:data-ending-style:scale-[0.26] data-[side=bottom]:data-ending-style:rotate-x-[70deg]`,
157
+ `data-[side=top]:data-starting-style:translate-y-[7px] data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:scale-[0.26] data-[side=top]:data-starting-style:rotate-x-[70deg] data-[side=top]:data-ending-style:translate-y-[7px] data-[side=top]:data-ending-style:opacity-0 data-[side=top]:data-ending-style:scale-[0.26] data-[side=top]:data-ending-style:rotate-x-[70deg]`,
158
+ `data-[side=left]:data-starting-style:translate-x-[-7px] data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:scale-[0.26] data-[side=left]:data-starting-style:rotate-y-[-40deg] data-[side=left]:data-ending-style:translate-x-[-7px] data-[side=left]:data-ending-style:opacity-0 data-[side=left]:data-ending-style:scale-[0.26] data-[side=left]:data-ending-style:rotate-y-[-40deg]`,
159
+ `data-[side=right]:data-starting-style:translate-x-[7px] data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:scale-[0.26] data-[side=right]:data-starting-style:rotate-y-[40deg] data-[side=right]:data-ending-style:translate-x-[7px] data-[side=right]:data-ending-style:opacity-0 data-[side=right]:data-ending-style:scale-[0.26] data-[side=right]:data-ending-style:rotate-y-[40deg]`,
160
+ `data-[side=inline-start]:data-starting-style:translate-x-[-7px] data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:scale-[0.26] data-[side=inline-start]:data-starting-style:rotate-y-[-40deg] data-[side=inline-start]:data-ending-style:translate-x-[-7px] data-[side=inline-start]:data-ending-style:opacity-0 data-[side=inline-start]:data-ending-style:scale-[0.26] data-[side=inline-start]:data-ending-style:rotate-y-[-40deg]`,
161
+ `data-[side=inline-end]:data-starting-style:translate-x-[7px] data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:scale-[0.26] data-[side=inline-end]:data-starting-style:rotate-y-[40deg] data-[side=inline-end]:data-ending-style:translate-x-[7px] data-[side=inline-end]:data-ending-style:opacity-0 data-[side=inline-end]:data-ending-style:scale-[0.26] data-[side=inline-end]:data-ending-style:rotate-y-[40deg]`
162
+ ]
163
+ };
164
+ const cssTransitionPresets = {
165
+ inExpo: `duration-[0.25s] ease-[cubic-bezier(0.95,0.05,0.795,0.035)]`,
166
+ outExpo: `duration-[0.25s] ease-[cubic-bezier(0.19,1,0.22,1)]`,
167
+ inOutExpo: `duration-[0.25s] ease-[cubic-bezier(1,0,0,1)]`,
168
+ anticipate: `duration-[0.25s] ease-[cubic-bezier(1,-0.4,0.35,0.95)]`,
169
+ quickOut: `duration-[0.25s] ease-out`,
170
+ overshootOut: `duration-[0.25s] ease-[cubic-bezier(0.175,0.885,0.32,1.275)]`,
171
+ swiftOut: `duration-[0.25s] ease-[cubic-bezier(0.175,0.885,0.32,1.1)]`,
172
+ snappyOut: `duration-[0.25s] ease-[cubic-bezier(0.19,1,0.22,1)]`,
173
+ in: `duration-[0.25s] ease-[cubic-bezier(0.42,0,1,1)]`,
174
+ out: `duration-[0.25s] ease-[cubic-bezier(0,0,0.58,1)]`,
175
+ inOut: `duration-[0.25s] ease-[cubic-bezier(0.42,0,0.58,1)]`,
176
+ outIn: `duration-[0.25s] ease-[cubic-bezier(0.1,0.7,0.9,0.5)]`,
177
+ inQuad: `duration-[0.25s] ease-[cubic-bezier(0.55,0.085,0.68,0.53)]`,
178
+ outQuad: `duration-[0.25s] ease-[cubic-bezier(0.25,0.46,0.45,0.94)]`,
179
+ inOutQuad: `duration-[0.32s] ease-[cubic-bezier(0.455,0.03,0.515,0.955)]`,
180
+ inCubic: `duration-[0.25s] ease-[cubic-bezier(0.55,0.055,0.675,0.19)]`,
181
+ outCubic: `duration-[0.25s] ease-[cubic-bezier(0.215,0.61,0.355,1)]`,
182
+ inOutCubic: `duration-[0.25s] ease-[cubic-bezier(0.645,0.045,0.355,1)]`,
183
+ inQuart: `duration-[0.25s] ease-[cubic-bezier(0.895,0.03,0.685,0.22)]`,
184
+ outQuart: `duration-[0.25s] ease-[cubic-bezier(0.165,0.84,0.44,1)]`,
185
+ inOutQuart: `duration-[0.25s] ease-[cubic-bezier(0.77,0,0.175,1)]`,
186
+ inQuint: `duration-[0.25s] ease-[cubic-bezier(0.755,0.05,0.855,0.06)]`,
187
+ outQuint: `duration-[0.25s] ease-[cubic-bezier(0.23,1,0.32,1)]`,
188
+ inOutQuint: `duration-[0.25s] ease-[cubic-bezier(0.86,0,0.07,1)]`,
189
+ inCirc: `duration-[0.25s] ease-[cubic-bezier(0.6,0.04,0.98,0.335)]`,
190
+ outCirc: `duration-[0.25s] ease-[cubic-bezier(0.075,0.82,0.165,1)]`,
191
+ inOutCirc: `duration-[0.25s] ease-[cubic-bezier(0.785,0.135,0.15,0.86)]`,
192
+ inOutBase: `duration-[0.25s] ease-[cubic-bezier(0.25,0.1,0.25,1)]`,
193
+ none: `duration-0 ease-none`
194
+ };
195
+ function TooltipProvider({ delay = 300, ...props }) {
196
+ return /* @__PURE__ */ jsx(Tooltip$1.Provider, {
197
+ "data-slot": "tooltip-provider",
198
+ delay,
199
+ ...props
200
+ });
201
+ }
202
+ function Tooltip({ ...props }) {
203
+ return /* @__PURE__ */ jsx(Tooltip$1.Root, {
204
+ "data-slot": "tooltip",
205
+ ...props
206
+ });
207
+ }
208
+ function TooltipTrigger(props) {
209
+ return /* @__PURE__ */ jsx(Tooltip$1.Trigger, {
210
+ "data-slot": "tooltip-trigger",
211
+ ...props
212
+ });
213
+ }
214
+ function TooltipPortal(props) {
215
+ return /* @__PURE__ */ jsx(Tooltip$1.Portal, {
216
+ "data-slot": "tooltip-portal",
217
+ ...props
218
+ });
219
+ }
220
+ function TooltipPositioner({ className, side = "top", ...rest }) {
221
+ return /* @__PURE__ */ jsx(TooltipPortal, { children: /* @__PURE__ */ jsx(Tooltip$1.Positioner, {
222
+ side,
223
+ "data-slot": "tooltip-positioner",
224
+ className: cn("z-100", (side === "inline-end" || side === "inline-start") && "**:data-[slot=tooltip-arrow]:hidden", className),
225
+ ...rest
226
+ }) });
227
+ }
228
+ function TooltipPopup({ className, animationPreset = "scale", transitionPreset = "outQuint", reduceMotion = false, showArrow = false, side = "top", sideOffset = 4, align = "center", alignOffset = 0, ...rest }) {
229
+ const cssAnimationConfig = useMemo(() => {
230
+ if (reduceMotion) return "none";
231
+ if (animationPreset) return cssAnimationPresets[animationPreset];
232
+ return cssAnimationPresets.scale;
233
+ }, [
234
+ animationPreset,
235
+ reduceMotion,
236
+ side
237
+ ]);
238
+ const cssTransitionConfig = useMemo(() => {
239
+ if (reduceMotion) return "none";
240
+ if (transitionPreset) return cssTransitionPresets[transitionPreset];
241
+ return cssTransitionPresets.snappyOut;
242
+ }, [
243
+ transitionPreset,
244
+ reduceMotion,
245
+ side
246
+ ]);
247
+ return /* @__PURE__ */ jsx(TooltipPositioner, {
248
+ side,
249
+ sideOffset,
250
+ align,
251
+ alignOffset,
252
+ children: /* @__PURE__ */ jsx(Tooltip$1.Popup, {
253
+ "data-slot": "tooltip-popup",
254
+ className: cn("[--radius:10px]", "bg-popover border-border pointer-events-auto w-fit origin-(--transform-origin) rounded-(--radius) border px-2 py-1 text-[13px] text-balance shadow-xs data-instant:duration-0!", className, cssAnimationConfig, cssTransitionConfig, showArrow && [
255
+ `before: before:bg-popover z-[-1] before:absolute before:h-2 before:w-2 before:rotate-45 before:content-['']`,
256
+ side === "top" && `before:border-border before:-bottom-[4.7px] before:left-1/2 before:-translate-x-1/2 before:border-r before:border-b`,
257
+ side === "right" && `before:border-border before:top-1/2 before:-left-[4.07px] before:-translate-y-1/2 before:border-b before:border-l`,
258
+ side === "bottom" && `before:border-border before:-top-[4.7px] before:left-1/2 before:-translate-x-1/2 before:border-t before:border-l`,
259
+ side === "left" && `before:border-border before:top-1/2 before:-right-[4.07px] before:-translate-y-1/2 before:border-t before:border-r`,
260
+ side === "inline-start" && `before:border-border before:top-1/2 before:-right-[4.07px] before:-translate-y-1/2 before:border-t before:border-r`,
261
+ side === "inline-end" && `before:border-border before:top-1/2 before:-left-[4.07px] before:-translate-y-1/2 before:border-b before:border-l`
262
+ ]),
263
+ ...rest
264
+ })
265
+ });
266
+ }
267
+
46
268
  //#endregion
47
269
  //#region src/components/Fields/Label/index.tsx
48
- const Label$1 = ({ label, readOnly }) => /* @__PURE__ */ jsx(Label$2, {
270
+ const Label$1 = ({ label, readOnly, tooltip }) => /* @__PURE__ */ jsxs(Label$2, {
49
271
  readOnly,
50
- children: label
272
+ children: [label, tooltip && /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
273
+ delay: 200,
274
+ children: /* @__PURE__ */ jsx(Button, {
275
+ variant: "secondary",
276
+ className: "!text-xs !rounded-full !p-0 !size-5 flex items-center justify-center",
277
+ children: "?"
278
+ })
279
+ }), /* @__PURE__ */ jsx(TooltipPopup, {
280
+ side: "top",
281
+ align: "end",
282
+ className: "max-w-64 text-xs",
283
+ children: tooltip
284
+ })] })]
51
285
  });
52
286
  var Label_default = Label$1;
53
287
 
@@ -88,11 +322,13 @@ const FieldCheckbox = ({ onChange, value, readOnly, field, label }) => {
88
322
  onChange(newValues);
89
323
  }
90
324
  };
91
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Label_default, {
325
+ const containerClassName = layout === "horizontal" ? "flex w-fit flex-wrap gap-1.5" : "flex flex-col gap-3";
326
+ return /* @__PURE__ */ jsxs(Fragment, { children: [label && /* @__PURE__ */ jsx(Label_default, {
92
327
  label,
93
- readOnly
328
+ readOnly: field.readOnly || readOnly,
329
+ tooltip: field.tooltip
94
330
  }), /* @__PURE__ */ jsx("div", {
95
- className: layout === "horizontal" ? "flex w-fit flex-wrap gap-1.5" : "flex flex-col gap-3",
331
+ className: containerClassName,
96
332
  children: field.options.map((option, index) => {
97
333
  const optionValue = option.value;
98
334
  const key = `${String(optionValue)}-${index}`;
@@ -150,7 +386,8 @@ function Input({ className, size = "default", unstyled = false, nativeInput = fa
150
386
  //#region src/components/Fields/Input/index.tsx
151
387
  const FieldInput = ({ onChange, value, label, field, readOnly }) => /* @__PURE__ */ jsxs(Fragment, { children: [label && /* @__PURE__ */ jsx(Label_default, {
152
388
  label,
153
- readOnly: field.readOnly || readOnly
389
+ readOnly: field.readOnly || readOnly,
390
+ tooltip: field.tooltip
154
391
  }), /* @__PURE__ */ jsx(Input, {
155
392
  type: "text",
156
393
  value: value || "",
@@ -162,322 +399,113 @@ var Input_default = FieldInput;
162
399
 
163
400
  //#endregion
164
401
  //#region src/components/ui/select.tsx
165
- const cssAnimationPresets$2 = {
166
- none: "transition-none",
167
- scale: [`[transition-property:scale,opacity] [will-change:scale,opacity]`, `data-starting-style:scale-80 data-starting-style:opacity-0 data-ending-style:opacity-0 data-ending-style:scale-80`],
168
- fade: [`[transition-property:opacity] [will-change:opacity]`, `data-starting-style:opacity-0 data-ending-style:opacity-0`],
169
- slideOutside: [
170
- `[transition-property:translate,opacity] [will-change:translate,opacity]`,
171
- `data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:translate-y-[10px] data-[side=bottom]:data-ending-style:translate-y-[10px] data-[side=bottom]:data-ending-style:opacity-0`,
172
- `data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:translate-y-[-10px] data-[side=top]:data-ending-style:translate-y-[-10px] data-[side=top]:data-ending-style:opacity-0`,
173
- `data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:translate-x-[-10px] data-[side=left]:data-ending-style:translate-x-[-10px] data-[side=left]:data-ending-style:opacity-0`,
174
- `data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:translate-x-[10px] data-[side=right]:data-ending-style:translate-x-[10px] data-[side=right]:data-ending-style:opacity-0`,
175
- `data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:translate-x-[-10px] data-[side=inline-start]:data-ending-style:translate-x-[-10px] data-[side=inline-start]:data-ending-style:opacity-0`,
176
- `data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:translate-x-[10px] data-[side=inline-end]:data-ending-style:translate-x-[10px] data-[side=inline-end]:data-ending-style:opacity-0`
177
- ],
178
- slideInside: [
179
- `[transition-property:translate,opacity] [will-change:translate,opacity]`,
180
- `data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:translate-y-[-10px] data-[side=bottom]:data-ending-style:translate-y-[-10px] data-[side=bottom]:data-ending-style:opacity-0`,
181
- `data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:translate-y-[10px] data-[side=top]:data-ending-style:translate-y-[10px] data-[side=top]:data-ending-style:opacity-0`,
182
- `data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:translate-x-[10px] data-[side=left]:data-ending-style:translate-x-[10px] data-[side=left]:data-ending-style:opacity-0`,
183
- `data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:translate-x-[-10px] data-[side=right]:data-ending-style:translate-x-[-10px] data-[side=right]:data-ending-style:opacity-0`,
184
- `data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:translate-x-[10px] data-[side=inline-start]:data-ending-style:translate-x-[10px] data-[side=inline-start]:data-ending-style:opacity-0`,
185
- `data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:translate-x-[-10px] data-[side=inline-end]:data-ending-style:translate-x-[-10px] data-[side=inline-end]:data-ending-style:opacity-0`
186
- ],
187
- wipe: [
188
- `[transition-property:clip-path] [will-change:clip-path]`,
189
- `[clip-path:inset(0_0_0_0_round_12px)] [-webkit-clip-path:inset(0_0_0_0_round_12px)]`,
190
- `data-[side=bottom]:data-starting-style:[clip-path:inset(0_0_100%_0_round_12px)] data-[side=bottom]:data-ending-style:[clip-path:inset(0_0_100%_0_round_12px)]`,
191
- `data-[side=top]:data-starting-style:[clip-path:inset(100%_0_0_0_round_12px)] data-[side=top]:data-ending-style:[clip-path:inset(100%_0_0_0_round_12px)]`,
192
- `data-[side=left]:data-starting-style:[clip-path:inset(0_0_0_100%_round_12px)] data-[side=left]:data-ending-style:[clip-path:inset(0_0_0_100%_round_12px)]`,
193
- `data-[side=right]:data-starting-style:[clip-path:inset(0_100%_0_0_round_12px)] data-[side=right]:data-ending-style:[clip-path:inset(0_100%_0_0_round_12px)]`,
194
- `data-[side=inline-start]:data-starting-style:[clip-path:inset(0_0_0_100%_round_12px)] data-[side=inline-start]:data-ending-style:[clip-path:inset(0_0_0_100%_round_12px)]`,
195
- `data-[side=inline-end]:data-starting-style:[clip-path:inset(0_100%_0_0_round_12px)] data-[side=inline-end]:data-ending-style:[clip-path:inset(0_100%_0_0_round_12px)]`
196
- ],
197
- wipeScale: [
198
- `[transition-property:clip-path,scale] [will-change:clip-path,scale]`,
199
- `[clip-path:inset(0_0_0_0_round_12px)] [-webkit-clip-path:inset(0_0_0_0_round_12px)]`,
200
- `data-starting-style:scale-80 data-ending-style:scale-80`,
201
- `data-[side=bottom]:data-starting-style:[clip-path:inset(0_0_100%_0_round_12px)] data-[side=bottom]:data-ending-style:[clip-path:inset(0_0_100%_0_round_12px)]`,
202
- `data-[side=top]:data-starting-style:[clip-path:inset(100%_0_0_0_round_12px)] data-[side=top]:data-ending-style:[clip-path:inset(100%_0_0_0_round_12px)]`,
203
- `data-[side=left]:data-starting-style:[clip-path:inset(0_0_0_100%_round_12px)] data-[side=left]:data-ending-style:[clip-path:inset(0_0_0_100%_round_12px)]`,
204
- `data-[side=right]:data-starting-style:[clip-path:inset(0_100%_0_0_round_12px)] data-[side=right]:data-ending-style:[clip-path:inset(0_100%_0_0_round_12px)]`,
205
- `data-[side=inline-start]:data-starting-style:[clip-path:inset(0_0_0_100%_round_12px)] data-[side=inline-start]:data-ending-style:[clip-path:inset(0_0_0_100%_round_12px)]`,
206
- `data-[side=inline-end]:data-starting-style:[clip-path:inset(0_100%_0_0_round_12px)] data-[side=inline-end]:data-ending-style:[clip-path:inset(0_100%_0_0_round_12px)]`
207
- ],
208
- motion: [
209
- `[transition-property:translate,scale,opacity,rotateX,rotateY,transform] [will-change:translate,scale,opacity,rotateX,rotateY,transform]`,
210
- `[transform:perspective(1000px)]`,
211
- `data-[side=bottom]:data-starting-style:translate-y-[7px] data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:scale-[0.26] data-[side=bottom]:data-starting-style:rotate-x-[70deg] data-[side=bottom]:data-ending-style:translate-y-[7px] data-[side=bottom]:data-ending-style:opacity-0 data-[side=bottom]:data-ending-style:scale-[0.26] data-[side=bottom]:data-ending-style:rotate-x-[70deg]`,
212
- `data-[side=top]:data-starting-style:translate-y-[7px] data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:scale-[0.26] data-[side=top]:data-starting-style:rotate-x-[70deg] data-[side=top]:data-ending-style:translate-y-[7px] data-[side=top]:data-ending-style:opacity-0 data-[side=top]:data-ending-style:scale-[0.26] data-[side=top]:data-ending-style:rotate-x-[70deg]`,
213
- `data-[side=left]:data-starting-style:translate-x-[-7px] data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:scale-[0.26] data-[side=left]:data-starting-style:rotate-y-[-40deg] data-[side=left]:data-ending-style:translate-x-[-7px] data-[side=left]:data-ending-style:opacity-0 data-[side=left]:data-ending-style:scale-[0.26] data-[side=left]:data-ending-style:rotate-y-[-40deg]`,
214
- `data-[side=right]:data-starting-style:translate-x-[7px] data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:scale-[0.26] data-[side=right]:data-starting-style:rotate-y-[40deg] data-[side=right]:data-ending-style:translate-x-[7px] data-[side=right]:data-ending-style:opacity-0 data-[side=right]:data-ending-style:scale-[0.26] data-[side=right]:data-ending-style:rotate-y-[40deg]`,
215
- `data-[side=inline-start]:data-starting-style:translate-x-[-7px] data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:scale-[0.26] data-[side=inline-start]:data-starting-style:rotate-y-[-40deg] data-[side=inline-start]:data-ending-style:translate-x-[-7px] data-[side=inline-start]:data-ending-style:opacity-0 data-[side=inline-start]:data-ending-style:scale-[0.26] data-[side=inline-start]:data-ending-style:rotate-y-[-40deg]`,
216
- `data-[side=inline-end]:data-starting-style:translate-x-[7px] data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:scale-[0.26] data-[side=inline-end]:data-starting-style:rotate-y-[40deg] data-[side=inline-end]:data-ending-style:translate-x-[7px] data-[side=inline-end]:data-ending-style:opacity-0 data-[side=inline-end]:data-ending-style:scale-[0.26] data-[side=inline-end]:data-ending-style:rotate-y-[40deg]`
217
- ],
218
- motionBlur: [
219
- `[transition-property:translate,scale,opacity,rotateX,rotateY,transform,filter] [will-change:translate,scale,opacity,rotateX,rotateY,transform,filter]`,
220
- `[transform:perspective(1000px)]`,
221
- `data-starting-style:blur-[9px] data-ending-style:blur-[9px]`,
222
- `data-[side=bottom]:data-starting-style:translate-y-[7px] data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:scale-[0.26] data-[side=bottom]:data-starting-style:rotate-x-[70deg] data-[side=bottom]:data-ending-style:translate-y-[7px] data-[side=bottom]:data-ending-style:opacity-0 data-[side=bottom]:data-ending-style:scale-[0.26] data-[side=bottom]:data-ending-style:rotate-x-[70deg]`,
223
- `data-[side=top]:data-starting-style:translate-y-[7px] data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:scale-[0.26] data-[side=top]:data-starting-style:rotate-x-[70deg] data-[side=top]:data-ending-style:translate-y-[7px] data-[side=top]:data-ending-style:opacity-0 data-[side=top]:data-ending-style:scale-[0.26] data-[side=top]:data-ending-style:rotate-x-[70deg]`,
224
- `data-[side=left]:data-starting-style:translate-x-[-7px] data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:scale-[0.26] data-[side=left]:data-starting-style:rotate-y-[-40deg] data-[side=left]:data-ending-style:translate-x-[-7px] data-[side=left]:data-ending-style:opacity-0 data-[side=left]:data-ending-style:scale-[0.26] data-[side=left]:data-ending-style:rotate-y-[-40deg]`,
225
- `data-[side=right]:data-starting-style:translate-x-[7px] data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:scale-[0.26] data-[side=right]:data-starting-style:rotate-y-[40deg] data-[side=right]:data-ending-style:translate-x-[7px] data-[side=right]:data-ending-style:opacity-0 data-[side=right]:data-ending-style:scale-[0.26] data-[side=right]:data-ending-style:rotate-y-[40deg]`,
226
- `data-[side=inline-start]:data-starting-style:translate-x-[-7px] data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:scale-[0.26] data-[side=inline-start]:data-starting-style:rotate-y-[-40deg] data-[side=inline-start]:data-ending-style:translate-x-[-7px] data-[side=inline-start]:data-ending-style:opacity-0 data-[side=inline-start]:data-ending-style:scale-[0.26] data-[side=inline-start]:data-ending-style:rotate-y-[-40deg]`,
227
- `data-[side=inline-end]:data-starting-style:translate-x-[7px] data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:scale-[0.26] data-[side=inline-end]:data-starting-style:rotate-y-[40deg] data-[side=inline-end]:data-ending-style:translate-x-[7px] data-[side=inline-end]:data-ending-style:opacity-0 data-[side=inline-end]:data-ending-style:scale-[0.26] data-[side=inline-end]:data-ending-style:rotate-y-[40deg]`
228
- ]
229
- };
230
- const cssTransitionPresets$2 = {
231
- inExpo: `duration-[0.35s] ease-[cubic-bezier(0.95,0.05,0.795,0.035)]`,
232
- outExpo: `duration-[0.35s] ease-[cubic-bezier(0.19,1,0.22,1)]`,
233
- inOutExpo: `duration-[0.35s] ease-[cubic-bezier(1,0,0,1)]`,
234
- anticipate: `duration-[0.35s] ease-[cubic-bezier(1,-0.4,0.35,0.95)]`,
235
- quickOut: `duration-[0.35s] ease-out`,
236
- overshootOut: `duration-[0.35s] ease-[cubic-bezier(0.175,0.885,0.32,1.275)]`,
237
- swiftOut: `duration-[0.35s] ease-[cubic-bezier(0.175,0.885,0.32,1.1)]`,
238
- snappyOut: `duration-[0.35s] ease-[cubic-bezier(0.19,1,0.22,1)]`,
239
- in: `duration-[0.35s] ease-[cubic-bezier(0.42,0,1,1)]`,
240
- out: `duration-[0.35s] ease-[cubic-bezier(0,0,0.58,1)]`,
241
- inOut: `duration-[0.25s] ease-[cubic-bezier(0.42,0,0.58,1)]`,
242
- outIn: `duration-[0.35s] ease-[cubic-bezier(0.1,0.7,0.9,0.5)]`,
243
- inQuad: `duration-[0.35s] ease-[cubic-bezier(0.55,0.085,0.68,0.53)]`,
244
- outQuad: `duration-[0.25s] ease-[cubic-bezier(0.25,0.46,0.45,0.94)]`,
245
- inOutQuad: `duration-[0.32s] ease-[cubic-bezier(0.455,0.03,0.515,0.955)]`,
246
- inCubic: `duration-[0.35s] ease-[cubic-bezier(0.55,0.055,0.675,0.19)]`,
247
- outCubic: `duration-[0.35s] ease-[cubic-bezier(0.215,0.61,0.355,1)]`,
248
- inOutCubic: `duration-[0.35s] ease-[cubic-bezier(0.645,0.045,0.355,1)]`,
249
- inQuart: `duration-[0.35s] ease-[cubic-bezier(0.895,0.03,0.685,0.22)]`,
250
- outQuart: `duration-[0.35s] ease-[cubic-bezier(0.165,0.84,0.44,1)]`,
251
- inOutQuart: `duration-[0.35s] ease-[cubic-bezier(0.77,0,0.175,1)]`,
252
- inQuint: `duration-[0.35s] ease-[cubic-bezier(0.755,0.05,0.855,0.06)]`,
253
- outQuint: `duration-[0.35s] ease-[cubic-bezier(0.23,1,0.32,1)]`,
254
- inOutQuint: `duration-[0.35s] ease-[cubic-bezier(0.86,0,0.07,1)]`,
255
- inCirc: `duration-[0.35s] ease-[cubic-bezier(0.6,0.04,0.98,0.335)]`,
256
- outCirc: `duration-[0.35s] ease-[cubic-bezier(0.075,0.82,0.165,1)]`,
257
- inOutCirc: `duration-[0.35s] ease-[cubic-bezier(0.785,0.135,0.15,0.86)]`,
258
- inOutBase: `duration-[0.35s] ease-[cubic-bezier(0.25,0.1,0.25,1)]`
259
- };
260
- const SelectContext = createContext(void 0);
261
- function useSelect() {
262
- const context = useContext(SelectContext);
263
- if (!context) throw new Error("useSelect must be used within a SelectProvider");
264
- return context;
265
- }
266
- function Select({ backdrop = "transparent", ...props }) {
267
- return /* @__PURE__ */ jsx(SelectContext.Provider, {
268
- value: { backdrop },
269
- children: /* @__PURE__ */ jsx(Select$1.Root, {
270
- "data-slot": "select",
271
- ...props
272
- })
273
- });
274
- }
275
- function SelectTrigger({ className, ...props }) {
276
- return /* @__PURE__ */ jsx(Select$1.Trigger, {
402
+ const Select = Select$1.Root;
403
+ const selectTriggerVariants = cva("relative inline-flex min-h-9 w-full min-w-36 select-none items-center justify-between gap-2 rounded-lg border border-input bg-background not-dark:bg-clip-padding px-[calc(--spacing(3)-1px)] text-left text-base text-foreground shadow-xs/5 outline-none ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 data-disabled:pointer-events-none data-disabled:opacity-64 sm:min-h-8 sm:text-sm dark:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none", {
404
+ defaultVariants: { size: "default" },
405
+ variants: { size: {
406
+ default: "",
407
+ lg: "min-h-10 sm:min-h-9",
408
+ sm: "min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7"
409
+ } }
410
+ });
411
+ const selectTriggerIconClassName = "-me-1 size-4.5 opacity-80 sm:size-4";
412
+ function SelectTrigger({ className, size = "default", children, ...props }) {
413
+ return /* @__PURE__ */ jsxs(Select$1.Trigger, {
414
+ className: cn(selectTriggerVariants({ size }), className),
277
415
  "data-slot": "select-trigger",
278
- className: cn("group/select-trigger border-input text-foreground focus-visible:border-primary bg-background dark:bg-input/40 inline-flex h-fit w-full touch-none items-center justify-between gap-3 rounded-lg border px-[calc(--spacing(2.5)-1px)] py-[calc(--spacing(2)-1px)] text-sm transition-colors ease-out select-none focus-visible:outline-none", className),
279
- ...props
416
+ ...props,
417
+ children: [children, /* @__PURE__ */ jsx(Select$1.Icon, {
418
+ "data-slot": "select-icon",
419
+ children: /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: selectTriggerIconClassName })
420
+ })]
280
421
  });
281
422
  }
282
- function SelectValue({ className, placeholder = "Select...", ...props }) {
423
+ function SelectValue({ className, ...props }) {
283
424
  return /* @__PURE__ */ jsx(Select$1.Value, {
425
+ className: cn("flex-1 truncate data-placeholder:text-muted-foreground", className),
284
426
  "data-slot": "select-value",
285
- ...props,
286
- render: (renderProps, state) => {
287
- const newValue = state.value;
288
- if ((newValue === null || newValue === void 0) && !renderProps.children) return /* @__PURE__ */ jsx("span", {
289
- ...renderProps,
290
- className: cn("text-foreground/60 w-full text-left", className),
291
- children: placeholder
292
- });
293
- return /* @__PURE__ */ jsx("span", {
294
- ...renderProps,
295
- className: cn("fadeIn w-full truncate text-left", className)
296
- }, newValue);
297
- }
298
- });
299
- }
300
- function SelectIcon({ className, ...props }) {
301
- return /* @__PURE__ */ jsx(Select$1.Icon, {
302
- "data-slot": "select-icon",
303
- className: cn("text-foreground/72 size-3.5 shrink-0", className),
304
- ...props
305
- });
306
- }
307
- function SelectPortal(props) {
308
- return /* @__PURE__ */ jsx(Select$1.Portal, {
309
- "data-slot": "select-portal",
310
- ...props
311
- });
312
- }
313
- function SelectBackdrop({ className, ...props }) {
314
- const { backdrop = "transparent" } = useSelect();
315
- return /* @__PURE__ */ jsx(Select$1.Backdrop, {
316
- "data-slot": "select-backdrop",
317
- className: cn(backdrop === "opaque" && "fixed inset-0 z-100 bg-black opacity-40 transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:opacity-60", backdrop === "blur" && "fixed inset-0 z-100 backdrop-blur-sm transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0", backdrop === "transparent" && "hidden", className),
318
427
  ...props
319
428
  });
320
429
  }
321
- function SelectPositioner({ sideOffset = 4, side = "bottom", className, alignItemWithTrigger = true, ...props }) {
322
- return /* @__PURE__ */ jsxs(SelectPortal, { children: [/* @__PURE__ */ jsx(SelectBackdrop, {}), /* @__PURE__ */ jsx(Select$1.Positioner, {
323
- sideOffset,
324
- side,
430
+ function SelectPopup({ className, children, side = "bottom", sideOffset = 4, align = "start", alignOffset = 0, alignItemWithTrigger = true, anchor, ...props }) {
431
+ return /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(Select$1.Positioner, {
432
+ align,
325
433
  alignItemWithTrigger,
434
+ alignOffset,
435
+ anchor,
436
+ className: "z-50 select-none",
326
437
  "data-slot": "select-positioner",
327
- className: cn("z-100 outline-none select-none", className),
328
- ...props
329
- })] });
330
- }
331
- function SelectArrow({ className, ...rest }) {
332
- return /* @__PURE__ */ jsx(Select$1.Arrow, {
333
- "data-slot": "select-arrow",
334
- className: cn("data-[side=bottom]:top-[-9px] data-[side=left]:right-[-14px] data-[side=left]:rotate-90 data-[side=right]:left-[-14px] data-[side=right]:-rotate-90 data-[side=top]:bottom-[-9px] data-[side=top]:rotate-180", className),
335
- ...rest
336
- });
337
- }
338
- function ArrowSvg(props) {
339
- return /* @__PURE__ */ jsxs("svg", {
340
- width: "20",
341
- height: "10",
342
- viewBox: "0 0 20 10",
343
- fill: "none",
344
- ...props,
345
- children: [/* @__PURE__ */ jsx("path", {
346
- d: "M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z",
347
- className: "fill-popover"
348
- }), /* @__PURE__ */ jsx("path", {
349
- d: "M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z",
350
- className: "fill-border/60"
351
- })]
352
- });
353
- }
354
- function SelectPopup({ className, animationPreset = "scale", transitionPreset = "outQuint", reduceMotion = false, showArrow = false, side = "bottom", sideOffset = 4, align = "center", alignOffset = 0, alignItemWithTrigger = false, children, ...rest }) {
355
- const cssAnimationConfig = useMemo(() => {
356
- if (reduceMotion) return "";
357
- if (animationPreset) return cssAnimationPresets$2[animationPreset];
358
- return cssAnimationPresets$2.scale;
359
- }, [
360
- animationPreset,
361
- reduceMotion,
362
- side
363
- ]);
364
- const cssTransitionConfig = useMemo(() => {
365
- if (reduceMotion) return "";
366
- if (transitionPreset) return cssTransitionPresets$2[transitionPreset];
367
- return cssTransitionPresets$2.snappyOut;
368
- }, [
369
- transitionPreset,
370
- reduceMotion,
371
- side
372
- ]);
373
- return /* @__PURE__ */ jsx(SelectPositioner, {
374
438
  side,
375
439
  sideOffset,
376
- align,
377
- alignOffset,
378
- alignItemWithTrigger,
379
- className: "",
380
- children: /* @__PURE__ */ jsx(Select$1.Popup, {
440
+ children: /* @__PURE__ */ jsxs(Select$1.Popup, {
441
+ className: "origin-(--transform-origin) text-foreground",
381
442
  "data-slot": "select-popup",
382
- render: (renderProps) => {
383
- if (alignItemWithTrigger) return /* @__PURE__ */ jsxs("div", {
384
- ...renderProps,
385
- className: cn("pointer-events-auto origin-(--transform-origin)", className),
386
- style: { ...renderProps.style },
387
- children: [
388
- showArrow && /* @__PURE__ */ jsx(SelectArrow, { children: /* @__PURE__ */ jsx(ArrowSvg, {}) }),
389
- /* @__PURE__ */ jsx(Select$1.ScrollUpArrow, {
390
- className: cn("top-0 z-50 flex h-6 w-full cursor-default items-center justify-center", "before:from-popover before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[140%] before:rounded-t-[calc(var(--radius-lg)-1px)] before:bg-linear-to-b before:from-50%"),
391
- "data-slot": "select-scroll-up-arrow",
392
- children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "relative size-4" })
393
- }),
394
- children,
395
- /* @__PURE__ */ jsx(Select$1.ScrollDownArrow, {
396
- className: cn("bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center", "before:from-popover before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[140%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50%"),
397
- "data-slot": "select-scroll-down-arrow",
398
- children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "relative size-4" })
399
- })
400
- ]
401
- }, "select-popup");
402
- return /* @__PURE__ */ jsxs("div", {
403
- ...renderProps,
404
- className: cn("pointer-events-auto origin-(--transform-origin)", className, renderProps.className, cssTransitionConfig, cssAnimationConfig),
405
- children: [
406
- showArrow && /* @__PURE__ */ jsx(SelectArrow, { children: /* @__PURE__ */ jsx(ArrowSvg, {}) }),
407
- /* @__PURE__ */ jsx(Select$1.ScrollUpArrow, {
408
- className: cn("top-0 z-50 flex h-6 w-full cursor-default items-center justify-center", "before:from-popover before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[140%] before:rounded-t-[calc(var(--radius-lg)-1px)] before:bg-linear-to-b before:from-50%"),
409
- "data-slot": "select-scroll-up-arrow",
410
- children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "relative size-4" })
411
- }),
412
- children,
413
- /* @__PURE__ */ jsx(Select$1.ScrollDownArrow, {
414
- className: cn("bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center", "before:from-popover before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[140%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50%"),
415
- "data-slot": "select-scroll-down-arrow",
416
- children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "relative size-4" })
417
- })
418
- ]
419
- }, "select-popup");
420
- },
421
- ...rest
443
+ ...props,
444
+ children: [
445
+ /* @__PURE__ */ jsx(Select$1.ScrollUpArrow, {
446
+ className: "top-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[200%] before:rounded-t-[calc(var(--radius-lg)-1px)] before:bg-linear-to-b before:from-50% before:from-popover",
447
+ "data-slot": "select-scroll-up-arrow",
448
+ children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "relative size-4.5 sm:size-4" })
449
+ }),
450
+ /* @__PURE__ */ jsx("div", {
451
+ className: "relative h-full min-w-(--anchor-width) rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
452
+ children: /* @__PURE__ */ jsx(Select$1.List, {
453
+ className: cn("max-h-(--available-height) overflow-y-auto p-1", className),
454
+ "data-slot": "select-list",
455
+ children
456
+ })
457
+ }),
458
+ /* @__PURE__ */ jsx(Select$1.ScrollDownArrow, {
459
+ className: "bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[200%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50% before:from-popover",
460
+ "data-slot": "select-scroll-down-arrow",
461
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "relative size-4.5 sm:size-4" })
462
+ })
463
+ ]
422
464
  })
423
- });
424
- }
425
- function SelectList({ className, ...props }) {
426
- return /* @__PURE__ */ jsx(Select$1.List, {
427
- "data-slot": "select-list",
428
- className: cn("bg-popover relative block h-full max-h-[min(var(--available-height),360px)] min-w-(--anchor-width) overflow-y-auto rounded-lg border p-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", className),
429
- ...props
430
- });
465
+ }) });
431
466
  }
432
- function SelectItem({ className, ...props }) {
433
- return /* @__PURE__ */ jsx(Select$1.Item, {
467
+ function SelectItem({ className, children, ...props }) {
468
+ return /* @__PURE__ */ jsxs(Select$1.Item, {
469
+ className: cn("grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-default grid-cols-[1rem_1fr] items-center gap-2 rounded-sm py-1 ps-2 pe-4 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", className),
434
470
  "data-slot": "select-item",
435
- className: cn("relative flex min-w-(--anchor-width) cursor-default items-center gap-2 px-3 py-1.5 text-sm outline-none select-none group-data-[side=none]:min-w-[calc(var(--anchor-width))]", `data-highlighted:before:bg-accent/70 dark:data-highlighted:before:bg-accent data-highlighted:text-accent-foreground data-highlighted:before:border-border/30 data-highlighted:z-0 data-highlighted:before:absolute data-highlighted:before:inset-x-0 data-highlighted:before:inset-y-0 data-highlighted:before:z-[-1] data-highlighted:before:rounded-md data-highlighted:before:border`, className),
436
- ...props
437
- });
438
- }
439
- function SelectItemText({ className, ...props }) {
440
- return /* @__PURE__ */ jsx(Select$1.ItemText, {
441
- "data-slot": "select-item-text",
442
- className: cn("flex-1", className),
443
- ...props
471
+ ...props,
472
+ children: [/* @__PURE__ */ jsx(Select$1.ItemIndicator, {
473
+ className: "col-start-1",
474
+ children: /* @__PURE__ */ jsx("svg", {
475
+ fill: "none",
476
+ height: "24",
477
+ stroke: "currentColor",
478
+ strokeLinecap: "round",
479
+ strokeLinejoin: "round",
480
+ strokeWidth: "2",
481
+ viewBox: "0 0 24 24",
482
+ width: "24",
483
+ xmlns: "http://www.w3.org/1500/svg",
484
+ children: /* @__PURE__ */ jsx("path", { d: "M5.252 12.7 10.2 18.63 18.748 5.37" })
485
+ })
486
+ }), /* @__PURE__ */ jsx(Select$1.ItemText, {
487
+ className: "col-start-2 min-w-0",
488
+ children
489
+ })]
444
490
  });
445
491
  }
446
- function SelectItemIndicator({ className, ...props }) {
447
- return /* @__PURE__ */ jsx(Select$1.ItemIndicator, {
448
- "data-slot": "select-item-indicator",
449
- className: cn("ml-auto min-w-fit", className),
492
+ function SelectSeparator({ className, ...props }) {
493
+ return /* @__PURE__ */ jsx(Select$1.Separator, {
494
+ className: cn("mx-2 my-1 h-px bg-border", className),
495
+ "data-slot": "select-separator",
450
496
  ...props
451
497
  });
452
498
  }
453
- function SelectGroup({ ...props }) {
499
+ function SelectGroup(props) {
454
500
  return /* @__PURE__ */ jsx(Select$1.Group, {
455
501
  "data-slot": "select-group",
456
502
  ...props
457
503
  });
458
504
  }
459
- function SelectGroupLabel({ ...props }) {
505
+ function SelectGroupLabel(props) {
460
506
  return /* @__PURE__ */ jsx(Select$1.GroupLabel, {
507
+ className: "px-2 py-1.5 font-medium text-muted-foreground text-xs",
461
508
  "data-slot": "select-group-label",
462
- className: "text-muted-foreground mt-2 mb-1 px-3 text-xs",
463
- ...props
464
- });
465
- }
466
- function SelectScrollUpArrow(props) {
467
- return /* @__PURE__ */ jsx(Select$1.ScrollUpArrow, {
468
- "data-slot": "select-scroll-up-arrow",
469
- ...props
470
- });
471
- }
472
- function SelectScrollDownArrow(props) {
473
- return /* @__PURE__ */ jsx(Select$1.ScrollDownArrow, {
474
- "data-slot": "select-scroll-down-arrow",
475
- ...props
476
- });
477
- }
478
- function SelectSeparator({ ...props }) {
479
- return /* @__PURE__ */ jsx(Select$1.Separator, {
480
- "data-slot": "select-separator",
481
509
  ...props
482
510
  });
483
511
  }
@@ -485,9 +513,9 @@ function SelectSeparator({ ...props }) {
485
513
  //#endregion
486
514
  //#region src/components/Fields/NumberUnit/index.tsx
487
515
  const FieldNumberUnit = ({ onChange, value, label, field, readOnly }) => {
488
- const currentValue = value || {
489
- value: "",
490
- unit: field.options?.[0]?.value || ""
516
+ const currentValue = {
517
+ value: value?.value ?? "",
518
+ unit: value?.unit ?? field.options?.[0]?.value ?? ""
491
519
  };
492
520
  const handleInputChange = (newValue) => {
493
521
  if (!readOnly) onChange({
@@ -501,15 +529,16 @@ const FieldNumberUnit = ({ onChange, value, label, field, readOnly }) => {
501
529
  unit: newUnit
502
530
  });
503
531
  };
504
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Label_default, {
532
+ return /* @__PURE__ */ jsxs(Fragment, { children: [label && /* @__PURE__ */ jsx(Label_default, {
505
533
  label,
506
- readOnly: field.readOnly || readOnly
534
+ readOnly: field.readOnly || readOnly,
535
+ tooltip: field.tooltip
507
536
  }), /* @__PURE__ */ jsxs("div", {
508
537
  className: "flex",
509
538
  children: [/* @__PURE__ */ jsx("div", {
510
539
  className: "flex-1",
511
540
  children: /* @__PURE__ */ jsx(Input, {
512
- className: "rounded-r-none",
541
+ className: "rounded-r-none before:rounded-r-none",
513
542
  type: "text",
514
543
  placeholder: field.placeholder || "Value",
515
544
  value: currentValue.value,
@@ -523,16 +552,16 @@ const FieldNumberUnit = ({ onChange, value, label, field, readOnly }) => {
523
552
  value: currentValue.unit,
524
553
  onValueChange: handleUnitChange,
525
554
  disabled: field.readOnly || readOnly,
526
- children: [/* @__PURE__ */ jsxs(SelectTrigger, {
527
- className: "rounded-l-none border-l-0",
528
- children: [/* @__PURE__ */ jsx(SelectValue, {}), /* @__PURE__ */ jsx(SelectIcon, { children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3.5" }) })]
555
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
556
+ className: "rounded-l-none before:rounded-l-none border-l-0 min-w-fit",
557
+ children: /* @__PURE__ */ jsx(SelectValue, {})
529
558
  }), /* @__PURE__ */ jsx(SelectPopup, {
530
559
  align: "end",
531
560
  side: "bottom",
532
- children: /* @__PURE__ */ jsx(SelectList, { children: (field.options || []).map((option) => /* @__PURE__ */ jsxs(SelectItem, {
561
+ children: (field.options || []).map((option) => /* @__PURE__ */ jsx(SelectItem, {
533
562
  value: option.value,
534
- children: [option.label, /* @__PURE__ */ jsx(SelectItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5" }) })]
535
- }, option.value)) })
563
+ children: option.label
564
+ }, option.value))
536
565
  })]
537
566
  })
538
567
  })]
@@ -563,30 +592,31 @@ const FieldSelect = ({ onChange, value, label, field, readOnly }) => {
563
592
  return acc;
564
593
  }, {});
565
594
  const hasGroups = Object.keys(groupedOptions).some((key) => key !== "__ungrouped");
566
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Label_default, {
595
+ return /* @__PURE__ */ jsxs(Fragment, { children: [label && /* @__PURE__ */ jsx(Label_default, {
567
596
  label,
568
- readOnly: field.readOnly || readOnly
597
+ readOnly: field.readOnly || readOnly,
598
+ tooltip: field.tooltip
569
599
  }), /* @__PURE__ */ jsxs(Select, {
570
600
  items: itemsWithPlaceholder,
571
601
  value: selectValue,
572
602
  onValueChange: handleValueChange,
573
603
  disabled: field.readOnly || readOnly,
574
- children: [/* @__PURE__ */ jsxs(SelectTrigger, {
604
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
575
605
  className: "min-w-46",
576
- children: [/* @__PURE__ */ jsx(SelectValue, {}), /* @__PURE__ */ jsx(SelectIcon, { children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3.5" }) })]
606
+ children: /* @__PURE__ */ jsx(SelectValue, {})
577
607
  }), /* @__PURE__ */ jsx(SelectPopup, {
578
608
  align: "center",
579
609
  side: "bottom",
580
- children: /* @__PURE__ */ jsx(SelectList, { children: hasGroups ? /* @__PURE__ */ jsx(Fragment, { children: Object.keys(groupedOptions).map((groupName) => {
610
+ children: hasGroups ? /* @__PURE__ */ jsx(Fragment, { children: Object.keys(groupedOptions).map((groupName) => {
581
611
  const options = groupedOptions[groupName];
582
- return /* @__PURE__ */ jsxs(SelectGroup, { children: [groupName !== "__ungrouped" && /* @__PURE__ */ jsx(SelectGroupLabel, { children: groupName }), options.map((option) => /* @__PURE__ */ jsxs(SelectItem, {
612
+ return /* @__PURE__ */ jsxs(SelectGroup, { children: [groupName !== "__ungrouped" && /* @__PURE__ */ jsx(SelectGroupLabel, { children: groupName }), options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
583
613
  value: option.value,
584
- children: [option.label, /* @__PURE__ */ jsx(SelectItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3" }) })]
614
+ children: option.label
585
615
  }, typeof option.label === "string" ? option.label : JSON.stringify(option.value)))] }, groupName);
586
- }) }) : field.options.map((option) => /* @__PURE__ */ jsxs(SelectItem, {
616
+ }) }) : field.options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
587
617
  value: option.value,
588
- children: [option.label, /* @__PURE__ */ jsx(SelectItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3" }) })]
589
- }, typeof option.label === "string" ? option.label : JSON.stringify(option.value))) })
618
+ children: option.label
619
+ }, typeof option.label === "string" ? option.label : JSON.stringify(option.value)))
590
620
  })]
591
621
  })] });
592
622
  };
@@ -604,7 +634,7 @@ function RadioGroup({ className, layout = "horizontal", ...props }) {
604
634
  function RadioGroupItem({ className, layout = "horizontal", ...props }) {
605
635
  if (layout === "horizontal") return /* @__PURE__ */ jsx(Radio.Root, {
606
636
  "data-slot": "radio-group-item",
607
- className: cn("text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 group/radio-group-item peer data-[checked]:text-primary-500 relative block flex h-full shrink-0 cursor-pointer items-center justify-center border border-transparent bg-white p-2 text-xs transition-[color,box-shadow] outline-none hover:bg-stone-50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[checked]:bg-stone-50 data-[checked]:font-semibold", className),
637
+ className: cn("text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 group/radio-group-item peer data-[checked]:text-primary-500 relative block flex h-full shrink-0 cursor-pointer items-center justify-center border border-transparent bg-white px-2 py-1.5 text-xs transition-[color,box-shadow] outline-none hover:bg-stone-50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[checked]:bg-stone-50 data-[checked]:font-semibold", className),
608
638
  ...props
609
639
  });
610
640
  return /* @__PURE__ */ jsx(Radio.Root, {
@@ -628,9 +658,10 @@ const FieldRadio = ({ onChange, value, readOnly, field, label }) => {
628
658
  if (!readOnly && newValue != null) onChange(newValue);
629
659
  };
630
660
  const groupClassName = layout === "horizontal" ? "border-input flex w-fit flex-wrap divide-x divide-stone-200 overflow-hidden rounded-md border" : "flex flex-col gap-3";
631
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Label_default, {
661
+ return /* @__PURE__ */ jsxs(Fragment, { children: [label && /* @__PURE__ */ jsx(Label_default, {
632
662
  label,
633
- readOnly
663
+ readOnly: field.readOnly || readOnly,
664
+ tooltip: field.tooltip
634
665
  }), /* @__PURE__ */ jsx(RadioGroup, {
635
666
  layout,
636
667
  value: value?.toString() || "",
@@ -682,9 +713,10 @@ function Textarea({ className, size = "default", unstyled = false, ...props }) {
682
713
 
683
714
  //#endregion
684
715
  //#region src/components/Fields/Textarea/index.tsx
685
- const FieldTextarea = ({ onChange, value, label, field, readOnly }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Label_default, {
716
+ const FieldTextarea = ({ onChange, value, label, field, readOnly }) => /* @__PURE__ */ jsxs(Fragment, { children: [label && /* @__PURE__ */ jsx(Label_default, {
686
717
  label,
687
- readOnly: field.readOnly || readOnly
718
+ readOnly: field.readOnly || readOnly,
719
+ tooltip: field.tooltip
688
720
  }), /* @__PURE__ */ jsx(Textarea, {
689
721
  value: value || "",
690
722
  placeholder: field.placeholder,
@@ -702,7 +734,7 @@ const Action = ({ children, label, onClick }) => /* @__PURE__ */ jsx("button", {
702
734
  title: label,
703
735
  children
704
736
  });
705
- const Group = ({ children }) => /* @__PURE__ */ jsx("div", {
737
+ const Group$1 = ({ children }) => /* @__PURE__ */ jsx("div", {
706
738
  className: "mx-2 flex h-full items-center first:ml-0 last:mr-0 empty:hidden [&>*]:m-0",
707
739
  children
708
740
  });
@@ -724,7 +756,7 @@ const ActionBar = ({ label, parentAction, children }) => /* @__PURE__ */ jsxs("d
724
756
  });
725
757
  ActionBar.Action = Action;
726
758
  ActionBar.Label = Label;
727
- ActionBar.Group = Group;
759
+ ActionBar.Group = Group$1;
728
760
  ActionBar.Separator = Separator$2;
729
761
  var ActionBar_default = ActionBar;
730
762
 
@@ -765,179 +797,40 @@ function TabsPanel({ className, ...props }) {
765
797
 
766
798
  //#endregion
767
799
  //#region src/components/ui/accordion.tsx
768
- const cssAnimationPresets$1 = {
769
- none: "transition-none",
770
- fade: [`[transition-property:opacity,height] [will-change:opacity,height]`, `data-starting-style:opacity-0 data-ending-style:opacity-0 data-starting-style:h-0 data-ending-style:h-0`],
771
- scale: [`[transition-property:scale,opacity,height] [will-change:scale,opacity,height] origin-left`, `data-starting-style:scale-85 data-starting-style:opacity-0 data-starting-style:h-0 data-ending-style:opacity-0 data-ending-style:h-0 data-ending-style:scale-85`],
772
- slide: [`[transition-property:translate,opacity,height] [will-change:translate,opacity,height]`, `data-starting-style:opacity-0 data-starting-style:translate-y-[10px] data-ending-style:translate-y-[10px] data-ending-style:opacity-0 data-ending-style:h-0 data-starting-style:h-0`],
773
- perspective: [
774
- `[transition-property:opacity,rotateX,rotateY,transform,height] [will-change:opacity,rotateX,rotateY,transform,height]`,
775
- `[transform:perspective(1000px)] origin-top`,
776
- `data-starting-style:h-0 data-ending-style:h-0`,
777
- `data-starting-style:opacity-0 data-ending-style:opacity-0`,
778
- `data-starting-style:-rotate-x-[90deg] data-ending-style:-rotate-x-[90deg]`
779
- ],
780
- perspectiveBlur: [
781
- `[transition-property:opacity,rotateX,rotateY,transform,height,filter] [will-change:opacity,rotateX,rotateY,transform,height,filter]`,
782
- `[transform:perspective(1000px)] origin-top`,
783
- `data-starting-style:h-0 data-ending-style:h-0`,
784
- `data-starting-style:opacity-0 data-ending-style:opacity-0`,
785
- `data-starting-style:-rotate-x-[90deg] data-ending-style:-rotate-x-[90deg]`,
786
- `data-starting-style:blur-[9px] data-ending-style:blur-[9px]`
787
- ]
788
- };
789
- const cssTransitionPresets$1 = {
790
- inExpo: `duration-[0.35s] ease-[cubic-bezier(0.95,0.05,0.795,0.035)]`,
791
- outExpo: `duration-[0.35s] ease-[cubic-bezier(0.19,1,0.22,1)]`,
792
- inOutExpo: `duration-[0.35s] ease-[cubic-bezier(1,0,0,1)]`,
793
- anticipate: `duration-[0.35s] ease-[cubic-bezier(1,-0.4,0.35,0.95)]`,
794
- quickOut: `duration-[0.35s] ease-out`,
795
- overshootOut: `duration-[0.35s] ease-[cubic-bezier(0.175,0.885,0.32,1.275)]`,
796
- swiftOut: `duration-[0.35s] ease-[cubic-bezier(0.175,0.885,0.32,1.1)]`,
797
- snappyOut: `duration-[0.35s] ease-[cubic-bezier(0.19,1,0.22,1)]`,
798
- in: `duration-[0.35s] ease-[cubic-bezier(0.42,0,1,1)]`,
799
- out: `duration-[0.35s] ease-[cubic-bezier(0,0,0.58,1)]`,
800
- inOut: `duration-[0.25s] ease-[cubic-bezier(0.42,0,0.58,1)]`,
801
- outIn: `duration-[0.35s] ease-[cubic-bezier(0.1,0.7,0.9,0.5)]`,
802
- inQuad: `duration-[0.35s] ease-[cubic-bezier(0.55,0.085,0.68,0.53)]`,
803
- outQuad: `duration-[0.25s] ease-[cubic-bezier(0.25,0.46,0.45,0.94)]`,
804
- inOutQuad: `duration-[0.32s] ease-[cubic-bezier(0.455,0.03,0.515,0.955)]`,
805
- inCubic: `duration-[0.35s] ease-[cubic-bezier(0.55,0.055,0.675,0.19)]`,
806
- outCubic: `duration-[0.35s] ease-[cubic-bezier(0.215,0.61,0.355,1)]`,
807
- inOutCubic: `duration-[0.35s] ease-[cubic-bezier(0.645,0.045,0.355,1)]`,
808
- inQuart: `duration-[0.35s] ease-[cubic-bezier(0.895,0.03,0.685,0.22)]`,
809
- outQuart: `duration-[0.35s] ease-[cubic-bezier(0.165,0.84,0.44,1)]`,
810
- inOutQuart: `duration-[0.35s] ease-[cubic-bezier(0.77,0,0.175,1)]`,
811
- inQuint: `duration-[0.35s] ease-[cubic-bezier(0.755,0.05,0.855,0.06)]`,
812
- outQuint: `duration-[0.35s] ease-[cubic-bezier(0.23,1,0.32,1)]`,
813
- inOutQuint: `duration-[0.35s] ease-[cubic-bezier(0.86,0,0.07,1)]`,
814
- inCirc: `duration-[0.35s] ease-[cubic-bezier(0.6,0.04,0.98,0.335)]`,
815
- outCirc: `duration-[0.35s] ease-[cubic-bezier(0.075,0.82,0.165,1)]`,
816
- inOutCirc: `duration-[0.35s] ease-[cubic-bezier(0.785,0.135,0.15,0.86)]`,
817
- inOutBase: `duration-[0.35s] ease-[cubic-bezier(0.25,0.1,0.25,1)]`
818
- };
819
- const AccordionContext = createContext(void 0);
820
- function useAccordion() {
821
- const context = useContext(AccordionContext);
822
- if (!context) throw new Error("useAccordion must be used within a AccordionProvider");
823
- return context;
824
- }
825
- function Accordion({ value, defaultValue, onValueChange, animationPreset = "fade", transitionPreset = "outQuad", reduceMotion, variant = "default", className, multiple = false, ...props }) {
826
- const [accordionValue, setAccordionValue] = useState(value ?? defaultValue ?? []);
827
- const handleValueChange = (value$1, eventDetails) => {
828
- setAccordionValue(value$1);
829
- onValueChange?.(value$1, eventDetails);
830
- };
831
- return /* @__PURE__ */ jsx(AccordionContext.Provider, {
832
- value: {
833
- value: accordionValue,
834
- onValueChange: handleValueChange,
835
- animationPreset,
836
- transitionPreset,
837
- reduceMotion,
838
- variant
839
- },
840
- children: /* @__PURE__ */ jsx(Accordion$1.Root, {
841
- "data-slot": "accordion",
842
- value: accordionValue,
843
- onValueChange: handleValueChange,
844
- multiple,
845
- className: cn("w-full", variant === "default" && "flex flex-col rounded-2xl border outline-hidden", variant === "card" && "flex flex-col gap-1.5", variant === "swiss" && "rounded-2xl", className),
846
- ...props
847
- })
848
- });
849
- }
850
- const AccordionItemContext = createContext(void 0);
851
- function useAccordionItem() {
852
- const context = useContext(AccordionItemContext);
853
- if (!context) throw new Error("useAccordionItem must be used within a AccordionItemProvider");
854
- return context;
855
- }
856
- function AccordionItem({ value: itemValue, onOpenChange, className, ...rest }) {
857
- const { value, variant = "default" } = useAccordion();
858
- const [isOpen, setIsOpen] = useState(value?.includes(itemValue) ?? false);
859
- useEffect(() => {
860
- setIsOpen(value?.includes(itemValue) ?? false);
861
- }, [value, itemValue]);
862
- const handleItemOpenChange = (open, eventDetails) => {
863
- setIsOpen(open);
864
- onOpenChange?.(open, eventDetails);
865
- };
866
- return /* @__PURE__ */ jsx(AccordionItemContext.Provider, {
867
- value: {
868
- open: isOpen,
869
- onOpenChange: handleItemOpenChange,
870
- variant
871
- },
872
- children: /* @__PURE__ */ jsx(Accordion$1.Item, {
873
- "data-slot": "accordion-item",
874
- value: itemValue,
875
- onOpenChange: handleItemOpenChange,
876
- className: cn("w-full outline-hidden contain-layout", `[transition-property:border-radius,margin,border] duration-260 ease-[cubic-bezier(0.215,0.61,0.355,1)] will-change-[border-radius,margin,border]`, "focus-within:relative focus-within:z-2", variant === "default" && "border-border bg-card border-b first:rounded-t-2xl last:rounded-b-2xl last:border-b-0", variant === "card" && "rounded-[14px] border p-1", variant === "swiss" && [
877
- "bg-popover border-border/60 relative overflow-hidden border-x",
878
- "data-closed:border-border/60 data-closed:border-b",
879
- "first:border-border/60 first:rounded-t-2xl first:border-t",
880
- "last:border-border/60 last:rounded-b-2xl last:border-b",
881
- "data-open:border-primary/70 data-open:z-2 data-open:rounded-2xl data-open:border",
882
- "data-open:my-6 data-open:first:mt-0 data-open:last:mb-0",
883
- "has-[+_[data-slot='accordion-item'][data-open]]:rounded-b-2xl",
884
- "has-[+_[data-slot='accordion-item'][data-open]]:border-b!",
885
- "has-[+_[data-slot='accordion-item'][data-open]]:border-border/60",
886
- "data-open:[&+[data-slot='accordion-item']]:rounded-t-2xl",
887
- "data-open:[&+[data-slot='accordion-item'][data-closed]]:border-t",
888
- "data-open:[&+[data-slot='accordion-item']]:border-border/60",
889
- "data-closed:first:border-t",
890
- "data-closed:last:border-b"
891
- ], className),
892
- ...rest
893
- })
800
+ function Accordion(props) {
801
+ return /* @__PURE__ */ jsx(AccordionPrimitive.Root, {
802
+ "data-slot": "accordion",
803
+ ...props
894
804
  });
895
805
  }
896
- function AccordionHeader({ className, ...props }) {
897
- return /* @__PURE__ */ jsx(Accordion$1.Header, {
898
- "data-slot": "accordion-header",
899
- className: cn(className),
806
+ function AccordionItem({ className, ...props }) {
807
+ return /* @__PURE__ */ jsx(AccordionPrimitive.Item, {
808
+ className: cn("border-b last:border-b-0", className),
809
+ "data-slot": "accordion-item",
900
810
  ...props
901
811
  });
902
812
  }
903
- function AccordionTrigger({ className, icon, children, ...props }) {
904
- const { open, variant = "default" } = useAccordionItem();
905
- return /* @__PURE__ */ jsx(AccordionHeader, {
813
+ function AccordionTrigger({ className, children, ...props }) {
814
+ return /* @__PURE__ */ jsx(AccordionPrimitive.Header, {
906
815
  className: "flex",
907
- children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
816
+ children: /* @__PURE__ */ jsxs(AccordionPrimitive.Trigger, {
817
+ className: cn("flex flex-1 cursor-pointer items-start justify-between gap-4 py-3 text-left font-medium text-sm outline-none transition-all focus-visible:ring-[3px] focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-64 data-panel-open:*:data-[slot=accordion-indicator]:rotate-180 px-4 hover:bg-muted", className),
908
818
  "data-slot": "accordion-trigger",
909
- className: cn("hover:bg-muted bg-muted flex w-full cursor-pointer items-center px-4 py-3 text-left text-sm not-data-panel-open:bg-transparent", "[transition-property:background-color,border-radius] duration-200 ease-[cubic-bezier(0.215,0.61,0.355,1)] will-change-[background-color,border-radius]", `focus-visible:bg-accent not-data-panel-open:dark:hover:bg-accent dark:focus-visible:bg-accent focus-visible:outline-ring font-medium focus-visible:outline-2 data-disabled:pointer-events-none data-disabled:cursor-not-allowed data-disabled:opacity-50`, variant === "card" && [`not-data-panel-open:bg-secondary/80 data-panel-open:bg-secondary/80 rounded-lg data-panel-open:rounded-b-none`], className),
910
819
  ...props,
911
- children: [children, /* @__PURE__ */ jsx("span", {
912
- className: "ml-auto",
913
- children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("h-4 w-4 transition-transform duration-200", open ? "rotate-180" : "") })
820
+ children: [children, /* @__PURE__ */ jsx(ChevronDownIcon, {
821
+ className: "pointer-events-none size-4 shrink-0 translate-y-0.5 opacity-80 transition-transform duration-0 ease-in-out",
822
+ "data-slot": "accordion-indicator"
914
823
  })]
915
824
  })
916
825
  });
917
826
  }
918
- function AccordionPanel({ className, children, style, ...props }) {
919
- const { variant = "default", animationPreset = "fade", transitionPreset = "snappyOut", reduceMotion = false } = useAccordion();
920
- const cssAnimationConfig = useMemo(() => {
921
- if (reduceMotion) return cssAnimationPresets$1.none;
922
- if (animationPreset) return cssAnimationPresets$1[animationPreset];
923
- return cssAnimationPresets$1.fade;
924
- }, [animationPreset, reduceMotion]);
925
- const cssTransitionConfig = useMemo(() => {
926
- if (reduceMotion) return "";
927
- if (transitionPreset) return cssTransitionPresets$1[transitionPreset];
928
- return cssTransitionPresets$1.inOutExpo;
929
- }, [transitionPreset, reduceMotion]);
930
- return /* @__PURE__ */ jsx(Accordion$1.Panel, {
827
+ function AccordionPanel({ className, children, ...props }) {
828
+ return /* @__PURE__ */ jsx(AccordionPrimitive.Panel, {
829
+ className: "h-(--accordion-panel-height) overflow-hidden text-muted-foreground text-sm transition-[height] duration-0 ease-in-out data-ending-style:h-0 data-starting-style:h-0",
931
830
  "data-slot": "accordion-panel",
932
- className: cn("h-(--accordion-panel-height) overflow-hidden text-sm", cssAnimationConfig, cssTransitionConfig, className),
933
- style: {
934
- willChange: "height, opacity, transform",
935
- ...style
936
- },
937
831
  ...props,
938
832
  children: /* @__PURE__ */ jsx("div", {
939
- "data-slot": "accordion-panel-content",
940
- className: cn(variant === "default" ? "p-0" : "p-3 pl-4"),
833
+ className: cn("pt-0 pb-4", className),
941
834
  children
942
835
  })
943
836
  });
@@ -945,13 +838,13 @@ function AccordionPanel({ className, children, style, ...props }) {
945
838
 
946
839
  //#endregion
947
840
  //#region src/components/FieldGroups/index.tsx
948
- const usePuck$1 = createUsePuck();
841
+ const usePuck$2 = createUsePuck();
949
842
  const isSingleAccordion = (accordions) => {
950
843
  return "fields" in accordions && Array.isArray(accordions.fields);
951
844
  };
952
845
  const FieldGroups = ({ children }) => {
953
- const config = usePuck$1((s) => s.config);
954
- const selectedItem = usePuck$1((s) => s.selectedItem);
846
+ const config = usePuck$2((s) => s.config);
847
+ const selectedItem = usePuck$2((s) => s.selectedItem);
955
848
  const componentConfig = useMemo(() => {
956
849
  if (!selectedItem?.type) return null;
957
850
  return config.components?.[selectedItem.type] || null;
@@ -1131,223 +1024,50 @@ const FieldGroups = ({ children }) => {
1131
1024
  var FieldGroups_default = FieldGroups;
1132
1025
 
1133
1026
  //#endregion
1134
- //#region src/components/ui/tooltip.tsx
1135
- const cssAnimationPresets = {
1136
- none: "transition-none",
1137
- scale: [`[transition-property:scale,opacity]`, `data-starting-style:scale-80 data-starting-style:opacity-0 data-ending-style:opacity-0 data-ending-style:scale-80`],
1138
- fade: [`[transition-property:opacity,scale]`, `data-starting-style:scale-98 data-starting-style:opacity-0 data-ending-style:opacity-0 data-ending-style:scale-98`],
1139
- slideOutside: [
1140
- `[transition-property:translate,opacity]`,
1141
- `data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:translate-y-[10px] data-[side=bottom]:data-ending-style:translate-y-[10px] data-[side=bottom]:data-ending-style:opacity-0`,
1142
- `data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:translate-y-[-10px] data-[side=top]:data-ending-style:translate-y-[-10px] data-[side=top]:data-ending-style:opacity-0`,
1143
- `data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:translate-x-[-10px] data-[side=left]:data-ending-style:translate-x-[-10px] data-[side=left]:data-ending-style:opacity-0`,
1144
- `data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:translate-x-[10px] data-[side=right]:data-ending-style:translate-x-[10px] data-[side=right]:data-ending-style:opacity-0`,
1145
- `data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:translate-x-[-10px] data-[side=inline-start]:data-ending-style:translate-x-[-10px] data-[side=inline-start]:data-ending-style:opacity-0`,
1146
- `data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:translate-x-[10px] data-[side=inline-end]:data-ending-style:translate-x-[10px] data-[side=inline-end]:data-ending-style:opacity-0`
1147
- ],
1148
- slideInside: [
1149
- `[transition-property:translate,opacity]`,
1150
- `data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:translate-y-[-10px] data-[side=bottom]:data-ending-style:translate-y-[-10px] data-[side=bottom]:data-ending-style:opacity-0`,
1151
- `data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:translate-y-[10px] data-[side=top]:data-ending-style:translate-y-[10px] data-[side=top]:data-ending-style:opacity-0`,
1152
- `data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:translate-x-[10px] data-[side=left]:data-ending-style:translate-x-[10px] data-[side=left]:data-ending-style:opacity-0`,
1153
- `data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:translate-x-[-10px] data-[side=right]:data-ending-style:translate-x-[-10px] data-[side=right]:data-ending-style:opacity-0`,
1154
- `data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:translate-x-[10px] data-[side=inline-start]:data-ending-style:translate-x-[10px] data-[side=inline-start]:data-ending-style:opacity-0`,
1155
- `data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:translate-x-[-10px] data-[side=inline-end]:data-ending-style:translate-x-[-10px] data-[side=inline-end]:data-ending-style:opacity-0`
1156
- ],
1157
- wipe: [
1158
- `[transition-property:clip-path] [will-change:clip-path]`,
1159
- `[clip-path:inset(0_0_0_0_round_var(--radius))] [-webkit-clip-path:inset(0_0_0_0_round_var(--radius))]`,
1160
- `data-[side=bottom]:data-starting-style:[clip-path:inset(0_0_100%_0_round_var(--radius))] data-[side=bottom]:data-ending-style:[clip-path:inset(0_0_100%_0_round_var(--radius))]`,
1161
- `data-[side=top]:data-starting-style:[clip-path:inset(100%_0_0_0_round_var(--radius))] data-[side=top]:data-ending-style:[clip-path:inset(100%_0_0_0_round_var(--radius))]`,
1162
- `data-[side=left]:data-starting-style:[clip-path:inset(0_0_0_100%_round_var(--radius))] data-[side=left]:data-ending-style:[clip-path:inset(0_0_0_100%_round_var(--radius))]`,
1163
- `data-[side=right]:data-starting-style:[clip-path:inset(0_100%_0_0_round_var(--radius))] data-[side=right]:data-ending-style:[clip-path:inset(0_100%_0_0_round_var(--radius))]`,
1164
- `data-[side=inline-start]:data-starting-style:[clip-path:inset(0_0_0_100%_round_var(--radius))] data-[side=inline-start]:data-ending-style:[clip-path:inset(0_0_0_100%_round_var(--radius))]`,
1165
- `data-[side=inline-end]:data-starting-style:[clip-path:inset(0_100%_0_0_round_var(--radius))] data-[side=inline-end]:data-ending-style:[clip-path:inset(0_100%_0_0_round_var(--radius))]`
1166
- ],
1167
- wipeScale: [
1168
- `[transition-property:clip-path,scale] [will-change:clip-path,scale]`,
1169
- `[clip-path:inset(0_0_0_0_round_var(--radius))] [-webkit-clip-path:inset(0_0_0_0_round_var(--radius))]`,
1170
- `data-starting-style:scale-80 data-ending-style:scale-80`,
1171
- `data-[side=bottom]:data-starting-style:[clip-path:inset(0_0_100%_0_round_var(--radius))] data-[side=bottom]:data-ending-style:[clip-path:inset(0_0_100%_0_round_var(--radius))]`,
1172
- `data-[side=top]:data-starting-style:[clip-path:inset(100%_0_0_0_round_var(--radius))] data-[side=top]:data-ending-style:[clip-path:inset(100%_0_0_0_round_var(--radius))]`,
1173
- `data-[side=left]:data-starting-style:[clip-path:inset(0_0_0_100%_round_var(--radius))] data-[side=left]:data-ending-style:[clip-path:inset(0_0_0_100%_round_var(--radius))]`,
1174
- `data-[side=right]:data-starting-style:[clip-path:inset(0_100%_0_0_round_var(--radius))] data-[side=right]:data-ending-style:[clip-path:inset(0_100%_0_0_round_var(--radius))]`,
1175
- `data-[side=inline-start]:data-starting-style:[clip-path:inset(0_0_0_100%_round_var(--radius))] data-[side=inline-start]:data-ending-style:[clip-path:inset(0_0_0_100%_round_var(--radius))]`,
1176
- `data-[side=inline-end]:data-starting-style:[clip-path:inset(0_100%_0_0_round_var(--radius))] data-[side=inline-end]:data-ending-style:[clip-path:inset(0_100%_0_0_round_var(--radius))]`
1177
- ],
1178
- motion: [
1179
- `[transition-property:translate,scale,opacity,rotateX,rotateY,transform] [will-change:translate,scale,opacity,rotateX,rotateY,transform]`,
1180
- `[transform:perspective(1000px)]`,
1181
- `data-[side=bottom]:data-starting-style:translate-y-[7px] data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:scale-[0.26] data-[side=bottom]:data-starting-style:rotate-x-[70deg] data-[side=bottom]:data-ending-style:translate-y-[7px] data-[side=bottom]:data-ending-style:opacity-0 data-[side=bottom]:data-ending-style:scale-[0.26] data-[side=bottom]:data-ending-style:rotate-x-[70deg]`,
1182
- `data-[side=top]:data-starting-style:translate-y-[7px] data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:scale-[0.26] data-[side=top]:data-starting-style:rotate-x-[70deg] data-[side=top]:data-ending-style:translate-y-[7px] data-[side=top]:data-ending-style:opacity-0 data-[side=top]:data-ending-style:scale-[0.26] data-[side=top]:data-ending-style:rotate-x-[70deg]`,
1183
- `data-[side=left]:data-starting-style:translate-x-[-7px] data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:scale-[0.26] data-[side=left]:data-starting-style:rotate-y-[-40deg] data-[side=left]:data-ending-style:translate-x-[-7px] data-[side=left]:data-ending-style:opacity-0 data-[side=left]:data-ending-style:scale-[0.26] data-[side=left]:data-ending-style:rotate-y-[-40deg]`,
1184
- `data-[side=right]:data-starting-style:translate-x-[7px] data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:scale-[0.26] data-[side=right]:data-starting-style:rotate-y-[40deg] data-[side=right]:data-ending-style:translate-x-[7px] data-[side=right]:data-ending-style:opacity-0 data-[side=right]:data-ending-style:scale-[0.26] data-[side=right]:data-ending-style:rotate-y-[40deg]`,
1185
- `data-[side=inline-start]:data-starting-style:translate-x-[-7px] data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:scale-[0.26] data-[side=inline-start]:data-starting-style:rotate-y-[-40deg] data-[side=inline-start]:data-ending-style:translate-x-[-7px] data-[side=inline-start]:data-ending-style:opacity-0 data-[side=inline-start]:data-ending-style:scale-[0.26] data-[side=inline-start]:data-ending-style:rotate-y-[-40deg]`,
1186
- `data-[side=inline-end]:data-starting-style:translate-x-[7px] data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:scale-[0.26] data-[side=inline-end]:data-starting-style:rotate-y-[40deg] data-[side=inline-end]:data-ending-style:translate-x-[7px] data-[side=inline-end]:data-ending-style:opacity-0 data-[side=inline-end]:data-ending-style:scale-[0.26] data-[side=inline-end]:data-ending-style:rotate-y-[40deg]`
1187
- ],
1188
- motionBlur: [
1189
- `[transition-property:translate,scale,opacity,rotateX,rotateY,transform,filter] [will-change:translate,scale,opacity,rotateX,rotateY,transform,filter]`,
1190
- `[transform:perspective(1000px)]`,
1191
- `data-starting-style:blur-[9px] data-ending-style:blur-[9px]`,
1192
- `data-[side=bottom]:data-starting-style:translate-y-[7px] data-[side=bottom]:data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:scale-[0.26] data-[side=bottom]:data-starting-style:rotate-x-[70deg] data-[side=bottom]:data-ending-style:translate-y-[7px] data-[side=bottom]:data-ending-style:opacity-0 data-[side=bottom]:data-ending-style:scale-[0.26] data-[side=bottom]:data-ending-style:rotate-x-[70deg]`,
1193
- `data-[side=top]:data-starting-style:translate-y-[7px] data-[side=top]:data-starting-style:opacity-0 data-[side=top]:data-starting-style:scale-[0.26] data-[side=top]:data-starting-style:rotate-x-[70deg] data-[side=top]:data-ending-style:translate-y-[7px] data-[side=top]:data-ending-style:opacity-0 data-[side=top]:data-ending-style:scale-[0.26] data-[side=top]:data-ending-style:rotate-x-[70deg]`,
1194
- `data-[side=left]:data-starting-style:translate-x-[-7px] data-[side=left]:data-starting-style:opacity-0 data-[side=left]:data-starting-style:scale-[0.26] data-[side=left]:data-starting-style:rotate-y-[-40deg] data-[side=left]:data-ending-style:translate-x-[-7px] data-[side=left]:data-ending-style:opacity-0 data-[side=left]:data-ending-style:scale-[0.26] data-[side=left]:data-ending-style:rotate-y-[-40deg]`,
1195
- `data-[side=right]:data-starting-style:translate-x-[7px] data-[side=right]:data-starting-style:opacity-0 data-[side=right]:data-starting-style:scale-[0.26] data-[side=right]:data-starting-style:rotate-y-[40deg] data-[side=right]:data-ending-style:translate-x-[7px] data-[side=right]:data-ending-style:opacity-0 data-[side=right]:data-ending-style:scale-[0.26] data-[side=right]:data-ending-style:rotate-y-[40deg]`,
1196
- `data-[side=inline-start]:data-starting-style:translate-x-[-7px] data-[side=inline-start]:data-starting-style:opacity-0 data-[side=inline-start]:data-starting-style:scale-[0.26] data-[side=inline-start]:data-starting-style:rotate-y-[-40deg] data-[side=inline-start]:data-ending-style:translate-x-[-7px] data-[side=inline-start]:data-ending-style:opacity-0 data-[side=inline-start]:data-ending-style:scale-[0.26] data-[side=inline-start]:data-ending-style:rotate-y-[-40deg]`,
1197
- `data-[side=inline-end]:data-starting-style:translate-x-[7px] data-[side=inline-end]:data-starting-style:opacity-0 data-[side=inline-end]:data-starting-style:scale-[0.26] data-[side=inline-end]:data-starting-style:rotate-y-[40deg] data-[side=inline-end]:data-ending-style:translate-x-[7px] data-[side=inline-end]:data-ending-style:opacity-0 data-[side=inline-end]:data-ending-style:scale-[0.26] data-[side=inline-end]:data-ending-style:rotate-y-[40deg]`
1198
- ]
1199
- };
1200
- const cssTransitionPresets = {
1201
- inExpo: `duration-[0.25s] ease-[cubic-bezier(0.95,0.05,0.795,0.035)]`,
1202
- outExpo: `duration-[0.25s] ease-[cubic-bezier(0.19,1,0.22,1)]`,
1203
- inOutExpo: `duration-[0.25s] ease-[cubic-bezier(1,0,0,1)]`,
1204
- anticipate: `duration-[0.25s] ease-[cubic-bezier(1,-0.4,0.35,0.95)]`,
1205
- quickOut: `duration-[0.25s] ease-out`,
1206
- overshootOut: `duration-[0.25s] ease-[cubic-bezier(0.175,0.885,0.32,1.275)]`,
1207
- swiftOut: `duration-[0.25s] ease-[cubic-bezier(0.175,0.885,0.32,1.1)]`,
1208
- snappyOut: `duration-[0.25s] ease-[cubic-bezier(0.19,1,0.22,1)]`,
1209
- in: `duration-[0.25s] ease-[cubic-bezier(0.42,0,1,1)]`,
1210
- out: `duration-[0.25s] ease-[cubic-bezier(0,0,0.58,1)]`,
1211
- inOut: `duration-[0.25s] ease-[cubic-bezier(0.42,0,0.58,1)]`,
1212
- outIn: `duration-[0.25s] ease-[cubic-bezier(0.1,0.7,0.9,0.5)]`,
1213
- inQuad: `duration-[0.25s] ease-[cubic-bezier(0.55,0.085,0.68,0.53)]`,
1214
- outQuad: `duration-[0.25s] ease-[cubic-bezier(0.25,0.46,0.45,0.94)]`,
1215
- inOutQuad: `duration-[0.32s] ease-[cubic-bezier(0.455,0.03,0.515,0.955)]`,
1216
- inCubic: `duration-[0.25s] ease-[cubic-bezier(0.55,0.055,0.675,0.19)]`,
1217
- outCubic: `duration-[0.25s] ease-[cubic-bezier(0.215,0.61,0.355,1)]`,
1218
- inOutCubic: `duration-[0.25s] ease-[cubic-bezier(0.645,0.045,0.355,1)]`,
1219
- inQuart: `duration-[0.25s] ease-[cubic-bezier(0.895,0.03,0.685,0.22)]`,
1220
- outQuart: `duration-[0.25s] ease-[cubic-bezier(0.165,0.84,0.44,1)]`,
1221
- inOutQuart: `duration-[0.25s] ease-[cubic-bezier(0.77,0,0.175,1)]`,
1222
- inQuint: `duration-[0.25s] ease-[cubic-bezier(0.755,0.05,0.855,0.06)]`,
1223
- outQuint: `duration-[0.25s] ease-[cubic-bezier(0.23,1,0.32,1)]`,
1224
- inOutQuint: `duration-[0.25s] ease-[cubic-bezier(0.86,0,0.07,1)]`,
1225
- inCirc: `duration-[0.25s] ease-[cubic-bezier(0.6,0.04,0.98,0.335)]`,
1226
- outCirc: `duration-[0.25s] ease-[cubic-bezier(0.075,0.82,0.165,1)]`,
1227
- inOutCirc: `duration-[0.25s] ease-[cubic-bezier(0.785,0.135,0.15,0.86)]`,
1228
- inOutBase: `duration-[0.25s] ease-[cubic-bezier(0.25,0.1,0.25,1)]`,
1229
- none: `duration-0 ease-none`
1230
- };
1231
- function TooltipProvider({ delay = 300, ...props }) {
1232
- return /* @__PURE__ */ jsx(Tooltip$1.Provider, {
1233
- "data-slot": "tooltip-provider",
1234
- delay,
1235
- ...props
1236
- });
1237
- }
1238
- function Tooltip({ ...props }) {
1239
- return /* @__PURE__ */ jsx(Tooltip$1.Root, {
1240
- "data-slot": "tooltip",
1241
- ...props
1242
- });
1243
- }
1244
- function TooltipTrigger(props) {
1245
- return /* @__PURE__ */ jsx(Tooltip$1.Trigger, {
1246
- "data-slot": "tooltip-trigger",
1247
- ...props
1248
- });
1249
- }
1250
- function TooltipPortal(props) {
1251
- return /* @__PURE__ */ jsx(Tooltip$1.Portal, {
1252
- "data-slot": "tooltip-portal",
1253
- ...props
1254
- });
1255
- }
1256
- function TooltipPositioner({ className, side = "top", ...rest }) {
1257
- return /* @__PURE__ */ jsx(TooltipPortal, { children: /* @__PURE__ */ jsx(Tooltip$1.Positioner, {
1258
- side,
1259
- "data-slot": "tooltip-positioner",
1260
- className: cn("z-100", (side === "inline-end" || side === "inline-start") && "**:data-[slot=tooltip-arrow]:hidden", className),
1261
- ...rest
1262
- }) });
1263
- }
1264
- function TooltipPopup({ className, animationPreset = "scale", transitionPreset = "outQuint", reduceMotion = false, showArrow = false, side = "top", sideOffset = 4, align = "center", alignOffset = 0, ...rest }) {
1265
- const cssAnimationConfig = useMemo(() => {
1266
- if (reduceMotion) return "none";
1267
- if (animationPreset) return cssAnimationPresets[animationPreset];
1268
- return cssAnimationPresets.scale;
1269
- }, [
1270
- animationPreset,
1271
- reduceMotion,
1272
- side
1273
- ]);
1274
- const cssTransitionConfig = useMemo(() => {
1275
- if (reduceMotion) return "none";
1276
- if (transitionPreset) return cssTransitionPresets[transitionPreset];
1277
- return cssTransitionPresets.snappyOut;
1278
- }, [
1279
- transitionPreset,
1280
- reduceMotion,
1281
- side
1282
- ]);
1283
- return /* @__PURE__ */ jsx(TooltipPositioner, {
1284
- side,
1285
- sideOffset,
1286
- align,
1287
- alignOffset,
1288
- children: /* @__PURE__ */ jsx(Tooltip$1.Popup, {
1289
- "data-slot": "tooltip-popup",
1290
- className: cn("[--radius:10px]", "bg-popover border-border pointer-events-auto w-fit origin-(--transform-origin) rounded-(--radius) border px-2 py-1 text-[13px] text-balance shadow-xs data-instant:duration-0!", className, cssAnimationConfig, cssTransitionConfig, showArrow && [
1291
- `before: before:bg-popover z-[-1] before:absolute before:h-2 before:w-2 before:rotate-45 before:content-['']`,
1292
- side === "top" && `before:border-border before:-bottom-[4.7px] before:left-1/2 before:-translate-x-1/2 before:border-r before:border-b`,
1293
- side === "right" && `before:border-border before:top-1/2 before:-left-[4.07px] before:-translate-y-1/2 before:border-b before:border-l`,
1294
- side === "bottom" && `before:border-border before:-top-[4.7px] before:left-1/2 before:-translate-x-1/2 before:border-t before:border-l`,
1295
- side === "left" && `before:border-border before:top-1/2 before:-right-[4.07px] before:-translate-y-1/2 before:border-t before:border-r`,
1296
- side === "inline-start" && `before:border-border before:top-1/2 before:-right-[4.07px] before:-translate-y-1/2 before:border-t before:border-r`,
1297
- side === "inline-end" && `before:border-border before:top-1/2 before:-left-[4.07px] before:-translate-y-1/2 before:border-b before:border-l`
1298
- ]),
1299
- ...rest
1300
- })
1301
- });
1302
- }
1303
-
1304
- //#endregion
1305
- //#region src/components/DrawerItem/index.tsx
1306
- const usePuck = createUsePuck();
1307
- const DrawerItem = ({ name, icon }) => {
1308
- const componentConfig = usePuck(useCallback((state) => state.config, [])).components?.[name];
1309
- const iconOrImage = icon || componentConfig?.metadata?.icon;
1310
- const imageUrl = componentConfig?.metadata?.image;
1311
- const description = componentConfig?.metadata?.description;
1312
- const label = componentConfig?.label || name;
1313
- const displayIcon = iconOrImage || /* @__PURE__ */ jsx(BoxIcon, { size: 16 });
1314
- const hasTooltipContent = imageUrl || description;
1315
- const drawerContent = /* @__PURE__ */ jsxs("div", {
1316
- className: "hover:bg-muted group flex cursor-grab items-center justify-between gap-2 rounded-md bg-white p-0.5 transition-colors",
1317
- children: [/* @__PURE__ */ jsxs("div", {
1318
- className: "flex items-center gap-2 truncate",
1319
- children: [/* @__PURE__ */ jsx("div", {
1320
- className: "border-border group-hover:border-muted rounded-sm border bg-white p-3",
1321
- children: displayIcon
1322
- }), /* @__PURE__ */ jsx("span", {
1323
- className: "truncate text-sm font-medium",
1324
- children: label
1325
- })]
1326
- }), /* @__PURE__ */ jsx("div", {
1327
- className: "text-foreground h-full flex-none rounded-sm bg-white px-1 py-3",
1328
- children: /* @__PURE__ */ jsx(GripVerticalIcon, { size: 16 })
1329
- })]
1330
- });
1331
- if (!hasTooltipContent) return drawerContent;
1332
- return /* @__PURE__ */ jsx(TooltipProvider, {
1333
- delay: 200,
1334
- children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
1335
- className: "w-full",
1336
- children: drawerContent
1337
- }), /* @__PURE__ */ jsxs(TooltipPopup, {
1338
- side: "right",
1339
- sideOffset: 8,
1340
- className: "w-64 p-2",
1341
- children: [imageUrl && /* @__PURE__ */ jsx("img", {
1342
- src: imageUrl,
1343
- alt: name,
1344
- className: "h-auto w-full rounded-sm object-contain"
1345
- }), description && /* @__PURE__ */ jsx("p", {
1346
- className: "text-muted-foreground mt-2 text-sm",
1347
- children: description
1348
- })]
1349
- })] })
1350
- });
1027
+ //#region src/components/DrawerItem/index.tsx
1028
+ const usePuck$1 = createUsePuck();
1029
+ const DrawerItem = ({ name, icon }) => {
1030
+ const componentConfig = usePuck$1(useCallback((state) => state.config, [])).components?.[name];
1031
+ const iconOrImage = icon || componentConfig?.metadata?.icon;
1032
+ const imageUrl = componentConfig?.metadata?.image;
1033
+ const description = componentConfig?.metadata?.description;
1034
+ const label = componentConfig?.label || name;
1035
+ const displayIcon = iconOrImage || /* @__PURE__ */ jsx(BoxIcon, { size: 16 });
1036
+ const hasTooltipContent = imageUrl || description;
1037
+ const drawerContent = /* @__PURE__ */ jsxs("div", {
1038
+ className: "hover:bg-muted group flex cursor-grab items-center justify-between gap-2 rounded-md bg-white p-0.5 transition-colors",
1039
+ children: [/* @__PURE__ */ jsxs("div", {
1040
+ className: "flex items-center gap-2 truncate",
1041
+ children: [/* @__PURE__ */ jsx("div", {
1042
+ className: "border-border group-hover:border-muted rounded-sm border bg-white p-3",
1043
+ children: displayIcon
1044
+ }), /* @__PURE__ */ jsx("span", {
1045
+ className: "truncate text-sm font-medium",
1046
+ children: label
1047
+ })]
1048
+ }), /* @__PURE__ */ jsx("div", {
1049
+ className: "text-foreground h-full flex-none rounded-sm bg-white px-1 py-3",
1050
+ children: /* @__PURE__ */ jsx(GripVerticalIcon, { size: 16 })
1051
+ })]
1052
+ });
1053
+ if (!hasTooltipContent) return drawerContent;
1054
+ return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
1055
+ delay: 200,
1056
+ className: "w-full",
1057
+ children: drawerContent
1058
+ }), /* @__PURE__ */ jsxs(TooltipPopup, {
1059
+ side: "right",
1060
+ sideOffset: 8,
1061
+ className: "w-64 p-2",
1062
+ children: [imageUrl && /* @__PURE__ */ jsx("img", {
1063
+ src: imageUrl,
1064
+ alt: name,
1065
+ className: "h-auto w-full rounded-sm object-contain"
1066
+ }), description && /* @__PURE__ */ jsx("p", {
1067
+ className: "text-muted-foreground mt-2 text-sm",
1068
+ children: description
1069
+ })]
1070
+ })] }) });
1351
1071
  };
1352
1072
  var DrawerItem_default = DrawerItem;
1353
1073
 
@@ -1359,7 +1079,10 @@ const createPuckOverridesPlugin = () => {
1359
1079
  drawer: ({ children }) => /* @__PURE__ */ jsx(Fragment, { children }),
1360
1080
  drawerItem: DrawerItem_default,
1361
1081
  fields: FieldGroups_default,
1362
- fieldLabel: ({ children, label }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Label_default, { label }), children] }),
1082
+ fieldLabel: ({ children, label, field, tooltip }) => /* @__PURE__ */ jsxs(Fragment, { children: [label && /* @__PURE__ */ jsx(Label_default, {
1083
+ label,
1084
+ tooltip
1085
+ }), children] }),
1363
1086
  fieldTypes: {
1364
1087
  checkbox: Checkbox_default,
1365
1088
  numberUnit: NumberUnit_default,
@@ -1372,110 +1095,6 @@ const createPuckOverridesPlugin = () => {
1372
1095
  };
1373
1096
  var plugin_default = createPuckOverridesPlugin;
1374
1097
 
1375
- //#endregion
1376
- //#region src/components/ui/button.tsx
1377
- const buttonVariants = cva("[&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 sm:text-sm [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", {
1378
- defaultVariants: {
1379
- size: "default",
1380
- variant: "default"
1381
- },
1382
- variants: {
1383
- size: {
1384
- default: "h-9 px-[calc(--spacing(3)-1px)] sm:h-8",
1385
- icon: "size-9 sm:size-8",
1386
- "icon-lg": "size-10 sm:size-9",
1387
- "icon-sm": "size-8 sm:size-7",
1388
- "icon-xl": "size-11 sm:size-10 [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5",
1389
- "icon-xs": "size-7 rounded-md before:rounded-[calc(var(--radius-md)-1px)] sm:size-6 not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-4 sm:not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-3.5",
1390
- lg: "h-10 px-[calc(--spacing(3.5)-1px)] sm:h-9",
1391
- sm: "h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:h-7",
1392
- xl: "h-11 px-[calc(--spacing(4)-1px)] text-lg sm:h-10 sm:text-base [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5",
1393
- xs: "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-sm before:rounded-[calc(var(--radius-md)-1px)] sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5"
1394
- },
1395
- variant: {
1396
- default: "not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-primary bg-primary text-primary-foreground shadow-primary/24 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-primary/90",
1397
- destructive: "not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-destructive bg-destructive text-white shadow-destructive/24 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-destructive/90",
1398
- "destructive-outline": "border-input bg-transparent not-dark:bg-clip-padding text-destructive-foreground not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:border-destructive/32 [:hover,[data-pressed]]:bg-destructive/4",
1399
- ghost: "border-transparent data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent",
1400
- link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",
1401
- outline: "border-input bg-background not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-accent/50 dark:[:hover,[data-pressed]]:bg-input/64",
1402
- primary: "border-transparent from-primary-600 to-primary-500 hover:from-primary-500 hover:to-primary-600 bg-linear-to-t text-white inset-shadow-[0_2px_0_0] inset-shadow-white/25 hover:text-white",
1403
- secondary: "border-transparent bg-secondary text-secondary-foreground [:active,[data-pressed]]:bg-secondary/80 [:hover,[data-pressed]]:bg-secondary/90"
1404
- }
1405
- }
1406
- });
1407
- function Button({ className, variant, size, render, ...props }) {
1408
- const typeValue = render ? void 0 : "button";
1409
- return useRender({
1410
- defaultTagName: "button",
1411
- props: mergeProps({
1412
- className: cn(buttonVariants({
1413
- className,
1414
- size,
1415
- variant
1416
- })),
1417
- "data-slot": "button",
1418
- type: typeValue
1419
- }, props),
1420
- render
1421
- });
1422
- }
1423
-
1424
- //#endregion
1425
- //#region src/components/ui/input-group.tsx
1426
- function InputGroup({ className, ...props }) {
1427
- return /* @__PURE__ */ jsx("div", {
1428
- className: cn("relative inline-flex w-full min-w-0 items-center rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_1px_--theme(--color-black/6%)] has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/64 has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/16 has-[textarea]:h-auto has-data-[align=block-end]:h-auto has-data-[align=block-start]:h-auto has-data-[align=block-end]:flex-col has-data-[align=block-start]:flex-col has-[input:focus-visible,textarea:focus-visible]:border-ring has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/36 has-[input:disabled,textarea:disabled]:opacity-64 has-[input:disabled,textarea:disabled,input:focus-visible,textarea:focus-visible,input[aria-invalid],textarea[aria-invalid]]:shadow-none has-[input:focus-visible,textarea:focus-visible]:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/24 dark:not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_-1px_--theme(--color-white/6%)] has-data-[align=inline-start]:**:[[data-size=sm]_input]:ps-1.5 has-data-[align=inline-end]:**:[[data-size=sm]_input]:pe-1.5 *:[[data-slot=input-control],[data-slot=textarea-control]]:contents *:[[data-slot=input-control],[data-slot=textarea-control]]:before:hidden has-[[data-align=block-start],[data-align=block-end]]:**:[input]:h-auto has-data-[align=inline-start]:**:[input]:ps-2 has-data-[align=inline-end]:**:[input]:pe-2 has-data-[align=block-end]:**:[input]:pt-1.5 has-data-[align=block-start]:**:[input]:pb-1.5 **:[textarea]:min-h-20.5 **:[textarea]:resize-none **:[textarea]:py-[calc(--spacing(3)-1px)] **:[textarea]:max-sm:min-h-23.5 **:[textarea_button]:rounded-[calc(var(--radius-md)-1px)]", className),
1429
- "data-slot": "input-group",
1430
- role: "group",
1431
- ...props
1432
- });
1433
- }
1434
- const inputGroupAddonVariants = cva("[&_svg]:-mx-0.5 flex h-auto cursor-text select-none items-center justify-center gap-2 leading-none [&>kbd]:rounded-[calc(var(--radius)-5px)] in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 not-has-[button]:**:[svg:not([class*='opacity-'])]:opacity-80", {
1435
- defaultVariants: { align: "inline-start" },
1436
- variants: { align: {
1437
- "block-end": "order-last w-full justify-start px-[calc(--spacing(3)-1px)] pb-[calc(--spacing(3)-1px)] [.border-t]:pt-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]",
1438
- "block-start": "order-first w-full justify-start px-[calc(--spacing(3)-1px)] pt-[calc(--spacing(3)-1px)] [.border-b]:pb-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]",
1439
- "inline-end": "has-[>:last-child[data-slot=badge]]:-me-1.5 has-[>button]:-me-2 order-last pe-[calc(--spacing(3)-1px)] has-[>kbd:last-child]:me-[-0.35rem] [[data-size=sm]+&]:pe-[calc(--spacing(2.5)-1px)]",
1440
- "inline-start": "has-[>:last-child[data-slot=badge]]:-ms-1.5 has-[>button]:-ms-2 order-first ps-[calc(--spacing(3)-1px)] has-[>kbd:last-child]:ms-[-0.35rem] [[data-size=sm]+&]:ps-[calc(--spacing(2.5)-1px)]"
1441
- } }
1442
- });
1443
- function InputGroupAddon({ className, align = "inline-start", ...props }) {
1444
- return /* @__PURE__ */ jsx("div", {
1445
- className: cn(inputGroupAddonVariants({ align }), className),
1446
- "data-align": align,
1447
- "data-slot": "input-group-addon",
1448
- onMouseDown: (e) => {
1449
- if (e.target.closest("button, a, input, select, textarea, [role='button'], [role='combobox'], [role='listbox'], [data-slot='select-trigger']")) return;
1450
- e.preventDefault();
1451
- const parent = e.currentTarget.parentElement;
1452
- const input = parent?.querySelector("input, textarea");
1453
- if (input && !parent?.querySelector("input:focus, textarea:focus")) input.focus();
1454
- },
1455
- ...props
1456
- });
1457
- }
1458
- function InputGroupText({ className, ...props }) {
1459
- return /* @__PURE__ */ jsx("span", {
1460
- className: cn("[&_svg]:-mx-0.5 line-clamp-1 flex items-center gap-2 text-muted-foreground leading-none in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none", className),
1461
- ...props
1462
- });
1463
- }
1464
- function InputGroupInput({ className, ...props }) {
1465
- return /* @__PURE__ */ jsx(Input, {
1466
- className,
1467
- unstyled: true,
1468
- ...props
1469
- });
1470
- }
1471
- function InputGroupTextarea({ className, ...props }) {
1472
- return /* @__PURE__ */ jsx(Textarea, {
1473
- className,
1474
- unstyled: true,
1475
- ...props
1476
- });
1477
- }
1478
-
1479
1098
  //#endregion
1480
1099
  //#region src/components/ui/popover.tsx
1481
1100
  const PopoverCreateHandle = Popover$1.createHandle;
@@ -1499,7 +1118,7 @@ function PopoverPopup({ children, className, side = "bottom", align = "center",
1499
1118
  "data-slot": "popover-popup",
1500
1119
  ...props,
1501
1120
  children: /* @__PURE__ */ jsx(Popover$1.Viewport, {
1502
- className: cn("relative size-full max-h-(--available-height) overflow-clip px-(--viewport-inline-padding) py-4 outline-none [--viewport-inline-padding:--spacing(4)] data-instant:transition-none **:data-current:data-ending-style:opacity-0 **:data-current:data-starting-style:opacity-0 **:data-previous:data-ending-style:opacity-0 **:data-previous:data-starting-style:opacity-0 **:data-current:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-previous:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-current:opacity-100 **:data-previous:opacity-100 **:data-current:transition-opacity **:data-previous:transition-opacity", tooltipStyle ? "py-1 [--viewport-inline-padding:--spacing(2)]" : "not-data-transitioning:overflow-y-auto"),
1121
+ className: cn("relative size-full max-h-(--available-height) overflow-clip px-(--viewport-inline-padding) py-3 outline-none [--viewport-inline-padding:--spacing(3)] data-instant:transition-none **:data-current:data-ending-style:opacity-0 **:data-current:data-starting-style:opacity-0 **:data-previous:data-ending-style:opacity-0 **:data-previous:data-starting-style:opacity-0 **:data-current:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-previous:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-current:opacity-100 **:data-previous:opacity-100 **:data-current:transition-opacity **:data-previous:transition-opacity", tooltipStyle ? "py-1 [--viewport-inline-padding:--spacing(2)]" : "not-data-transitioning:overflow-y-auto"),
1503
1122
  "data-slot": "popover-viewport",
1504
1123
  children
1505
1124
  })
@@ -1528,168 +1147,70 @@ function PopoverDescription({ className, ...props }) {
1528
1147
  }
1529
1148
 
1530
1149
  //#endregion
1531
- //#region src/components/RichTextMenuLink/index.tsx
1532
- const richTextMenuLinkSelector = ({ editor }) => ({
1533
- isLink: editor?.isActive("link") ?? false,
1534
- canLink: editor?.can().chain().focus().toggleLink({ href: "" }).run() ?? false
1535
- });
1536
- /**
1537
- * Pre-configured tiptap Link extension ready to use in Puck's richtext field.
1538
- * Add this to `tiptap.extensions` in your field config.
1539
- */
1540
- const richTextMenuLinkExtension = TiptapLink.configure({
1541
- openOnClick: false,
1542
- autolink: true,
1543
- defaultProtocol: "https",
1544
- HTMLAttributes: { rel: "noopener noreferrer nofollow" }
1545
- });
1546
- function RichTextMenuLink({ editor, editorState, ...props }) {
1547
- const [url, setUrl] = useState("");
1548
- const [open, setOpen] = useState(false);
1549
- const inputRef = useRef(null);
1550
- const selectionRef = useRef(null);
1551
- useEffect(() => {
1552
- if (open && editor) {
1553
- setUrl(editor.getAttributes("link").href ?? "");
1554
- setTimeout(() => inputRef.current?.querySelector?.("input")?.focus(), 50);
1150
+ //#region src/components/ui/badge.tsx
1151
+ const badgeVariants = cva("relative inline-flex shrink-0 items-center justify-center gap-1 whitespace-nowrap rounded-md border border-transparent font-medium outline-none transition-shadow focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-3.5 sm:[&_svg:not([class*='size-'])]:size-3 [&_svg]:pointer-events-none [&_svg]:shrink-0 [button&,a&]:cursor-pointer [button&,a&]:pointer-coarse:after:absolute [button&,a&]:pointer-coarse:after:size-full [button&,a&]:pointer-coarse:after:min-h-11 [button&,a&]:pointer-coarse:after:min-w-11", {
1152
+ defaultVariants: {
1153
+ size: "default",
1154
+ variant: "default"
1155
+ },
1156
+ variants: {
1157
+ size: {
1158
+ default: "h-5.5 min-w-5.5 px-[calc(--spacing(1)-1px)] text-sm sm:h-4.5 sm:min-w-4.5 sm:text-xs",
1159
+ lg: "h-6.5 min-w-6.5 px-[calc(--spacing(1.5)-1px)] text-base sm:h-5.5 sm:min-w-5.5 sm:text-sm",
1160
+ sm: "h-5 min-w-5 rounded-[.25rem] px-[calc(--spacing(1)-1px)] text-xs sm:h-4 sm:min-w-4 sm:text-[.625rem]"
1161
+ },
1162
+ variant: {
1163
+ default: "bg-primary text-primary-foreground [button&,a&]:hover:bg-primary/90",
1164
+ destructive: "bg-destructive text-white [button&,a&]:hover:bg-destructive/90",
1165
+ error: "bg-destructive/8 text-destructive-foreground dark:bg-destructive/16",
1166
+ info: "bg-info/8 text-info-foreground dark:bg-info/16",
1167
+ outline: "border-input bg-background text-foreground dark:bg-input/32 [button&,a&]:hover:bg-accent/50 dark:[button&,a&]:hover:bg-input/48",
1168
+ secondary: "bg-secondary text-secondary-foreground [button&,a&]:hover:bg-secondary/90",
1169
+ success: "bg-success/8 text-success-foreground dark:bg-success/16",
1170
+ warning: "bg-warning/8 text-warning-foreground dark:bg-warning/16"
1555
1171
  }
1556
- }, [open, editor]);
1557
- const handleSetLink = useCallback(() => {
1558
- if (!editor) return;
1559
- const trimmedUrl = url.trim();
1560
- const sel = selectionRef.current;
1561
- if (trimmedUrl === "") {
1562
- const chain = editor.chain().focus();
1563
- if (sel) chain.setTextSelection(sel);
1564
- chain.extendMarkRange("link").unsetLink().run();
1565
- } else {
1566
- const chain = editor.chain().focus();
1567
- if (sel) chain.setTextSelection(sel);
1568
- chain.extendMarkRange("link").setLink({ href: trimmedUrl }).run();
1569
- }
1570
- setOpen(false);
1571
- }, [editor, url]);
1572
- const handleUnsetLink = useCallback(() => {
1573
- if (!editor) return;
1574
- const sel = selectionRef.current;
1575
- const chain = editor.chain().focus();
1576
- if (sel) chain.setTextSelection(sel);
1577
- chain.extendMarkRange("link").unsetLink().run();
1578
- setOpen(false);
1579
- }, [editor]);
1580
- const isActive = editorState?.isLink ?? false;
1581
- return /* @__PURE__ */ jsx("div", {
1582
- ...props,
1583
- children: /* @__PURE__ */ jsxs(Popover, {
1584
- open,
1585
- onOpenChange: setOpen,
1586
- children: [/* @__PURE__ */ jsx(PopoverTrigger, {
1587
- render: /* @__PURE__ */ jsx("button", {
1588
- type: "button",
1589
- title: "Link",
1590
- onPointerDown: () => {
1591
- if (editor) {
1592
- const { from, to } = editor.state.selection;
1593
- selectionRef.current = {
1594
- from,
1595
- to
1596
- };
1597
- }
1598
- },
1599
- onClick: (e) => {
1600
- e.stopPropagation();
1601
- },
1602
- className: "inline-flex border h-full aspect-square cursor-pointer border-stone-200 bg-white items-center p-1.5 text-black hover:border-stone-300 hover:bg-stone-50 justify-center rounded-md transition-colors hover:bg-primary-500 hover:text-primary-500" + (isActive ? " bg-accent text-accent-foreground" : "")
1603
- }),
1604
- children: /* @__PURE__ */ jsx(Link, { className: "size-4" })
1605
- }), /* @__PURE__ */ jsx(PopoverPopup, {
1606
- side: "bottom",
1607
- align: "start",
1608
- sideOffset: 8,
1609
- className: "w-72",
1610
- children: /* @__PURE__ */ jsx("div", {
1611
- "data-puck-rte-menu": true,
1612
- children: /* @__PURE__ */ jsxs("div", {
1613
- className: "flex flex-col gap-2",
1614
- children: [/* @__PURE__ */ jsxs("div", {
1615
- className: "flex items-center gap-1.5",
1616
- children: [/* @__PURE__ */ jsxs(InputGroup, {
1617
- ref: inputRef,
1618
- className: "flex-1",
1619
- children: [/* @__PURE__ */ jsx(InputGroupInput, {
1620
- "aria-label": "Link URL",
1621
- onChange: (e) => setUrl(e.target.value),
1622
- onKeyDown: (e) => {
1623
- if (e.key === "Enter") {
1624
- e.preventDefault();
1625
- handleSetLink();
1626
- }
1627
- },
1628
- placeholder: "https://example.com",
1629
- type: "text",
1630
- value: url
1631
- }), url && /* @__PURE__ */ jsx(InputGroupAddon, {
1632
- align: "inline-end",
1633
- children: /* @__PURE__ */ jsx(Button, {
1634
- "aria-label": "Clear input",
1635
- onClick: () => setUrl(""),
1636
- size: "icon-xs",
1637
- variant: "ghost",
1638
- children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
1639
- })
1640
- })]
1641
- }), /* @__PURE__ */ jsx(Button, {
1642
- size: "xs",
1643
- variant: "default",
1644
- onClick: handleSetLink,
1645
- children: "OK"
1646
- })]
1647
- }), isActive && /* @__PURE__ */ jsx("div", {
1648
- className: "flex justify-end",
1649
- children: /* @__PURE__ */ jsxs(PopoverClose, {
1650
- render: /* @__PURE__ */ jsx(Button, {
1651
- size: "xs",
1652
- variant: "ghost",
1653
- onClick: handleUnsetLink
1654
- }),
1655
- children: [/* @__PURE__ */ jsx(Link2Off, { className: "size-3" }), /* @__PURE__ */ jsx("span", {
1656
- className: "text-xs",
1657
- children: "Remove link"
1658
- })]
1659
- })
1660
- })]
1661
- })
1662
- })
1663
- })]
1664
- })
1172
+ }
1173
+ });
1174
+ function Badge({ className, variant, size, render, ...props }) {
1175
+ return useRender({
1176
+ defaultTagName: "span",
1177
+ props: mergeProps({
1178
+ className: cn(badgeVariants({
1179
+ className,
1180
+ size,
1181
+ variant
1182
+ })),
1183
+ "data-slot": "badge"
1184
+ }, props),
1185
+ render
1665
1186
  });
1666
1187
  }
1667
1188
 
1668
1189
  //#endregion
1669
1190
  //#region src/components/ui/scroll-area.tsx
1670
- function ScrollArea$1({ className, children, scrollFade = false, scrollbarGutter = false, ...props }) {
1671
- return /* @__PURE__ */ jsxs(ScrollArea.Root, {
1191
+ function ScrollArea({ className, children, scrollFade = false, scrollbarGutter = false, ...props }) {
1192
+ return /* @__PURE__ */ jsxs(ScrollArea$1.Root, {
1672
1193
  className: cn("size-full min-h-0", className),
1673
1194
  ...props,
1674
1195
  children: [
1675
- /* @__PURE__ */ jsx(ScrollArea.Viewport, {
1196
+ /* @__PURE__ */ jsx(ScrollArea$1.Viewport, {
1676
1197
  className: cn("h-full rounded-[inherit] outline-none transition-shadows focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background data-has-overflow-x:overscroll-x-contain", scrollFade && "mask-t-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-start)))] mask-b-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-end)))] mask-l-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-start)))] mask-r-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-end)))] [--fade-size:1.5rem]", scrollbarGutter && "data-has-overflow-y:pe-2.5 data-has-overflow-x:pb-2.5"),
1677
1198
  "data-slot": "scroll-area-viewport",
1678
1199
  children
1679
1200
  }),
1680
1201
  /* @__PURE__ */ jsx(ScrollBar, { orientation: "vertical" }),
1681
1202
  /* @__PURE__ */ jsx(ScrollBar, { orientation: "horizontal" }),
1682
- /* @__PURE__ */ jsx(ScrollArea.Corner, { "data-slot": "scroll-area-corner" })
1203
+ /* @__PURE__ */ jsx(ScrollArea$1.Corner, { "data-slot": "scroll-area-corner" })
1683
1204
  ]
1684
1205
  });
1685
1206
  }
1686
1207
  function ScrollBar({ className, orientation = "vertical", ...props }) {
1687
- return /* @__PURE__ */ jsx(ScrollArea.Scrollbar, {
1208
+ return /* @__PURE__ */ jsx(ScrollArea$1.Scrollbar, {
1688
1209
  className: cn("m-1 flex opacity-0 transition-opacity delay-300 data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:w-1.5 data-[orientation=horizontal]:flex-col data-hovering:opacity-100 data-scrolling:opacity-100 data-hovering:delay-0 data-scrolling:delay-0 data-hovering:duration-100 data-scrolling:duration-100", className),
1689
1210
  "data-slot": "scroll-area-scrollbar",
1690
1211
  orientation,
1691
1212
  ...props,
1692
- children: /* @__PURE__ */ jsx(ScrollArea.Thumb, {
1213
+ children: /* @__PURE__ */ jsx(ScrollArea$1.Thumb, {
1693
1214
  className: "relative flex-1 rounded-full bg-foreground/20",
1694
1215
  "data-slot": "scroll-area-thumb"
1695
1216
  })
@@ -1769,7 +1290,7 @@ function DialogDescription({ className, ...props }) {
1769
1290
  });
1770
1291
  }
1771
1292
  function DialogPanel({ className, scrollFade = true, ...props }) {
1772
- return /* @__PURE__ */ jsx(ScrollArea$1, {
1293
+ return /* @__PURE__ */ jsx(ScrollArea, {
1773
1294
  scrollFade,
1774
1295
  children: /* @__PURE__ */ jsx("div", {
1775
1296
  className: cn("px-6 in-[[data-slot=dialog-popup]:has([data-slot=dialog-header])]:pt-1 in-[[data-slot=dialog-popup]:not(:has([data-slot=dialog-header]))]:pt-6 in-[[data-slot=dialog-popup]:not(:has([data-slot=dialog-footer]))]:pb-6! in-[[data-slot=dialog-popup]:not(:has([data-slot=dialog-footer].border-t))]:pb-1 pb-6", className),
@@ -1780,64 +1301,101 @@ function DialogPanel({ className, scrollFade = true, ...props }) {
1780
1301
  }
1781
1302
 
1782
1303
  //#endregion
1783
- //#region src/components/ui/table.tsx
1784
- function Table({ className, ...props }) {
1304
+ //#region src/components/ui/input-group.tsx
1305
+ function InputGroup({ className, ...props }) {
1785
1306
  return /* @__PURE__ */ jsx("div", {
1786
- "data-slot": "table-container",
1787
- className: "relative w-full overflow-x-auto",
1788
- children: /* @__PURE__ */ jsx("table", {
1789
- "data-slot": "table",
1790
- className: cn("w-full caption-bottom text-sm", className),
1791
- ...props
1792
- })
1307
+ className: cn("relative inline-flex w-full min-w-0 items-center rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_1px_--theme(--color-black/6%)] has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/64 has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/16 has-[textarea]:h-auto has-data-[align=block-end]:h-auto has-data-[align=block-start]:h-auto has-data-[align=block-end]:flex-col has-data-[align=block-start]:flex-col has-[input:focus-visible,textarea:focus-visible]:border-ring has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/36 has-[input:disabled,textarea:disabled]:opacity-64 has-[input:disabled,textarea:disabled,input:focus-visible,textarea:focus-visible,input[aria-invalid],textarea[aria-invalid]]:shadow-none has-[input:focus-visible,textarea:focus-visible]:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/24 dark:not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_-1px_--theme(--color-white/6%)] has-data-[align=inline-start]:**:[[data-size=sm]_input]:ps-1.5 has-data-[align=inline-end]:**:[[data-size=sm]_input]:pe-1.5 *:[[data-slot=input-control],[data-slot=textarea-control]]:contents *:[[data-slot=input-control],[data-slot=textarea-control]]:before:hidden has-[[data-align=block-start],[data-align=block-end]]:**:[input]:h-auto has-data-[align=inline-start]:**:[input]:ps-2 has-data-[align=inline-end]:**:[input]:pe-2 has-data-[align=block-end]:**:[input]:pt-1.5 has-data-[align=block-start]:**:[input]:pb-1.5 **:[textarea]:min-h-20.5 **:[textarea]:resize-none **:[textarea]:py-[calc(--spacing(3)-1px)] **:[textarea]:max-sm:min-h-23.5 **:[textarea_button]:rounded-[calc(var(--radius-md)-1px)]", className),
1308
+ "data-slot": "input-group",
1309
+ role: "group",
1310
+ ...props
1793
1311
  });
1794
1312
  }
1795
- function TableHeader({ className, ...props }) {
1796
- return /* @__PURE__ */ jsx("thead", {
1797
- "data-slot": "table-header",
1798
- className: cn("[&_tr]:border-b", className),
1313
+ const inputGroupAddonVariants = cva("[&_svg]:-mx-0.5 flex h-auto cursor-text select-none items-center justify-center gap-2 leading-none [&>kbd]:rounded-[calc(var(--radius)-5px)] in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 not-has-[button]:**:[svg:not([class*='opacity-'])]:opacity-80", {
1314
+ defaultVariants: { align: "inline-start" },
1315
+ variants: { align: {
1316
+ "block-end": "order-last w-full justify-start px-[calc(--spacing(3)-1px)] pb-[calc(--spacing(3)-1px)] [.border-t]:pt-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]",
1317
+ "block-start": "order-first w-full justify-start px-[calc(--spacing(3)-1px)] pt-[calc(--spacing(3)-1px)] [.border-b]:pb-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]",
1318
+ "inline-end": "has-[>:last-child[data-slot=badge]]:-me-1.5 has-[>button]:-me-2 order-last pe-[calc(--spacing(3)-1px)] has-[>kbd:last-child]:me-[-0.35rem] [[data-size=sm]+&]:pe-[calc(--spacing(2.5)-1px)]",
1319
+ "inline-start": "has-[>:last-child[data-slot=badge]]:-ms-1.5 has-[>button]:-ms-2 order-first ps-[calc(--spacing(3)-1px)] has-[>kbd:last-child]:ms-[-0.35rem] [[data-size=sm]+&]:ps-[calc(--spacing(2.5)-1px)]"
1320
+ } }
1321
+ });
1322
+ function InputGroupAddon({ className, align = "inline-start", ...props }) {
1323
+ return /* @__PURE__ */ jsx("div", {
1324
+ className: cn(inputGroupAddonVariants({ align }), className),
1325
+ "data-align": align,
1326
+ "data-slot": "input-group-addon",
1327
+ onMouseDown: (e) => {
1328
+ if (e.target.closest("button, a, input, select, textarea, [role='button'], [role='combobox'], [role='listbox'], [data-slot='select-trigger']")) return;
1329
+ e.preventDefault();
1330
+ const parent = e.currentTarget.parentElement;
1331
+ const input = parent?.querySelector("input, textarea");
1332
+ if (input && !parent?.querySelector("input:focus, textarea:focus")) input.focus();
1333
+ },
1799
1334
  ...props
1800
1335
  });
1801
1336
  }
1802
- function TableBody({ className, ...props }) {
1803
- return /* @__PURE__ */ jsx("tbody", {
1804
- "data-slot": "table-body",
1805
- className: cn("[&_tr:last-child]:border-0", className),
1337
+ function InputGroupText({ className, ...props }) {
1338
+ return /* @__PURE__ */ jsx("span", {
1339
+ className: cn("[&_svg]:-mx-0.5 line-clamp-1 flex items-center gap-2 text-muted-foreground leading-none in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none", className),
1806
1340
  ...props
1807
1341
  });
1808
1342
  }
1809
- function TableFooter({ className, ...props }) {
1810
- return /* @__PURE__ */ jsx("tfoot", {
1811
- "data-slot": "table-footer",
1812
- className: cn("bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", className),
1343
+ function InputGroupInput({ className, ...props }) {
1344
+ return /* @__PURE__ */ jsx(Input, {
1345
+ className,
1346
+ unstyled: true,
1813
1347
  ...props
1814
1348
  });
1815
1349
  }
1816
- function TableRow({ className, ...props }) {
1817
- return /* @__PURE__ */ jsx("tr", {
1818
- "data-slot": "table-row",
1819
- className: cn("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors", className),
1350
+ function InputGroupTextarea({ className, ...props }) {
1351
+ return /* @__PURE__ */ jsx(Textarea, {
1352
+ className,
1353
+ unstyled: true,
1820
1354
  ...props
1821
1355
  });
1822
1356
  }
1823
- function TableHead({ className, ...props }) {
1824
- return /* @__PURE__ */ jsx("th", {
1825
- "data-slot": "table-head",
1826
- className: cn("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className),
1357
+
1358
+ //#endregion
1359
+ //#region src/components/ui/frame.tsx
1360
+ function Frame({ className, ...props }) {
1361
+ return /* @__PURE__ */ jsx("div", {
1362
+ className: cn("relative flex flex-col rounded-xl bg-muted/72 p-1", "*:[[data-slot=frame-panel]+[data-slot=frame-panel]]:mt-1", className),
1363
+ "data-slot": "frame",
1827
1364
  ...props
1828
1365
  });
1829
1366
  }
1830
- function TableCell({ className, ...props }) {
1831
- return /* @__PURE__ */ jsx("td", {
1832
- "data-slot": "table-cell",
1833
- className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className),
1367
+ function FramePanel({ className, ...props }) {
1368
+ return /* @__PURE__ */ jsx("div", {
1369
+ className: cn("relative rounded-xl border bg-background bg-clip-padding p-5 shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", className),
1370
+ "data-slot": "frame-panel",
1834
1371
  ...props
1835
1372
  });
1836
1373
  }
1837
- function TableCaption({ className, ...props }) {
1838
- return /* @__PURE__ */ jsx("caption", {
1839
- "data-slot": "table-caption",
1840
- className: cn("text-muted-foreground mt-4 text-sm", className),
1374
+ function FrameHeader({ className, ...props }) {
1375
+ return /* @__PURE__ */ jsx("header", {
1376
+ className: cn("flex flex-col px-5 py-4", className),
1377
+ "data-slot": "frame-panel-header",
1378
+ ...props
1379
+ });
1380
+ }
1381
+ function FrameTitle({ className, ...props }) {
1382
+ return /* @__PURE__ */ jsx("div", {
1383
+ className: cn("font-semibold text-sm", className),
1384
+ "data-slot": "frame-panel-title",
1385
+ ...props
1386
+ });
1387
+ }
1388
+ function FrameDescription({ className, ...props }) {
1389
+ return /* @__PURE__ */ jsx("div", {
1390
+ className: cn("text-muted-foreground text-sm", className),
1391
+ "data-slot": "frame-panel-description",
1392
+ ...props
1393
+ });
1394
+ }
1395
+ function FrameFooter({ className, ...props }) {
1396
+ return /* @__PURE__ */ jsx("footer", {
1397
+ className: cn("px-5 py-4", className),
1398
+ "data-slot": "frame-panel-footer",
1841
1399
  ...props
1842
1400
  });
1843
1401
  }
@@ -1846,49 +1404,48 @@ function TableCaption({ className, ...props }) {
1846
1404
  //#region src/components/ui/pagination.tsx
1847
1405
  function Pagination({ className, ...props }) {
1848
1406
  return /* @__PURE__ */ jsx("nav", {
1849
- role: "navigation",
1850
1407
  "aria-label": "pagination",
1408
+ className: cn("mx-auto flex w-full justify-center", className),
1851
1409
  "data-slot": "pagination",
1852
- className: cn("cn-pagination mx-auto flex w-full justify-center", className),
1853
1410
  ...props
1854
1411
  });
1855
1412
  }
1856
1413
  function PaginationContent({ className, ...props }) {
1857
1414
  return /* @__PURE__ */ jsx("ul", {
1415
+ className: cn("flex flex-row items-center gap-1", className),
1858
1416
  "data-slot": "pagination-content",
1859
- className: cn("cn-pagination-content bg-background divide-border border-border flex items-center divide-x overflow-hidden rounded-md border", className),
1860
1417
  ...props
1861
1418
  });
1862
1419
  }
1863
1420
  function PaginationItem({ ...props }) {
1864
1421
  return /* @__PURE__ */ jsx("li", {
1865
1422
  "data-slot": "pagination-item",
1866
- className: "h-full",
1867
1423
  ...props
1868
1424
  });
1869
1425
  }
1870
- function PaginationLink({ className, isActive, size = "icon", ...props }) {
1871
- return /* @__PURE__ */ jsx(Button, {
1872
- variant: "ghost",
1873
- size,
1874
- className: cn("cn-pagination-link hover:bg-muted rounded-none", isActive && "text-primary-500", className),
1875
- nativeButton: false,
1876
- render: /* @__PURE__ */ jsx("a", {
1426
+ function PaginationLink({ className, isActive, size = "icon", render, ...props }) {
1427
+ return useRender({
1428
+ defaultTagName: "a",
1429
+ props: mergeProps({
1877
1430
  "aria-current": isActive ? "page" : void 0,
1878
- "data-slot": "pagination-link",
1431
+ className: render ? className : cn(buttonVariants({
1432
+ size,
1433
+ variant: isActive ? "outline" : "ghost"
1434
+ }), className),
1879
1435
  "data-active": isActive,
1880
- ...props
1881
- })
1436
+ "data-slot": "pagination-link"
1437
+ }, props),
1438
+ render
1882
1439
  });
1883
1440
  }
1884
1441
  function PaginationPrevious({ className, ...props }) {
1885
1442
  return /* @__PURE__ */ jsxs(PaginationLink, {
1886
1443
  "aria-label": "Go to previous page",
1444
+ className: cn("max-sm:aspect-square max-sm:p-0", className),
1887
1445
  size: "default",
1888
- className: cn("cn-pagination-previous", className),
1889
1446
  ...props,
1890
- children: [/* @__PURE__ */ jsx(ChevronLeftIcon, {}), /* @__PURE__ */ jsx("span", {
1891
- className: "cn-pagination-previous-text hidden",
1447
+ children: [/* @__PURE__ */ jsx(ChevronLeftIcon, { className: "sm:-ms-1" }), /* @__PURE__ */ jsx("span", {
1448
+ className: "sm:hidden",
1892
1449
  children: "Previous"
1893
1450
  })]
1894
1451
  });
@@ -1896,151 +1453,916 @@ function PaginationPrevious({ className, ...props }) {
1896
1453
  function PaginationNext({ className, ...props }) {
1897
1454
  return /* @__PURE__ */ jsxs(PaginationLink, {
1898
1455
  "aria-label": "Go to next page",
1456
+ className: cn("max-sm:aspect-square max-sm:p-0", className),
1899
1457
  size: "default",
1900
- className: cn("cn-pagination-next", className),
1901
1458
  ...props,
1902
1459
  children: [/* @__PURE__ */ jsx("span", {
1903
- className: "cn-pagination-next-text hidden",
1460
+ className: "sm:hidden",
1904
1461
  children: "Next"
1905
- }), /* @__PURE__ */ jsx(ChevronRightIcon, {})]
1462
+ }), /* @__PURE__ */ jsx(ChevronRightIcon, { className: "sm:-me-1" })]
1906
1463
  });
1907
1464
  }
1908
1465
  function PaginationEllipsis({ className, ...props }) {
1909
1466
  return /* @__PURE__ */ jsxs("span", {
1910
1467
  "aria-hidden": true,
1468
+ className: cn("flex min-w-7 justify-center", className),
1911
1469
  "data-slot": "pagination-ellipsis",
1912
- className: cn("cn-pagination-ellipsis flex h-full w-auto items-end justify-center px-2 py-1.5", className),
1913
1470
  ...props,
1914
- children: [/* @__PURE__ */ jsx(MoreHorizontalIcon, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
1471
+ children: [/* @__PURE__ */ jsx(MoreHorizontalIcon, { className: "size-5 sm:size-4" }), /* @__PURE__ */ jsx("span", {
1915
1472
  className: "sr-only",
1916
1473
  children: "More pages"
1917
1474
  })]
1918
1475
  });
1919
- }
1476
+ }
1477
+
1478
+ //#endregion
1479
+ //#region src/components/ui/table.tsx
1480
+ function Table({ className, ...props }) {
1481
+ return /* @__PURE__ */ jsx("div", {
1482
+ className: "relative w-full overflow-x-auto",
1483
+ "data-slot": "table-container",
1484
+ children: /* @__PURE__ */ jsx("table", {
1485
+ className: cn("w-full caption-bottom in-data-[slot=frame]:border-separate in-data-[slot=frame]:border-spacing-0 text-sm", className),
1486
+ "data-slot": "table",
1487
+ ...props
1488
+ })
1489
+ });
1490
+ }
1491
+ function TableHeader({ className, ...props }) {
1492
+ return /* @__PURE__ */ jsx("thead", {
1493
+ className: cn("[&_tr]:border-b in-data-[slot=frame]:**:[th]:h-9 in-data-[slot=frame]:*:[tr]:border-none in-data-[slot=frame]:*:[tr]:hover:bg-transparent", className),
1494
+ "data-slot": "table-header",
1495
+ ...props
1496
+ });
1497
+ }
1498
+ function TableBody({ className, ...props }) {
1499
+ return /* @__PURE__ */ jsx("tbody", {
1500
+ className: cn("relative in-data-[slot=frame]:rounded-xl in-data-[slot=frame]:shadow-xs/5 before:pointer-events-none before:absolute before:inset-px not-in-data-[slot=frame]:before:hidden before:rounded-[calc(var(--radius-xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/8%)] [&_tr:last-child]:border-0 in-data-[slot=frame]:*:[tr]:border-0 in-data-[slot=frame]:*:[tr]:*:[td]:border-b in-data-[slot=frame]:*:[tr]:*:[td]:bg-background in-data-[slot=frame]:*:[tr]:*:[td]:bg-clip-padding in-data-[slot=frame]:*:[tr]:first:*:[td]:first:rounded-ss-xl in-data-[slot=frame]:*:[tr]:*:[td]:first:border-s in-data-[slot=frame]:*:[tr]:first:*:[td]:border-t in-data-[slot=frame]:*:[tr]:last:*:[td]:last:rounded-ee-xl in-data-[slot=frame]:*:[tr]:*:[td]:last:border-e in-data-[slot=frame]:*:[tr]:first:*:[td]:last:rounded-se-xl in-data-[slot=frame]:*:[tr]:last:*:[td]:first:rounded-es-xl in-data-[slot=frame]:*:[tr]:hover:*:[td]:bg-transparent in-data-[slot=frame]:*:[tr]:data-[state=selected]:*:[td]:bg-muted/72", className),
1501
+ "data-slot": "table-body",
1502
+ ...props
1503
+ });
1504
+ }
1505
+ function TableFooter({ className, ...props }) {
1506
+ return /* @__PURE__ */ jsx("tfoot", {
1507
+ className: cn("border-t in-data-[slot=frame]:border-none bg-muted/72 in-data-[slot=frame]:bg-transparent font-medium [&>tr]:last:border-b-0 in-data-[slot=frame]:*:[tr]:hover:bg-transparent", className),
1508
+ "data-slot": "table-footer",
1509
+ ...props
1510
+ });
1511
+ }
1512
+ function TableRow({ className, ...props }) {
1513
+ return /* @__PURE__ */ jsx("tr", {
1514
+ className: cn("border-b transition-colors hover:bg-muted/72 in-data-[slot=frame]:hover:bg-transparent data-[state=selected]:bg-muted/72 in-data-[slot=frame]:data-[state=selected]:bg-transparent", className),
1515
+ "data-slot": "table-row",
1516
+ ...props
1517
+ });
1518
+ }
1519
+ function TableHead({ className, ...props }) {
1520
+ return /* @__PURE__ */ jsx("th", {
1521
+ className: cn("h-10 whitespace-nowrap px-2.5 text-left align-middle font-medium text-muted-foreground leading-none has-[[role=checkbox]]:w-px has-[[role=checkbox]]:pe-0", className),
1522
+ "data-slot": "table-head",
1523
+ ...props
1524
+ });
1525
+ }
1526
+ function TableCell({ className, ...props }) {
1527
+ return /* @__PURE__ */ jsx("td", {
1528
+ className: cn("whitespace-nowrap p-2.5 align-middle leading-none in-data-[slot=frame]:first:p-[calc(--spacing(2.5)-1px)] in-data-[slot=frame]:last:p-[calc(--spacing(2.5)-1px)] has-[[role=checkbox]]:pe-0", className),
1529
+ "data-slot": "table-cell",
1530
+ ...props
1531
+ });
1532
+ }
1533
+ function TableCaption({ className, ...props }) {
1534
+ return /* @__PURE__ */ jsx("caption", {
1535
+ className: cn("in-data-[slot=frame]:my-4 mt-4 text-muted-foreground text-sm", className),
1536
+ "data-slot": "table-caption",
1537
+ ...props
1538
+ });
1539
+ }
1540
+
1541
+ //#endregion
1542
+ //#region src/components/PickerModal/index.tsx
1543
+ /**
1544
+ * Returns an ordered list of page numbers and ellipsis markers to display.
1545
+ *
1546
+ * Rules (always-visible anchors: first 2 + last 2):
1547
+ * - Near start (currentPage ≤ 3) → show [1,2,3] … [n-1,n]
1548
+ * - Near end (currentPage ≥ totalPages-2) → show [1,2] … [n-2,n-1,n]
1549
+ * - Middle → show [1,2] … [p] … [n-1,n]
1550
+ *
1551
+ * Single-page gaps are filled automatically (no orphan ellipsis).
1552
+ */
1553
+ function getPageItems(currentPage, totalPages) {
1554
+ const left = [1, 2];
1555
+ const right = [totalPages - 1, totalPages];
1556
+ let middle;
1557
+ if (currentPage <= 3) middle = [3];
1558
+ else if (currentPage >= totalPages - 2) middle = [totalPages - 2];
1559
+ else middle = [currentPage];
1560
+ const pagesSet = new Set([
1561
+ ...left,
1562
+ ...middle,
1563
+ ...right
1564
+ ].filter((p) => p >= 1 && p <= totalPages));
1565
+ const pages = Array.from(pagesSet).sort((a, b) => a - b);
1566
+ const items = [];
1567
+ for (let i = 0; i < pages.length; i++) {
1568
+ if (i > 0) {
1569
+ const gap = pages[i] - pages[i - 1];
1570
+ if (gap === 2) items.push(pages[i] - 1);
1571
+ else if (gap > 2) items.push("ellipsis");
1572
+ }
1573
+ items.push(pages[i]);
1574
+ }
1575
+ return items;
1576
+ }
1577
+ function PickerModal({ title, searchQuery, onSearch, searchPlaceholder = "Search...", columns, data, loading, totalItems, selectedId, onRowClick, pagination, onPaginationChange, sorting = [], onSortingChange, pageSizeOptions = [
1578
+ 10,
1579
+ 25,
1580
+ 50,
1581
+ 100
1582
+ ], emptyIcon, emptyMessage = "No results found", footer }) {
1583
+ const table = useReactTable({
1584
+ data,
1585
+ columns,
1586
+ pageCount: Math.max(1, Math.ceil(totalItems / pagination.pageSize)),
1587
+ state: {
1588
+ pagination,
1589
+ sorting
1590
+ },
1591
+ onPaginationChange,
1592
+ ...onSortingChange ? { onSortingChange } : {},
1593
+ getCoreRowModel: getCoreRowModel(),
1594
+ manualPagination: true,
1595
+ manualSorting: true,
1596
+ enableSortingRemoval: false
1597
+ });
1598
+ const pageSize = table.getState().pagination.pageSize;
1599
+ return /* @__PURE__ */ jsxs(DialogPopup, {
1600
+ className: "max-w-4xl",
1601
+ children: [
1602
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: title }) }),
1603
+ /* @__PURE__ */ jsxs(DialogPanel, {
1604
+ className: "flex flex-col gap-4",
1605
+ children: [/* @__PURE__ */ jsxs(InputGroup, { children: [/* @__PURE__ */ jsx(InputGroupInput, {
1606
+ placeholder: searchPlaceholder,
1607
+ value: searchQuery,
1608
+ onChange: (e) => onSearch(e.target.value)
1609
+ }), /* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(SearchIcon, { className: "size-4" }) })] }), loading ? /* @__PURE__ */ jsx("div", {
1610
+ className: "flex items-center justify-center py-12",
1611
+ children: /* @__PURE__ */ jsx(Loader2Icon, { className: "text-muted-foreground size-8 animate-spin" })
1612
+ }) : /* @__PURE__ */ jsxs(Frame, {
1613
+ className: "w-full overflow-hidden",
1614
+ children: [/* @__PURE__ */ jsxs(Table, {
1615
+ className: "table-fixed",
1616
+ children: [/* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, {
1617
+ className: "hover:bg-transparent",
1618
+ children: headerGroup.headers.map((header) => {
1619
+ const columnSize = header.column.getSize();
1620
+ return /* @__PURE__ */ jsx(TableHead, {
1621
+ style: columnSize ? { width: `${columnSize}px` } : void 0,
1622
+ children: header.isPlaceholder ? null : header.column.getCanSort() ? /* @__PURE__ */ jsxs("div", {
1623
+ className: "flex h-full cursor-pointer select-none items-center justify-between gap-2",
1624
+ onClick: header.column.getToggleSortingHandler(),
1625
+ onKeyDown: (e) => {
1626
+ if (e.key === "Enter" || e.key === " ") {
1627
+ e.preventDefault();
1628
+ header.column.getToggleSortingHandler()?.(e);
1629
+ }
1630
+ },
1631
+ role: "button",
1632
+ tabIndex: 0,
1633
+ children: [flexRender(header.column.columnDef.header, header.getContext()), {
1634
+ asc: /* @__PURE__ */ jsx(ChevronUpIcon, {
1635
+ "aria-hidden": "true",
1636
+ className: "size-4 shrink-0 opacity-80"
1637
+ }),
1638
+ desc: /* @__PURE__ */ jsx(ChevronDownIcon, {
1639
+ "aria-hidden": "true",
1640
+ className: "size-4 shrink-0 opacity-80"
1641
+ })
1642
+ }[header.column.getIsSorted()] ?? /* @__PURE__ */ jsx(ChevronsUpDownIcon, {
1643
+ "aria-hidden": "true",
1644
+ className: "size-4 shrink-0 opacity-40"
1645
+ })]
1646
+ }) : flexRender(header.column.columnDef.header, header.getContext())
1647
+ }, header.id);
1648
+ })
1649
+ }, headerGroup.id)) }), /* @__PURE__ */ jsx(TableBody, { children: table.getRowModel().rows.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(TableRow, {
1650
+ className: cn("hover:bg-muted/50 cursor-pointer transition-colors", selectedId === row.original.id && "bg-primary/5"),
1651
+ onClick: () => onRowClick(row.original),
1652
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
1653
+ }, row.id)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, {
1654
+ colSpan: columns.length,
1655
+ className: "py-12 text-center",
1656
+ children: /* @__PURE__ */ jsxs("div", {
1657
+ className: "text-muted-foreground flex flex-col items-center justify-center text-sm",
1658
+ children: [emptyIcon, /* @__PURE__ */ jsx("p", { children: emptyMessage })]
1659
+ })
1660
+ }) }) })]
1661
+ }), totalItems > 0 && /* @__PURE__ */ jsx(FrameFooter, {
1662
+ className: "p-2",
1663
+ children: /* @__PURE__ */ jsxs("div", {
1664
+ className: "grid grid-cols-[1fr_auto_1fr] items-center gap-x-4",
1665
+ children: [
1666
+ /* @__PURE__ */ jsxs("div", {
1667
+ className: "hidden sm:flex items-center gap-2 whitespace-nowrap justify-self-start",
1668
+ children: [
1669
+ /* @__PURE__ */ jsx("p", {
1670
+ className: "text-muted-foreground text-sm",
1671
+ children: "Viewing"
1672
+ }),
1673
+ /* @__PURE__ */ jsxs(Select, {
1674
+ value: (table.getState().pagination.pageIndex + 1).toString(),
1675
+ onValueChange: (val) => table.setPageIndex(Number(val) - 1),
1676
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
1677
+ "aria-label": "Select result range",
1678
+ className: "w-fit min-w-none",
1679
+ size: "sm",
1680
+ children: /* @__PURE__ */ jsx(SelectValue, { children: (() => {
1681
+ const idx = table.getState().pagination.pageIndex;
1682
+ return `${idx * pageSize + 1}–${Math.min((idx + 1) * pageSize, totalItems)}`;
1683
+ })() })
1684
+ }), /* @__PURE__ */ jsx(SelectPopup, { children: Array.from({ length: table.getPageCount() }, (_, i) => {
1685
+ const pageNum = i + 1;
1686
+ const start = i * pageSize + 1;
1687
+ const end = Math.min((i + 1) * pageSize, totalItems);
1688
+ return /* @__PURE__ */ jsx(SelectItem, {
1689
+ value: pageNum.toString(),
1690
+ children: `${start}–${end}`
1691
+ }, pageNum);
1692
+ }) })]
1693
+ }),
1694
+ /* @__PURE__ */ jsxs("p", {
1695
+ className: "text-muted-foreground text-sm",
1696
+ children: [
1697
+ "of",
1698
+ " ",
1699
+ /* @__PURE__ */ jsx("strong", {
1700
+ className: "font-medium text-foreground",
1701
+ children: totalItems
1702
+ }),
1703
+ " ",
1704
+ "results"
1705
+ ]
1706
+ })
1707
+ ]
1708
+ }),
1709
+ /* @__PURE__ */ jsxs("div", {
1710
+ className: "flex items-center gap-2 whitespace-nowrap justify-self-center col-start-2",
1711
+ children: [/* @__PURE__ */ jsx("p", {
1712
+ className: "text-muted-foreground text-sm",
1713
+ children: "Per page"
1714
+ }), /* @__PURE__ */ jsxs(Select, {
1715
+ value: pageSize.toString(),
1716
+ onValueChange: (val) => table.setPageSize(Number(val)),
1717
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
1718
+ "aria-label": "Rows per page",
1719
+ className: "w-fit min-w-none",
1720
+ size: "sm",
1721
+ children: /* @__PURE__ */ jsx("span", {
1722
+ className: "flex-1 truncate",
1723
+ children: pageSize
1724
+ })
1725
+ }), /* @__PURE__ */ jsx(SelectPopup, { children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, {
1726
+ value: size.toString(),
1727
+ children: size
1728
+ }, size)) })]
1729
+ })]
1730
+ }),
1731
+ /* @__PURE__ */ jsx(Pagination, {
1732
+ className: "justify-self-end justify-end table-pagination",
1733
+ children: /* @__PURE__ */ jsxs(PaginationContent, {
1734
+ className: "gap-0",
1735
+ children: [
1736
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationPrevious, {
1737
+ className: "max-sm:*:[svg]:hidden",
1738
+ render: /* @__PURE__ */ jsx(Button, {
1739
+ disabled: !table.getCanPreviousPage(),
1740
+ onClick: () => table.previousPage(),
1741
+ size: "sm",
1742
+ variant: "outline"
1743
+ })
1744
+ }) }),
1745
+ getPageItems(table.getState().pagination.pageIndex + 1, table.getPageCount()).map((item, index) => /* @__PURE__ */ jsx(PaginationItem, {
1746
+ className: "hidden sm:block",
1747
+ children: item === "ellipsis" ? /* @__PURE__ */ jsx(Button, {
1748
+ size: "sm",
1749
+ variant: "outline",
1750
+ className: "pagination-ellipsis",
1751
+ children: /* @__PURE__ */ jsx(PaginationEllipsis, {})
1752
+ }) : /* @__PURE__ */ jsx(PaginationLink, {
1753
+ isActive: item === table.getState().pagination.pageIndex + 1,
1754
+ size: "sm",
1755
+ render: /* @__PURE__ */ jsx(Button, {
1756
+ onClick: () => table.setPageIndex(item - 1),
1757
+ size: "sm",
1758
+ variant: "outline"
1759
+ }),
1760
+ children: item
1761
+ })
1762
+ }, index)),
1763
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationNext, {
1764
+ className: "max-sm:*:[svg]:hidden",
1765
+ render: /* @__PURE__ */ jsx(Button, {
1766
+ disabled: !table.getCanNextPage(),
1767
+ onClick: () => table.nextPage(),
1768
+ size: "sm",
1769
+ variant: "outline"
1770
+ })
1771
+ }) })
1772
+ ]
1773
+ })
1774
+ })
1775
+ ]
1776
+ })
1777
+ })]
1778
+ })]
1779
+ }),
1780
+ footer && /* @__PURE__ */ jsx(DialogFooter, { children: footer })
1781
+ ]
1782
+ });
1783
+ }
1784
+
1785
+ //#endregion
1786
+ //#region src/components/PagePicker/index.tsx
1787
+ const getEditorConfig$1 = () => {
1788
+ const editorEl = document.getElementById("editor");
1789
+ return {
1790
+ pagesUrl: editorEl?.dataset.pagesUrl || "/admin/pages/puck/pages",
1791
+ langId: editorEl?.dataset.langId || ""
1792
+ };
1793
+ };
1794
+ const fetchPages = async ({ query, filters, page = 1, limit = 10, sortBy, sortOrder }) => {
1795
+ const { pagesUrl, langId } = getEditorConfig$1();
1796
+ const params = new URLSearchParams();
1797
+ if (query) params.append("search", query);
1798
+ if (langId) params.append("lang_id", langId);
1799
+ params.append("page", page.toString());
1800
+ params.append("limit", limit.toString());
1801
+ if (sortBy) params.append("sort_by", sortBy);
1802
+ if (sortOrder) params.append("sort_order", sortOrder);
1803
+ if (filters) Object.entries(filters).forEach(([key, value]) => {
1804
+ params.append(key, value);
1805
+ });
1806
+ const data = await (await fetch(`${pagesUrl}?${params.toString()}`, { credentials: "same-origin" })).json();
1807
+ if (data.success && data.pages) return {
1808
+ items: data.pages,
1809
+ total: data.total || data.pages.length
1810
+ };
1811
+ return {
1812
+ items: [],
1813
+ total: 0
1814
+ };
1815
+ };
1816
+ const fetchPageById = async (id) => {
1817
+ try {
1818
+ return (await fetchPages({
1819
+ filters: { id: id.toString() },
1820
+ limit: 1
1821
+ })).items[0] ?? null;
1822
+ } catch {
1823
+ return null;
1824
+ }
1825
+ };
1826
+ const getPublishedBadge = (published) => published ? {
1827
+ label: "Published",
1828
+ dot: "bg-emerald-500"
1829
+ } : {
1830
+ label: "Unpublished",
1831
+ dot: "bg-red-500"
1832
+ };
1833
+ const DEFAULT_VALUE$1 = {
1834
+ type: "page",
1835
+ page: null
1836
+ };
1837
+ const PAGE_SIZE$1 = 10;
1838
+ const PageLibraryModal = ({ value, onChange, open, onOpenChange }) => {
1839
+ const [pages, setPages] = useState([]);
1840
+ const [loading, setLoading] = useState(false);
1841
+ const [totalItems, setTotalItems] = useState(0);
1842
+ const [searchQuery, setSearchQuery] = useState("");
1843
+ const [pagination, setPagination] = useState({
1844
+ pageIndex: 0,
1845
+ pageSize: PAGE_SIZE$1
1846
+ });
1847
+ const [sorting, setSorting] = useState([]);
1848
+ const loadPages = useCallback(async (pageIndex, pageSize, query, sort) => {
1849
+ setLoading(true);
1850
+ try {
1851
+ const sortItem = sort[0];
1852
+ const result = await fetchPages({
1853
+ page: pageIndex + 1,
1854
+ limit: pageSize,
1855
+ query,
1856
+ sortBy: sortItem?.id,
1857
+ sortOrder: sortItem ? sortItem.desc ? "desc" : "asc" : void 0
1858
+ });
1859
+ setPages(result.items);
1860
+ setTotalItems(result.total);
1861
+ } catch (error) {
1862
+ console.error("Error loading pages:", error);
1863
+ } finally {
1864
+ setLoading(false);
1865
+ }
1866
+ }, []);
1867
+ useEffect(() => {
1868
+ if (open) loadPages(pagination.pageIndex, pagination.pageSize, searchQuery, sorting);
1869
+ }, [
1870
+ open,
1871
+ pagination,
1872
+ sorting,
1873
+ searchQuery,
1874
+ loadPages
1875
+ ]);
1876
+ const handleSearch = useCallback((query) => {
1877
+ setSearchQuery(query);
1878
+ setPagination((prev) => ({
1879
+ ...prev,
1880
+ pageIndex: 0
1881
+ }));
1882
+ }, []);
1883
+ const handleRowClick = useCallback((page) => {
1884
+ onChange({
1885
+ id: page.id,
1886
+ name: page.name,
1887
+ url: page.url
1888
+ });
1889
+ onOpenChange(false);
1890
+ }, [onChange, onOpenChange]);
1891
+ return /* @__PURE__ */ jsx(PickerModal, {
1892
+ title: "Select Page",
1893
+ searchQuery,
1894
+ onSearch: handleSearch,
1895
+ searchPlaceholder: "Search pages...",
1896
+ columns: useMemo(() => [
1897
+ {
1898
+ accessorKey: "id",
1899
+ header: "ID",
1900
+ size: 40,
1901
+ cell: ({ row }) => /* @__PURE__ */ jsxs("span", {
1902
+ className: "text-muted-foreground font-mono text-xs",
1903
+ children: ["#", row.getValue("id")]
1904
+ })
1905
+ },
1906
+ {
1907
+ accessorKey: "name",
1908
+ header: "Name",
1909
+ size: 200,
1910
+ cell: ({ row }) => /* @__PURE__ */ jsx("div", {
1911
+ className: "font-medium",
1912
+ children: row.getValue("name")
1913
+ })
1914
+ },
1915
+ {
1916
+ accessorKey: "url",
1917
+ header: "URL",
1918
+ cell: ({ row }) => /* @__PURE__ */ jsx("div", {
1919
+ className: "text-muted-foreground font-mono text-xs truncate",
1920
+ children: toRelativeUrl(row.getValue("url"))
1921
+ })
1922
+ },
1923
+ {
1924
+ accessorKey: "published",
1925
+ header: "Status",
1926
+ size: 60,
1927
+ enableSorting: false,
1928
+ cell: ({ row }) => {
1929
+ const { label, dot } = getPublishedBadge(row.getValue("published"));
1930
+ return /* @__PURE__ */ jsxs(Badge, {
1931
+ variant: "outline",
1932
+ children: [/* @__PURE__ */ jsx("span", {
1933
+ "aria-hidden": "true",
1934
+ className: cn("size-1.5 rounded-full", dot)
1935
+ }), label]
1936
+ });
1937
+ }
1938
+ }
1939
+ ], []),
1940
+ data: pages,
1941
+ loading,
1942
+ totalItems,
1943
+ selectedId: value?.id,
1944
+ onRowClick: handleRowClick,
1945
+ pagination,
1946
+ onPaginationChange: setPagination,
1947
+ sorting,
1948
+ onSortingChange: setSorting,
1949
+ emptyIcon: /* @__PURE__ */ jsx(FileTextIcon, { className: "mb-2 size-12 opacity-20" }),
1950
+ emptyMessage: "No pages found"
1951
+ });
1952
+ };
1953
+ const PagePicker = ({ value, onChange }) => {
1954
+ const [open, setOpen] = useState(false);
1955
+ const currentValue = value || DEFAULT_VALUE$1;
1956
+ const displayValue = currentValue.type === "page" && currentValue.page ? currentValue.page.name : currentValue.url || "";
1957
+ const hasValue = Boolean(currentValue.type === "page" && currentValue.page || currentValue.type === "url" && currentValue.url);
1958
+ const handleInputChange = (e) => {
1959
+ onChange({
1960
+ type: "url",
1961
+ url: e.target.value
1962
+ });
1963
+ };
1964
+ const handlePageChange = (page) => {
1965
+ onChange({
1966
+ type: "page",
1967
+ page
1968
+ });
1969
+ };
1970
+ const handleClear = () => {
1971
+ onChange(DEFAULT_VALUE$1);
1972
+ };
1973
+ return /* @__PURE__ */ jsxs(Dialog, {
1974
+ open,
1975
+ onOpenChange: setOpen,
1976
+ children: [/* @__PURE__ */ jsxs(InputGroup, { children: [
1977
+ currentValue.type === "page" && currentValue.page && /* @__PURE__ */ jsx(InputGroupAddon, {
1978
+ align: "inline-start",
1979
+ children: /* @__PURE__ */ jsxs("span", {
1980
+ className: "bg-muted text-muted-foreground rounded px-1.5 py-0.5 font-mono text-xs",
1981
+ children: ["#", currentValue.page.id]
1982
+ })
1983
+ }),
1984
+ /* @__PURE__ */ jsx(InputGroupInput, {
1985
+ placeholder: "https://example.com/",
1986
+ type: "text",
1987
+ value: displayValue,
1988
+ onChange: handleInputChange
1989
+ }),
1990
+ /* @__PURE__ */ jsx(InputGroupAddon, {
1991
+ align: "inline-end",
1992
+ children: hasValue ? /* @__PURE__ */ jsx(Button, {
1993
+ size: "icon-xs",
1994
+ variant: "ghost",
1995
+ onClick: handleClear,
1996
+ children: /* @__PURE__ */ jsx(XIcon, { "aria-hidden": "true" })
1997
+ }) : /* @__PURE__ */ jsx(DialogTrigger, { render: /* @__PURE__ */ jsx(Button, {
1998
+ size: "icon-xs",
1999
+ variant: "outline",
2000
+ children: /* @__PURE__ */ jsx(DatabaseIcon, { className: "size-3.5" })
2001
+ }) })
2002
+ })
2003
+ ] }), /* @__PURE__ */ jsx(PageLibraryModal, {
2004
+ value: currentValue.page || null,
2005
+ onChange: handlePageChange,
2006
+ open,
2007
+ onOpenChange: setOpen
2008
+ })]
2009
+ });
2010
+ };
2011
+ /**
2012
+ * Converts an absolute URL to a relative URL by extracting the pathname.
2013
+ * If the URL is already relative, returns it as-is.
2014
+ *
2015
+ * @example
2016
+ * toRelativeUrl("https://example.com/page?foo=bar#section") // "/page?foo=bar#section"
2017
+ * toRelativeUrl("/page") // "/page"
2018
+ * toRelativeUrl("") // ""
2019
+ */
2020
+ const toRelativeUrl = (url) => {
2021
+ if (!url) return "";
2022
+ if (url.startsWith("/")) return url;
2023
+ try {
2024
+ const { pathname, search, hash } = new URL(url);
2025
+ return pathname + search + hash;
2026
+ } catch {
2027
+ return url;
2028
+ }
2029
+ };
2030
+ /**
2031
+ * Hook React qui résout dynamiquement l'URL courante d'un `PagePickerValue`.
2032
+ *
2033
+ * Pour les références de page (`type: "page"`), l'URL est récupérée depuis
2034
+ * l'API à partir de l'`id` de la page — ce qui garantit que le lien reste
2035
+ * valide même si l'URL de la page a été modifiée après la sélection.
2036
+ *
2037
+ * @example
2038
+ * const { url, loading } = usePageUrl(value)
2039
+ * return loading ? <Spinner /> : <a href={url}>Lien</a>
2040
+ */
2041
+ const usePageUrl = (value) => {
2042
+ const [url, setUrl] = useState(void 0);
2043
+ const [loading, setLoading] = useState(false);
2044
+ const pageId = value?.type === "page" ? value.page?.id : void 0;
2045
+ const directUrl = value?.type === "url" ? value.url : void 0;
2046
+ useEffect(() => {
2047
+ if (directUrl !== void 0) {
2048
+ setUrl(directUrl ? toRelativeUrl(directUrl) : void 0);
2049
+ return;
2050
+ }
2051
+ if (pageId !== void 0) {
2052
+ let cancelled = false;
2053
+ setLoading(true);
2054
+ fetchPageById(pageId).then((page) => {
2055
+ if (!cancelled) setUrl(page ? toRelativeUrl(page.url) : void 0);
2056
+ }).catch(() => {
2057
+ if (!cancelled) setUrl(void 0);
2058
+ }).finally(() => {
2059
+ if (!cancelled) setLoading(false);
2060
+ });
2061
+ return () => {
2062
+ cancelled = true;
2063
+ };
2064
+ }
2065
+ setUrl(void 0);
2066
+ }, [pageId, directUrl]);
2067
+ return {
2068
+ url,
2069
+ loading
2070
+ };
2071
+ };
2072
+
2073
+ //#endregion
2074
+ //#region src/components/RichTextMenuLink/index.tsx
2075
+ function RichTextMenuLink({ editor, ...props }) {
2076
+ const [pickerValue, setPickerValue] = useState({
2077
+ type: "url",
2078
+ url: ""
2079
+ });
2080
+ const [open, setOpen] = useState(false);
2081
+ const selectionRef = useRef(null);
2082
+ useEffect(() => {
2083
+ if (open && editor) setPickerValue({
2084
+ type: "url",
2085
+ url: editor.getAttributes("link").href ?? ""
2086
+ });
2087
+ }, [open, editor]);
2088
+ const handleSetLink = useCallback(() => {
2089
+ if (!editor) return;
2090
+ let resolvedUrl = "";
2091
+ if (pickerValue.type === "page" && pickerValue.page?.url) resolvedUrl = toRelativeUrl(pickerValue.page.url);
2092
+ else if (pickerValue.type === "url") resolvedUrl = pickerValue.url?.trim() ?? "";
2093
+ const sel = selectionRef.current;
2094
+ if (!resolvedUrl) {
2095
+ const chain = editor.chain().focus();
2096
+ if (sel) chain.setTextSelection(sel);
2097
+ chain.extendMarkRange("link").unsetLink().run();
2098
+ } else {
2099
+ const chain = editor.chain().focus();
2100
+ if (sel) chain.setTextSelection(sel);
2101
+ chain.extendMarkRange("link").setLink({ href: resolvedUrl }).run();
2102
+ }
2103
+ setOpen(false);
2104
+ }, [editor, pickerValue]);
2105
+ return /* @__PURE__ */ jsx("div", {
2106
+ ...props,
2107
+ children: /* @__PURE__ */ jsxs(Popover, {
2108
+ open,
2109
+ onOpenChange: setOpen,
2110
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
2111
+ render: /* @__PURE__ */ jsx("button", {
2112
+ type: "button",
2113
+ title: "Link",
2114
+ onPointerDown: () => {
2115
+ if (editor) {
2116
+ const { from, to } = editor.state.selection;
2117
+ selectionRef.current = {
2118
+ from,
2119
+ to
2120
+ };
2121
+ }
2122
+ },
2123
+ onClick: (e) => {
2124
+ e.stopPropagation();
2125
+ },
2126
+ className: "inline-flex border h-full aspect-square cursor-pointer items-center p-1.5 justify-center rounded-md transition-colors border-stone-200 bg-white text-black hover:border-stone-300 hover:bg-stone-50"
2127
+ }),
2128
+ children: /* @__PURE__ */ jsx(LinkIcon, { className: "size-4" })
2129
+ }), /* @__PURE__ */ jsx(PopoverPopup, {
2130
+ side: "bottom",
2131
+ align: "start",
2132
+ sideOffset: 8,
2133
+ className: "w-80",
2134
+ children: /* @__PURE__ */ jsx("div", {
2135
+ "data-puck-rte-menu": true,
2136
+ children: /* @__PURE__ */ jsxs("div", {
2137
+ className: "flex items-center gap-2",
2138
+ children: [/* @__PURE__ */ jsx(PagePicker, {
2139
+ value: pickerValue,
2140
+ onChange: setPickerValue
2141
+ }), /* @__PURE__ */ jsx(Button, {
2142
+ size: "sm",
2143
+ variant: "default",
2144
+ onClick: handleSetLink,
2145
+ className: "ml-auto h-8.5 sm:h-7.5",
2146
+ children: "OK"
2147
+ })]
2148
+ })
2149
+ })
2150
+ })]
2151
+ })
2152
+ });
2153
+ }
2154
+
2155
+ //#endregion
2156
+ //#region src/components/ColorPicker/index.tsx
2157
+ const PREDEFINED_COLORS = [
2158
+ {
2159
+ name: "Blue",
2160
+ value: "#3B82F6"
2161
+ },
2162
+ {
2163
+ name: "Purple",
2164
+ value: "#8B5CF6"
2165
+ },
2166
+ {
2167
+ name: "Pink",
2168
+ value: "#EC4899"
2169
+ },
2170
+ {
2171
+ name: "Rose",
2172
+ value: "#F43F5E"
2173
+ },
2174
+ {
2175
+ name: "Red",
2176
+ value: "#EF4444"
2177
+ },
2178
+ {
2179
+ name: "Orange",
2180
+ value: "#F97316"
2181
+ },
2182
+ {
2183
+ name: "Amber",
2184
+ value: "#F59E0B"
2185
+ },
2186
+ {
2187
+ name: "Green",
2188
+ value: "#10B981"
2189
+ }
2190
+ ];
2191
+ const GRAY_COLORS = [
2192
+ {
2193
+ name: "Black",
2194
+ value: "#000000"
2195
+ },
2196
+ {
2197
+ name: "Gray 900",
2198
+ value: "#18181B"
2199
+ },
2200
+ {
2201
+ name: "Gray 600",
2202
+ value: "#52525B"
2203
+ },
2204
+ {
2205
+ name: "Gray 300",
2206
+ value: "#D4D4D8"
2207
+ },
2208
+ {
2209
+ name: "Gray 200",
2210
+ value: "#E4E4E7"
2211
+ },
2212
+ {
2213
+ name: "Gray 100",
2214
+ value: "#F4F4F5"
2215
+ },
2216
+ {
2217
+ name: "White",
2218
+ value: "#FFFFFF"
2219
+ }
2220
+ ];
2221
+ const ColorPickerContent = ({ value, onChange, onClear }) => {
2222
+ return /* @__PURE__ */ jsxs("div", {
2223
+ className: "flex flex-col gap-3",
2224
+ children: [/* @__PURE__ */ jsxs("div", {
2225
+ className: "flex flex-col gap-3",
2226
+ children: [/* @__PURE__ */ jsx("button", {
2227
+ type: "button",
2228
+ onClick: onClear,
2229
+ className: "border-border after:bg-destructive relative size-5 cursor-pointer rounded-md border bg-white after:absolute after:inset-0 after:top-1/2 after:left-1/2 after:z-1 after:flex after:h-0.5 after:w-7 after:-translate-x-1/2 after:-translate-y-1/2 after:-rotate-45 after:rounded-full after:content-['']",
2230
+ title: "Clear color",
2231
+ "aria-label": "Clear color"
2232
+ }), /* @__PURE__ */ jsxs("div", {
2233
+ className: "flex flex-wrap gap-1",
2234
+ children: [PREDEFINED_COLORS.map((color) => /* @__PURE__ */ jsx("button", {
2235
+ type: "button",
2236
+ className: cn("border-primary/20 size-5 cursor-pointer rounded-md border transition-all hover:scale-105"),
2237
+ style: { backgroundColor: color.value },
2238
+ onClick: () => onChange(color.value),
2239
+ title: color.name,
2240
+ "aria-label": color.name
2241
+ }, color.value)), GRAY_COLORS.map((color) => /* @__PURE__ */ jsx("button", {
2242
+ type: "button",
2243
+ className: cn("border-primary/20 size-5 cursor-pointer rounded-md border transition-all hover:scale-105"),
2244
+ style: { backgroundColor: color.value },
2245
+ onClick: () => onChange(color.value),
2246
+ title: color.name,
2247
+ "aria-label": color.name
2248
+ }, color.value))]
2249
+ })]
2250
+ }), /* @__PURE__ */ jsxs("div", {
2251
+ className: "flex flex-col gap-1.5",
2252
+ children: [/* @__PURE__ */ jsx("div", {
2253
+ className: "text-xs font-medium",
2254
+ children: "Custom Color"
2255
+ }), /* @__PURE__ */ jsxs("div", {
2256
+ className: "flex flex-col gap-2",
2257
+ children: [/* @__PURE__ */ jsx(HexColorPicker, {
2258
+ color: value || "#000000",
2259
+ onChange,
2260
+ className: "!w-full !h-32 color-picker"
2261
+ }), /* @__PURE__ */ jsx(Input, {
2262
+ type: "text",
2263
+ value: value || "",
2264
+ onChange: (e) => onChange(e.target.value),
2265
+ placeholder: "Select a color",
2266
+ onKeyDown: (e) => e.stopPropagation()
2267
+ })]
2268
+ })]
2269
+ })]
2270
+ });
2271
+ };
2272
+ const ColorPicker = ({ value, onChange }) => {
2273
+ return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsxs(PopoverTrigger, {
2274
+ className: cn("border-input text-foreground focus-visible:border-primary hover:bg-accent w-full justify-between gap-2 rounded-lg border bg-white px-3 py-2 text-sm transition-colors", "flex items-center"),
2275
+ children: [value ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
2276
+ className: "border-border size-5 rounded-md border",
2277
+ style: { backgroundColor: value }
2278
+ }), /* @__PURE__ */ jsx("span", {
2279
+ className: "flex-1 text-left",
2280
+ children: value
2281
+ })] }) : /* @__PURE__ */ jsxs("div", {
2282
+ className: "flex items-center justify-start gap-2",
2283
+ children: [/* @__PURE__ */ jsx("div", { className: "border-border after:bg-destructive relative size-5 rounded-md border bg-white after:absolute after:inset-0 after:top-1/2 after:left-1/2 after:z-1 after:flex after:h-0.5 after:w-7 after:-translate-x-1/2 after:-translate-y-1/2 after:-rotate-45 after:rounded-full after:content-['']" }), /* @__PURE__ */ jsx("span", { children: "No color" })]
2284
+ }), /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" })]
2285
+ }), /* @__PURE__ */ jsx(PopoverPopup, {
2286
+ align: "center",
2287
+ side: "bottom",
2288
+ className: "!w-full",
2289
+ children: /* @__PURE__ */ jsx(ColorPickerContent, {
2290
+ value,
2291
+ onChange,
2292
+ onClear: () => onChange("")
2293
+ })
2294
+ })] });
2295
+ };
2296
+ var ColorPicker_default = ColorPicker;
1920
2297
 
1921
2298
  //#endregion
1922
- //#region src/components/TablePagination/index.tsx
1923
- const TablePagination = ({ currentPage, totalPages, totalItems, itemsPerPage, onPageChange, onItemsPerPageChange, pageSizeOptions = [
1924
- 5,
1925
- 10,
1926
- 20,
1927
- 50,
1928
- 100
1929
- ], maxVisiblePages = 4, showInfo = true, showPageSizeSelect = true, className }) => {
1930
- const handleItemsPerPageChange = useCallback((value) => {
1931
- onItemsPerPageChange(Number(value));
1932
- }, [onItemsPerPageChange]);
1933
- const renderPaginationItems = useCallback(() => {
1934
- const items = [];
1935
- let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
1936
- let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);
1937
- if (endPage - startPage + 1 < maxVisiblePages) startPage = Math.max(1, endPage - maxVisiblePages + 1);
1938
- if (startPage > 1) {
1939
- items.push(/* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationLink, {
1940
- size: "icon",
1941
- onClick: (e) => {
1942
- e.preventDefault();
1943
- onPageChange(1);
1944
- },
1945
- children: "1"
1946
- }) }, "1"));
1947
- if (startPage > 2) items.push(/* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationEllipsis, {}) }, "ellipsis-start"));
1948
- }
1949
- for (let i = startPage; i <= endPage; i++) items.push(/* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationLink, {
1950
- size: "icon",
1951
- isActive: currentPage === i,
1952
- onClick: (e) => {
1953
- e.preventDefault();
1954
- onPageChange(i);
1955
- },
1956
- children: i
1957
- }) }, i));
1958
- if (endPage < totalPages) {
1959
- if (endPage < totalPages - 1) items.push(/* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationEllipsis, {}) }, "ellipsis-end"));
1960
- items.push(/* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationLink, {
1961
- size: "icon",
1962
- onClick: (e) => {
1963
- e.preventDefault();
1964
- onPageChange(totalPages);
1965
- },
1966
- children: totalPages
1967
- }) }, totalPages));
1968
- }
1969
- return items;
1970
- }, [
1971
- currentPage,
1972
- totalPages,
1973
- maxVisiblePages,
1974
- onPageChange
1975
- ]);
1976
- const startItem = totalItems === 0 ? 0 : (currentPage - 1) * itemsPerPage + 1;
1977
- const endItem = Math.min(currentPage * itemsPerPage, totalItems);
1978
- return /* @__PURE__ */ jsxs("div", {
1979
- className: cn("grid grid-cols-[1fr_auto_1fr] items-center gap-x-4", className),
1980
- children: [
1981
- showInfo && /* @__PURE__ */ jsx("div", {
1982
- className: "justify-self-start",
1983
- children: /* @__PURE__ */ jsxs("div", {
1984
- className: "text-muted-foreground text-sm",
1985
- children: [
1986
- "Showing ",
1987
- startItem,
1988
- " to ",
1989
- endItem,
1990
- " of ",
1991
- totalItems,
1992
- " results"
1993
- ]
2299
+ //#region src/components/RichTextMenuColorPicker/index.tsx
2300
+ /**
2301
+ * Pre-configured tiptap extensions for text color support.
2302
+ * Spread this into `tiptap.extensions` in your field config:
2303
+ * `extensions: [...richTextMenuColorPickerExtension]`
2304
+ */
2305
+ const richTextMenuColorPickerExtension = [TextStyle, Color];
2306
+ function RichTextMenuColorPicker({ editor, ...props }) {
2307
+ const [open, setOpen] = useState(false);
2308
+ const selectionRef = useRef(null);
2309
+ const [localColor, setLocalColor] = useState(null);
2310
+ useEffect(() => {
2311
+ if (open && editor) setLocalColor(editor.getAttributes("textStyle").color ?? null);
2312
+ }, [open, editor]);
2313
+ const handleColorChange = useCallback((color) => {
2314
+ setLocalColor(color || null);
2315
+ if (!editor) return;
2316
+ const chain = editor.chain();
2317
+ if (selectionRef.current) chain.setTextSelection(selectionRef.current);
2318
+ if (color === "") chain.unsetColor().run();
2319
+ else chain.setColor(color).run();
2320
+ }, [editor]);
2321
+ return /* @__PURE__ */ jsx("div", {
2322
+ ...props,
2323
+ children: /* @__PURE__ */ jsxs(Popover, {
2324
+ open,
2325
+ onOpenChange: setOpen,
2326
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
2327
+ render: /* @__PURE__ */ jsx("button", {
2328
+ type: "button",
2329
+ title: "Text color",
2330
+ onPointerDown: () => {
2331
+ if (editor) {
2332
+ const { from, to } = editor.state.selection;
2333
+ selectionRef.current = {
2334
+ from,
2335
+ to
2336
+ };
2337
+ }
2338
+ },
2339
+ onClick: (e) => {
2340
+ e.stopPropagation();
2341
+ },
2342
+ className: "inline-flex border h-full aspect-square cursor-pointer border-stone-200 bg-white items-center p-1.5 text-black hover:border-stone-300 hover:bg-stone-50 justify-center rounded-md transition-colors hover:bg-primary-500 hover:text-primary-500"
2343
+ }),
2344
+ children: /* @__PURE__ */ jsx(BaselineIcon, { className: "size-4.5" })
2345
+ }), /* @__PURE__ */ jsx(PopoverPopup, {
2346
+ side: "bottom",
2347
+ align: "start",
2348
+ sideOffset: 8,
2349
+ className: "max-w-54",
2350
+ children: /* @__PURE__ */ jsx("div", {
2351
+ "data-puck-rte-menu": true,
2352
+ children: /* @__PURE__ */ jsx(ColorPickerContent, {
2353
+ value: localColor ?? void 0,
2354
+ onChange: handleColorChange,
2355
+ onClear: () => handleColorChange("")
2356
+ })
1994
2357
  })
1995
- }),
1996
- showPageSizeSelect && /* @__PURE__ */ jsxs("div", {
1997
- className: "flex items-center gap-2 justify-self-center",
1998
- children: [/* @__PURE__ */ jsx("span", {
1999
- className: "text-muted-foreground text-sm",
2000
- children: "Per page"
2001
- }), /* @__PURE__ */ jsxs(Select, {
2002
- value: itemsPerPage.toString(),
2003
- onValueChange: handleItemsPerPageChange,
2004
- children: [/* @__PURE__ */ jsxs(SelectTrigger, {
2005
- className: "h-8 w-fit",
2006
- children: [/* @__PURE__ */ jsx(SelectValue, {}), /* @__PURE__ */ jsx(SelectIcon, { children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" }) })]
2007
- }), /* @__PURE__ */ jsx(SelectPopup, { children: /* @__PURE__ */ jsx(SelectList, { children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, {
2008
- value: size.toString(),
2009
- children: /* @__PURE__ */ jsx(SelectItemText, { children: size })
2010
- }, size)) }) })]
2011
- })]
2012
- }),
2013
- totalPages > 1 && /* @__PURE__ */ jsx("div", {
2014
- className: "justify-self-end",
2015
- children: /* @__PURE__ */ jsx(Pagination, { children: /* @__PURE__ */ jsxs(PaginationContent, { children: [
2016
- /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationPrevious, {
2017
- size: "default",
2018
- onClick: (e) => {
2019
- e.preventDefault();
2020
- if (currentPage > 1) onPageChange(currentPage - 1);
2021
- },
2022
- "aria-disabled": currentPage === 1,
2023
- className: cn(currentPage === 1 && "pointer-events-none opacity-50")
2024
- }) }),
2025
- renderPaginationItems(),
2026
- /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationNext, {
2027
- size: "default",
2028
- onClick: (e) => {
2029
- e.preventDefault();
2030
- if (currentPage < totalPages) onPageChange(currentPage + 1);
2031
- },
2032
- "aria-disabled": currentPage === totalPages,
2033
- className: cn(currentPage === totalPages && "pointer-events-none opacity-50")
2034
- }) })
2035
- ] }) })
2036
- })
2037
- ]
2358
+ })]
2359
+ })
2038
2360
  });
2039
- };
2361
+ }
2040
2362
 
2041
2363
  //#endregion
2042
2364
  //#region src/components/MediaPicker/index.tsx
2043
- const getEditorConfig$1 = () => {
2365
+ const getEditorConfig = () => {
2044
2366
  const editorEl = document.getElementById("editor");
2045
2367
  return {
2046
2368
  mediasUrl: editorEl?.dataset.mediasUrl || "/admin/pages/puck/medias",
@@ -2048,13 +2370,15 @@ const getEditorConfig$1 = () => {
2048
2370
  langId: editorEl?.dataset.langId || ""
2049
2371
  };
2050
2372
  };
2051
- const fetchMedias = async ({ query, filters, page = 1, limit = 10 }) => {
2052
- const { mediasUrl, langId } = getEditorConfig$1();
2373
+ const fetchMedias = async ({ query, filters, page = 1, limit = 10, sortBy, sortOrder }) => {
2374
+ const { mediasUrl, langId } = getEditorConfig();
2053
2375
  const params = new URLSearchParams();
2054
2376
  if (query) params.append("search", query);
2055
2377
  if (langId) params.append("lang_id", langId);
2056
2378
  params.append("page", page.toString());
2057
2379
  params.append("limit", limit.toString());
2380
+ if (sortBy) params.append("sort_by", sortBy);
2381
+ if (sortOrder) params.append("sort_order", sortOrder);
2058
2382
  if (filters) Object.entries(filters).forEach(([key, value]) => {
2059
2383
  params.append(key, value);
2060
2384
  });
@@ -2068,7 +2392,17 @@ const fetchMedias = async ({ query, filters, page = 1, limit = 10 }) => {
2068
2392
  total: 0
2069
2393
  };
2070
2394
  };
2071
- const MediaUploadZone = ({ onUploadSuccess, acceptedTypes = "image/*", maxSize = 10 }) => {
2395
+ const fetchMediaById = async (id) => {
2396
+ try {
2397
+ return (await fetchMedias({
2398
+ filters: { id: id.toString() },
2399
+ limit: 1
2400
+ })).items[0] ?? null;
2401
+ } catch {
2402
+ return null;
2403
+ }
2404
+ };
2405
+ const MediaUploadZone = ({ onUploadSuccess, acceptedTypes = "image/*,video/*,application/pdf", maxSize = 10 }) => {
2072
2406
  const [uploading, setUploading] = useState(false);
2073
2407
  const [uploadProgress, setUploadProgress] = useState(0);
2074
2408
  const [dragActive, setDragActive] = useState(false);
@@ -2077,14 +2411,17 @@ const MediaUploadZone = ({ onUploadSuccess, acceptedTypes = "image/*", maxSize =
2077
2411
  completed: 0
2078
2412
  });
2079
2413
  const getAcceptedTypesLabel = () => {
2080
- if (acceptedTypes.includes("image") && acceptedTypes.includes("video")) return "Images and Videos";
2081
- if (acceptedTypes.includes("video")) return "MP4, WebM, MOV";
2082
- return "PNG, JPG, GIF, WebP";
2414
+ const parts = [];
2415
+ if (acceptedTypes.includes("image")) parts.push("Images");
2416
+ if (acceptedTypes.includes("video")) parts.push("Videos");
2417
+ if (acceptedTypes.includes("pdf")) parts.push("PDF");
2418
+ if (acceptedTypes === "*" || acceptedTypes.includes("*/*")) return "All files";
2419
+ return parts.length > 0 ? parts.join(", ") : acceptedTypes;
2083
2420
  };
2084
2421
  const handleUploadSingle = useCallback((file) => {
2085
2422
  return new Promise((resolve, reject) => {
2086
2423
  try {
2087
- const { uploadUrl, langId } = getEditorConfig$1();
2424
+ const { uploadUrl, langId } = getEditorConfig();
2088
2425
  const csrfToken = document.querySelector("meta[name=\"csrf-token\"]");
2089
2426
  const formData = new FormData();
2090
2427
  formData.append("file", file);
@@ -2224,58 +2561,45 @@ const MediaUploadZone = ({ onUploadSuccess, acceptedTypes = "image/*", maxSize =
2224
2561
  const MediaPreview = ({ media, className }) => {
2225
2562
  if (media.type.toLowerCase().startsWith("video/")) return /* @__PURE__ */ jsx("video", {
2226
2563
  src: media.url,
2227
- className: cn("rounded object-cover", className),
2564
+ className: cn("h-auto w-full aspect-square border border-border rounded-md object-cover", className),
2228
2565
  controls: true,
2229
2566
  preload: "metadata"
2230
2567
  });
2231
2568
  return /* @__PURE__ */ jsx("img", {
2232
2569
  src: media.thumbnail,
2233
2570
  alt: media.name,
2234
- className: cn("rounded object-cover", className)
2571
+ className: cn("h-auto w-full aspect-square border border-border rounded-md object-cover", className)
2235
2572
  });
2236
2573
  };
2237
- const SOURCE_TYPE_OPTIONS$1 = [{
2238
- label: "Medias",
2239
- value: "media"
2240
- }, {
2241
- label: "URL",
2242
- value: "url"
2243
- }];
2244
- const DEFAULT_VALUE$1 = {
2574
+ const DEFAULT_VALUE = {
2245
2575
  type: "media",
2246
2576
  media: null
2247
2577
  };
2248
- const UrlField$1 = ({ value, onChange }) => {
2249
- return /* @__PURE__ */ jsx(Input, {
2250
- type: "text",
2251
- value,
2252
- onChange: useCallback((e) => {
2253
- onChange(e.target.value);
2254
- }, [onChange]),
2255
- placeholder: "https://example.com/image.jpg"
2256
- });
2257
- };
2578
+ const PAGE_SIZE = 10;
2258
2579
  const MediaLibraryModal = ({ value, onChange, mediaType, open, onOpenChange, acceptedTypes, maxSize }) => {
2259
2580
  const [medias, setMedias] = useState([]);
2260
2581
  const [loading, setLoading] = useState(false);
2261
- const [selectedMedia, setSelectedMedia] = useState(value);
2262
- const [currentPage, setCurrentPage] = useState(1);
2263
- const [totalPages, setTotalPages] = useState(1);
2264
2582
  const [totalItems, setTotalItems] = useState(0);
2265
2583
  const [searchQuery, setSearchQuery] = useState("");
2266
- const [itemsPerPage, setItemsPerPage] = useState(10);
2267
- const loadMedias = useCallback(async (page, limit, query) => {
2584
+ const [pagination, setPagination] = useState({
2585
+ pageIndex: 0,
2586
+ pageSize: PAGE_SIZE
2587
+ });
2588
+ const [sorting, setSorting] = useState([]);
2589
+ const loadMedias = useCallback(async (pageIndex, pageSize, query, sort = []) => {
2268
2590
  setLoading(true);
2269
2591
  try {
2592
+ const sortItem = sort[0];
2270
2593
  const result = await fetchMedias({
2271
- page,
2272
- limit,
2594
+ page: pageIndex + 1,
2595
+ limit: pageSize,
2273
2596
  query,
2597
+ sortBy: sortItem?.id,
2598
+ sortOrder: sortItem ? sortItem.desc ? "desc" : "asc" : void 0,
2274
2599
  filters: mediaType ? { type: mediaType } : void 0
2275
2600
  });
2276
2601
  setMedias(result.items);
2277
2602
  setTotalItems(result.total);
2278
- setTotalPages(Math.ceil(result.total / limit));
2279
2603
  } catch (error) {
2280
2604
  console.error("Error loading medias:", error);
2281
2605
  } finally {
@@ -2283,499 +2607,210 @@ const MediaLibraryModal = ({ value, onChange, mediaType, open, onOpenChange, acc
2283
2607
  }
2284
2608
  }, [mediaType]);
2285
2609
  useEffect(() => {
2286
- if (open) loadMedias(currentPage, itemsPerPage, searchQuery);
2610
+ if (open) loadMedias(pagination.pageIndex, pagination.pageSize, searchQuery, sorting);
2287
2611
  }, [
2288
2612
  open,
2289
- currentPage,
2290
- itemsPerPage,
2291
- loadMedias,
2292
- searchQuery
2613
+ pagination,
2614
+ sorting,
2615
+ searchQuery,
2616
+ loadMedias
2293
2617
  ]);
2294
2618
  const handleSearch = useCallback((query) => {
2295
2619
  setSearchQuery(query);
2296
- setCurrentPage(1);
2297
- }, []);
2298
- const handleItemsPerPageChange = useCallback((newLimit) => {
2299
- setItemsPerPage(newLimit);
2300
- setCurrentPage(1);
2620
+ setPagination((prev) => ({
2621
+ ...prev,
2622
+ pageIndex: 0
2623
+ }));
2301
2624
  }, []);
2302
- const handleMediaSelectAndConfirm = useCallback((media) => {
2303
- setSelectedMedia(media);
2625
+ const handleRowClick = useCallback((media) => {
2304
2626
  onChange(media);
2305
2627
  onOpenChange(false);
2306
2628
  }, [onChange, onOpenChange]);
2307
- const handleUploadSuccess = useCallback(async (media) => {
2308
- await loadMedias(1, itemsPerPage);
2309
- setCurrentPage(1);
2310
- setSelectedMedia(media);
2311
- }, [loadMedias, itemsPerPage]);
2312
- return /* @__PURE__ */ jsxs(DialogPopup, {
2313
- className: "max-w-4xl",
2314
- children: [
2315
- /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "Select Media" }) }),
2316
- /* @__PURE__ */ jsxs(DialogPanel, {
2317
- className: "flex flex-col gap-4",
2318
- children: [/* @__PURE__ */ jsxs(InputGroup, { children: [/* @__PURE__ */ jsx(InputGroupInput, {
2319
- placeholder: "Search...",
2320
- value: searchQuery,
2321
- onChange: (e) => handleSearch(e.target.value)
2322
- }), /* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(SearchIcon, { className: "size-4" }) })] }), loading ? /* @__PURE__ */ jsx("div", {
2323
- className: "flex items-center justify-center py-12",
2324
- children: /* @__PURE__ */ jsx(Loader2Icon, { className: "text-muted-foreground size-8 animate-spin" })
2325
- }) : medias.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
2326
- className: "border-border overflow-hidden rounded-lg border",
2327
- children: /* @__PURE__ */ jsxs(Table, { children: [/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
2328
- /* @__PURE__ */ jsx(TableHead, {
2329
- className: "w-20",
2330
- children: "Preview"
2331
- }),
2332
- /* @__PURE__ */ jsx(TableHead, { children: "Name" }),
2333
- /* @__PURE__ */ jsx(TableHead, { children: "Type" })
2334
- ] }) }), /* @__PURE__ */ jsx(TableBody, { children: medias.map((media) => /* @__PURE__ */ jsxs(TableRow, {
2335
- className: cn("hover:bg-muted/50 cursor-pointer transition-colors", selectedMedia?.id === media.id && "bg-primary/5"),
2336
- onClick: () => handleMediaSelectAndConfirm(media),
2337
- children: [
2338
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(MediaPreview, {
2339
- media,
2340
- className: "size-12"
2341
- }) }),
2342
- /* @__PURE__ */ jsx(TableCell, {
2343
- className: "font-medium",
2344
- children: media.name
2345
- }),
2346
- /* @__PURE__ */ jsx(TableCell, {
2347
- className: "text-muted-foreground text-sm",
2348
- children: media.type
2349
- })
2350
- ]
2351
- }, media.id)) })] })
2352
- }), /* @__PURE__ */ jsx(TablePagination, {
2353
- currentPage,
2354
- totalPages,
2355
- totalItems,
2356
- itemsPerPage,
2357
- onPageChange: setCurrentPage,
2358
- onItemsPerPageChange: handleItemsPerPageChange,
2359
- pageSizeOptions: [
2360
- 5,
2361
- 10,
2362
- 20,
2363
- 50
2364
- ]
2365
- })] }) : /* @__PURE__ */ jsxs("div", {
2366
- className: "text-muted-foreground flex flex-col items-center justify-center py-12 text-sm",
2367
- children: [/* @__PURE__ */ jsx(FileIcon, { className: "mb-2 size-12 opacity-20" }), /* @__PURE__ */ jsx("p", { children: "No media found" })]
2368
- })]
2369
- }),
2370
- /* @__PURE__ */ jsx(DialogFooter, { children: /* @__PURE__ */ jsx(MediaUploadZone, {
2371
- onUploadSuccess: handleUploadSuccess,
2372
- acceptedTypes,
2373
- maxSize
2374
- }) })
2375
- ]
2376
- });
2377
- };
2378
- const MediaLibraryField = ({ value, onChange, mediaType, acceptedTypes, maxSize }) => {
2379
- const [open, setOpen] = useState(false);
2380
- const [selectedMedia, setSelectedMedia] = useState(value);
2381
- useEffect(() => {
2382
- setSelectedMedia(value);
2383
- }, [value]);
2384
- const handleChange = useCallback((media) => {
2385
- setSelectedMedia(media);
2386
- onChange(media);
2387
- }, [onChange]);
2388
- const handleClear = useCallback(() => {
2389
- handleChange(null);
2390
- }, [handleChange]);
2391
- return /* @__PURE__ */ jsxs("div", {
2392
- className: "flex flex-col gap-3",
2393
- children: [/* @__PURE__ */ jsxs(Dialog, {
2394
- open,
2395
- onOpenChange: setOpen,
2396
- children: [/* @__PURE__ */ jsx(DialogTrigger, { render: /* @__PURE__ */ jsx(Button, {
2397
- variant: "outline",
2398
- className: "w-full",
2399
- children: selectedMedia ? "Change Media" : "Select Media"
2400
- }) }), /* @__PURE__ */ jsx(MediaLibraryModal, {
2401
- value: selectedMedia,
2402
- onChange: handleChange,
2403
- mediaType,
2404
- open,
2405
- onOpenChange: setOpen,
2406
- acceptedTypes,
2407
- maxSize
2408
- })]
2409
- }), selectedMedia && /* @__PURE__ */ jsxs("div", {
2410
- className: "border-border bg-background flex items-center gap-3 rounded-lg border p-3",
2411
- children: [
2412
- /* @__PURE__ */ jsx(MediaPreview, {
2413
- media: selectedMedia,
2414
- className: "size-16"
2415
- }),
2416
- /* @__PURE__ */ jsxs("div", {
2417
- className: "flex-1",
2418
- children: [/* @__PURE__ */ jsx("p", {
2419
- className: "text-sm font-medium",
2420
- children: selectedMedia.name
2421
- }), /* @__PURE__ */ jsx("p", {
2422
- className: "text-muted-foreground text-xs",
2423
- children: selectedMedia.type
2424
- })]
2425
- }),
2426
- /* @__PURE__ */ jsx(Button, {
2427
- variant: "ghost",
2428
- size: "sm",
2429
- onClick: handleClear,
2430
- children: "Clear"
2431
- })
2432
- ]
2433
- })]
2434
- });
2435
- };
2436
- const useMediaPicker = (initialValue, onChange) => {
2437
- const currentValue = initialValue || DEFAULT_VALUE$1;
2438
- return {
2439
- currentValue,
2440
- selectedType: currentValue.type || "media",
2441
- handleTypeChange: useCallback((newType) => {
2442
- onChange({
2443
- ...currentValue,
2444
- type: newType
2445
- });
2446
- }, [currentValue, onChange]),
2447
- handleUrlChange: useCallback((url) => {
2448
- onChange({
2449
- ...currentValue,
2450
- url
2451
- });
2452
- }, [currentValue, onChange]),
2453
- handleMediaChange: useCallback((media) => {
2454
- onChange({
2455
- ...currentValue,
2456
- media
2457
- });
2458
- }, [currentValue, onChange])
2459
- };
2460
- };
2461
- const MediaPicker = ({ value, onChange, mediaType, acceptedTypes = "image/*", maxSize = 10 }) => {
2462
- const { currentValue, selectedType, handleTypeChange, handleUrlChange, handleMediaChange } = useMediaPicker(value, onChange);
2463
- return /* @__PURE__ */ jsxs("div", {
2464
- className: "flex flex-col gap-y-3",
2465
- children: [
2466
- /* @__PURE__ */ jsx(RadioGroup, {
2467
- value: selectedType,
2468
- onValueChange: handleTypeChange,
2469
- className: "border-input flex w-fit flex-wrap divide-x divide-stone-200 overflow-hidden rounded-md border",
2470
- children: SOURCE_TYPE_OPTIONS$1.map((option) => /* @__PURE__ */ jsx("label", {
2471
- className: "flex-1",
2472
- children: /* @__PURE__ */ jsx(RadioGroupItem, {
2473
- layout: "horizontal",
2474
- value: option.value,
2475
- children: option.label
2476
- })
2477
- }, option.value))
2478
- }),
2479
- selectedType === "url" && /* @__PURE__ */ jsx(UrlField$1, {
2480
- value: currentValue.url || "",
2481
- onChange: handleUrlChange
2482
- }),
2483
- selectedType === "media" && /* @__PURE__ */ jsx(MediaLibraryField, {
2484
- value: currentValue.media || null,
2485
- onChange: handleMediaChange,
2486
- mediaType,
2487
- acceptedTypes,
2488
- maxSize
2489
- })
2490
- ]
2491
- });
2492
- };
2493
- const getMediaUrl = (value) => {
2494
- if (!value) return void 0;
2495
- if (value.type === "media" && value.media) return value.media.url;
2496
- return value.url;
2497
- };
2498
-
2499
- //#endregion
2500
- //#region src/components/PagePicker/index.tsx
2501
- const getEditorConfig = () => {
2502
- const editorEl = document.getElementById("editor");
2503
- return {
2504
- pagesUrl: editorEl?.dataset.pagesUrl || "/admin/pages/puck/pages",
2505
- langId: editorEl?.dataset.langId || ""
2506
- };
2507
- };
2508
- const fetchPages = async ({ query, filters, page = 1, limit = 10 }) => {
2509
- const { pagesUrl, langId } = getEditorConfig();
2510
- const params = new URLSearchParams();
2511
- if (query) params.append("search", query);
2512
- if (langId) params.append("lang_id", langId);
2513
- params.append("page", page.toString());
2514
- params.append("limit", limit.toString());
2515
- if (filters) Object.entries(filters).forEach(([key, value]) => {
2516
- params.append(key, value);
2517
- });
2518
- const data = await (await fetch(`${pagesUrl}?${params.toString()}`, { credentials: "same-origin" })).json();
2519
- if (data.success && data.pages) return {
2520
- items: data.pages,
2521
- total: data.total || data.pages.length
2522
- };
2523
- return {
2524
- items: [],
2525
- total: 0
2526
- };
2527
- };
2528
- const SOURCE_TYPE_OPTIONS = [{
2529
- label: "Pages",
2530
- value: "page"
2531
- }, {
2532
- label: "URL",
2533
- value: "url"
2534
- }];
2535
- const DEFAULT_VALUE = {
2536
- type: "page",
2537
- page: null
2538
- };
2539
- const UrlField = ({ value, onChange }) => {
2540
- return /* @__PURE__ */ jsx(Input, {
2541
- type: "text",
2542
- value,
2543
- onChange: useCallback((e) => {
2544
- onChange(e.target.value);
2545
- }, [onChange]),
2546
- placeholder: "/page-slug"
2547
- });
2548
- };
2549
- const PageLibraryModal = ({ value, onChange, open, onOpenChange }) => {
2550
- const [pages, setPages] = useState([]);
2551
- const [loading, setLoading] = useState(false);
2552
- const [selectedPage, setSelectedPage] = useState(value);
2553
- const [currentPage, setCurrentPage] = useState(1);
2554
- const [totalPages, setTotalPages] = useState(1);
2555
- const [totalItems, setTotalItems] = useState(0);
2556
- const [searchQuery, setSearchQuery] = useState("");
2557
- const [itemsPerPage, setItemsPerPage] = useState(10);
2558
- const loadPages = useCallback(async (page, limit, query) => {
2559
- setLoading(true);
2560
- try {
2561
- const result = await fetchPages({
2562
- page,
2563
- limit,
2564
- query
2565
- });
2566
- setPages(result.items);
2567
- setTotalItems(result.total);
2568
- setTotalPages(Math.ceil(result.total / limit));
2569
- } catch (error) {
2570
- console.error("Error loading pages:", error);
2571
- } finally {
2572
- setLoading(false);
2573
- }
2574
- }, []);
2575
- useEffect(() => {
2576
- if (open) loadPages(currentPage, itemsPerPage, searchQuery);
2629
+ const handleUploadSuccess = useCallback(async (_media) => {
2630
+ await loadMedias(0, pagination.pageSize, searchQuery, sorting);
2631
+ setPagination((prev) => ({
2632
+ ...prev,
2633
+ pageIndex: 0
2634
+ }));
2577
2635
  }, [
2578
- open,
2579
- currentPage,
2580
- itemsPerPage,
2581
- loadPages,
2582
- searchQuery
2636
+ loadMedias,
2637
+ pagination.pageSize,
2638
+ searchQuery,
2639
+ sorting
2583
2640
  ]);
2584
- const handleSearch = useCallback((query) => {
2585
- setSearchQuery(query);
2586
- setCurrentPage(1);
2587
- }, []);
2588
- const handleItemsPerPageChange = useCallback((newLimit) => {
2589
- setItemsPerPage(newLimit);
2590
- setCurrentPage(1);
2591
- }, []);
2592
- const handlePageSelectAndConfirm = useCallback((page) => {
2593
- setSelectedPage(page);
2594
- onChange(page);
2595
- onOpenChange(false);
2596
- }, [onChange, onOpenChange]);
2597
- return /* @__PURE__ */ jsxs(DialogPopup, {
2598
- className: "max-w-4xl",
2599
- children: [/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "Select Page" }) }), /* @__PURE__ */ jsxs(DialogPanel, {
2600
- className: "flex flex-col gap-4",
2601
- children: [/* @__PURE__ */ jsxs(InputGroup, { children: [/* @__PURE__ */ jsx(InputGroupInput, {
2602
- placeholder: "Search pages...",
2603
- value: searchQuery,
2604
- onChange: (e) => handleSearch(e.target.value)
2605
- }), /* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(SearchIcon, { className: "size-4" }) })] }), loading ? /* @__PURE__ */ jsx("div", {
2606
- className: "flex items-center justify-center py-12",
2607
- children: /* @__PURE__ */ jsx(Loader2Icon, { className: "text-muted-foreground size-8 animate-spin" })
2608
- }) : pages.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
2609
- className: "border-border overflow-hidden rounded-lg border",
2610
- children: /* @__PURE__ */ jsxs(Table, { children: [/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
2611
- /* @__PURE__ */ jsx(TableHead, { children: "Title" }),
2612
- /* @__PURE__ */ jsx(TableHead, { children: "Slug" }),
2613
- /* @__PURE__ */ jsx(TableHead, { children: "Status" })
2614
- ] }) }), /* @__PURE__ */ jsx(TableBody, { children: pages.map((page) => /* @__PURE__ */ jsxs(TableRow, {
2615
- className: cn("hover:bg-muted/50 cursor-pointer transition-colors", selectedPage?.id === page.id && "bg-primary/5"),
2616
- onClick: () => handlePageSelectAndConfirm(page),
2617
- children: [
2618
- /* @__PURE__ */ jsx(TableCell, {
2619
- className: "font-medium",
2620
- children: page.name
2621
- }),
2622
- /* @__PURE__ */ jsx(TableCell, {
2623
- className: "text-muted-foreground text-sm",
2624
- children: toRelativeUrl(page.url)
2625
- }),
2626
- /* @__PURE__ */ jsx(TableCell, {
2627
- className: "text-muted-foreground text-sm",
2628
- children: page.status || "published"
2629
- })
2630
- ]
2631
- }, page.id)) })] })
2632
- }), /* @__PURE__ */ jsx(TablePagination, {
2633
- currentPage,
2634
- totalPages,
2635
- totalItems,
2636
- itemsPerPage,
2637
- onPageChange: setCurrentPage,
2638
- onItemsPerPageChange: handleItemsPerPageChange,
2639
- pageSizeOptions: [
2640
- 5,
2641
- 10,
2642
- 20,
2643
- 50
2644
- ]
2645
- })] }) : /* @__PURE__ */ jsxs("div", {
2646
- className: "text-muted-foreground flex flex-col items-center justify-center py-12 text-sm",
2647
- children: [/* @__PURE__ */ jsx(FileTextIcon, { className: "mb-2 size-12 opacity-20" }), /* @__PURE__ */ jsx("p", { children: "No pages found" })]
2648
- })]
2649
- })]
2641
+ return /* @__PURE__ */ jsx(PickerModal, {
2642
+ title: "Select Media",
2643
+ searchQuery,
2644
+ onSearch: handleSearch,
2645
+ columns: useMemo(() => [
2646
+ {
2647
+ id: "thumbnail",
2648
+ header: "Preview",
2649
+ size: 80,
2650
+ enableSorting: false,
2651
+ cell: ({ row }) => /* @__PURE__ */ jsx(MediaPreview, {
2652
+ media: row.original,
2653
+ className: "size-12"
2654
+ })
2655
+ },
2656
+ {
2657
+ accessorKey: "name",
2658
+ header: "Name",
2659
+ cell: ({ row }) => /* @__PURE__ */ jsx("div", {
2660
+ className: "font-medium",
2661
+ children: row.getValue("name")
2662
+ })
2663
+ },
2664
+ {
2665
+ accessorKey: "type",
2666
+ header: "Type",
2667
+ size: 140,
2668
+ cell: ({ row }) => /* @__PURE__ */ jsx(Badge, {
2669
+ variant: "outline",
2670
+ children: row.getValue("type")
2671
+ })
2672
+ }
2673
+ ], []),
2674
+ data: medias,
2675
+ loading,
2676
+ totalItems,
2677
+ selectedId: value?.id,
2678
+ onRowClick: handleRowClick,
2679
+ pagination,
2680
+ onPaginationChange: setPagination,
2681
+ sorting,
2682
+ onSortingChange: setSorting,
2683
+ emptyIcon: /* @__PURE__ */ jsx(FileIcon, { className: "mb-2 size-12 opacity-20" }),
2684
+ emptyMessage: "No media found",
2685
+ footer: /* @__PURE__ */ jsx(MediaUploadZone, {
2686
+ onUploadSuccess: handleUploadSuccess,
2687
+ acceptedTypes,
2688
+ maxSize
2689
+ })
2650
2690
  });
2651
2691
  };
2652
- const PageLibraryField = ({ value, onChange }) => {
2692
+ const MediaPicker = ({ value, onChange, mediaType, acceptedTypes = "image/*,video/*,application/pdf", maxSize = 10 }) => {
2653
2693
  const [open, setOpen] = useState(false);
2654
- const [selectedPage, setSelectedPage] = useState(value);
2655
- useEffect(() => {
2656
- setSelectedPage(value);
2657
- }, [value]);
2658
- const handleChange = useCallback((page) => {
2659
- setSelectedPage(page);
2660
- onChange(page);
2661
- }, [onChange]);
2662
- const handleClear = useCallback(() => {
2663
- handleChange(null);
2664
- }, [handleChange]);
2665
- return /* @__PURE__ */ jsxs("div", {
2694
+ const currentValue = value || DEFAULT_VALUE;
2695
+ const displayValue = currentValue.type === "media" && currentValue.media ? currentValue.media.name : currentValue.url || "";
2696
+ const hasValue = Boolean(currentValue.type === "media" && currentValue.media || currentValue.type === "url" && currentValue.url);
2697
+ const handleInputChange = (e) => {
2698
+ onChange({
2699
+ type: "url",
2700
+ url: e.target.value
2701
+ });
2702
+ };
2703
+ const handleMediaChange = (media) => {
2704
+ onChange({
2705
+ type: "media",
2706
+ media: {
2707
+ id: media.id,
2708
+ name: media.name,
2709
+ thumbnail: media.thumbnail
2710
+ }
2711
+ });
2712
+ };
2713
+ const handleClear = () => {
2714
+ onChange(DEFAULT_VALUE);
2715
+ };
2716
+ return /* @__PURE__ */ jsx("div", {
2666
2717
  className: "flex flex-col gap-3",
2667
- children: [/* @__PURE__ */ jsxs(Dialog, {
2718
+ children: /* @__PURE__ */ jsxs(Dialog, {
2668
2719
  open,
2669
2720
  onOpenChange: setOpen,
2670
- children: [/* @__PURE__ */ jsx(DialogTrigger, { render: /* @__PURE__ */ jsx(Button, {
2671
- variant: "outline",
2672
- className: "w-full",
2673
- children: selectedPage ? "Change Page" : "Select Page"
2674
- }) }), /* @__PURE__ */ jsx(PageLibraryModal, {
2675
- value: selectedPage,
2676
- onChange: handleChange,
2721
+ children: [/* @__PURE__ */ jsx("div", {
2722
+ className: "flex items-center gap-2",
2723
+ children: /* @__PURE__ */ jsxs(InputGroup, { children: [
2724
+ currentValue.type === "media" && currentValue.media?.thumbnail && /* @__PURE__ */ jsx(InputGroupAddon, {
2725
+ align: "inline-start",
2726
+ className: "pl-1.5",
2727
+ children: /* @__PURE__ */ jsx("img", {
2728
+ src: currentValue.media.thumbnail,
2729
+ alt: currentValue.media.name,
2730
+ className: cn("max-h-12 my-1.5 aspect-square border border-border rounded-md object-cover")
2731
+ })
2732
+ }),
2733
+ /* @__PURE__ */ jsx(InputGroupInput, {
2734
+ placeholder: "https://example.com/image.jpg",
2735
+ type: "text",
2736
+ value: displayValue,
2737
+ onChange: handleInputChange
2738
+ }),
2739
+ /* @__PURE__ */ jsx(InputGroupAddon, {
2740
+ align: "inline-end",
2741
+ children: hasValue ? /* @__PURE__ */ jsx(Button, {
2742
+ size: "icon-xs",
2743
+ variant: "ghost",
2744
+ onClick: handleClear,
2745
+ children: /* @__PURE__ */ jsx(XIcon, { "aria-hidden": "true" })
2746
+ }) : /* @__PURE__ */ jsx(DialogTrigger, { render: /* @__PURE__ */ jsx(Button, {
2747
+ size: "icon-xs",
2748
+ variant: "outline",
2749
+ children: /* @__PURE__ */ jsx(DatabaseIcon, { className: "size-3.5" })
2750
+ }) })
2751
+ })
2752
+ ] })
2753
+ }), /* @__PURE__ */ jsx(MediaLibraryModal, {
2754
+ value: currentValue.media || null,
2755
+ onChange: handleMediaChange,
2756
+ mediaType,
2677
2757
  open,
2678
- onOpenChange: setOpen
2679
- })]
2680
- }), selectedPage && /* @__PURE__ */ jsxs("div", {
2681
- className: "border-border bg-background flex items-center gap-3 rounded-lg border p-3",
2682
- children: [/* @__PURE__ */ jsxs("div", {
2683
- className: "flex-1",
2684
- children: [/* @__PURE__ */ jsx("p", {
2685
- className: "text-sm font-medium",
2686
- children: selectedPage.name
2687
- }), /* @__PURE__ */ jsx("p", {
2688
- className: "text-muted-foreground text-xs",
2689
- children: toRelativeUrl(selectedPage.url)
2690
- })]
2691
- }), /* @__PURE__ */ jsx(Button, {
2692
- variant: "ghost",
2693
- size: "sm",
2694
- onClick: handleClear,
2695
- children: "Clear"
2758
+ onOpenChange: setOpen,
2759
+ acceptedTypes,
2760
+ maxSize
2696
2761
  })]
2697
- })]
2762
+ })
2698
2763
  });
2699
2764
  };
2700
- const usePagePicker = (initialValue, onChange) => {
2701
- const currentValue = initialValue || DEFAULT_VALUE;
2702
- return {
2703
- currentValue,
2704
- selectedType: currentValue.type || "page",
2705
- handleTypeChange: useCallback((newType) => {
2706
- onChange({
2707
- ...currentValue,
2708
- type: newType
2709
- });
2710
- }, [currentValue, onChange]),
2711
- handleUrlChange: useCallback((url) => {
2712
- onChange({
2713
- ...currentValue,
2714
- url
2715
- });
2716
- }, [currentValue, onChange]),
2717
- handlePageChange: useCallback((page) => {
2718
- onChange({
2719
- ...currentValue,
2720
- page
2721
- });
2722
- }, [currentValue, onChange])
2723
- };
2724
- };
2725
- const PagePicker = ({ value, onChange }) => {
2726
- const { currentValue, selectedType, handleTypeChange, handleUrlChange, handlePageChange } = usePagePicker(value, onChange);
2727
- return /* @__PURE__ */ jsxs("div", {
2728
- className: "flex flex-col gap-y-3",
2729
- children: [
2730
- /* @__PURE__ */ jsx(RadioGroup, {
2731
- value: selectedType,
2732
- onValueChange: handleTypeChange,
2733
- className: "border-input flex w-fit flex-wrap divide-x divide-stone-200 overflow-hidden rounded-md border",
2734
- children: SOURCE_TYPE_OPTIONS.map((option) => /* @__PURE__ */ jsx("label", {
2735
- className: "flex-1",
2736
- children: /* @__PURE__ */ jsx(RadioGroupItem, {
2737
- layout: "horizontal",
2738
- value: option.value,
2739
- children: option.label
2740
- })
2741
- }, option.value))
2742
- }),
2743
- selectedType === "url" && /* @__PURE__ */ jsx(UrlField, {
2744
- value: currentValue.url || "",
2745
- onChange: handleUrlChange
2746
- }),
2747
- selectedType === "page" && /* @__PURE__ */ jsx(PageLibraryField, {
2748
- value: currentValue.page || null,
2749
- onChange: handlePageChange
2750
- })
2751
- ]
2752
- });
2765
+ /**
2766
+ * Retourne l'URL directe si le type est "url".
2767
+ * Pour les références média (`type: "media"`), utiliser `useMediaUrl` à la place.
2768
+ */
2769
+ const getMediaUrl = (value) => {
2770
+ if (!value) return void 0;
2771
+ if (value.type === "url") return value.url;
2753
2772
  };
2754
2773
  /**
2755
- * Converts an absolute URL to a relative URL by extracting the pathname.
2756
- * If the URL is already relative, returns it as-is.
2774
+ * Hook React qui résout dynamiquement l'URL courante d'un `MediaPickerValue`.
2775
+ *
2776
+ * Pour les références média (`type: "media"`), l'URL est récupérée depuis
2777
+ * l'API à partir de l'`id` du média — ce qui garantit que le lien reste
2778
+ * valide même si l'URL du fichier a été modifiée après la sélection.
2757
2779
  *
2758
2780
  * @example
2759
- * toRelativeUrl("https://example.com/page?foo=bar#section") // "/page?foo=bar#section"
2760
- * toRelativeUrl("/page") // "/page"
2761
- * toRelativeUrl("") // ""
2781
+ * const { url, loading } = useMediaUrl(value)
2782
+ * return loading ? <Spinner /> : <img src={url} />
2762
2783
  */
2763
- const toRelativeUrl = (url) => {
2764
- if (!url) return "";
2765
- if (url.startsWith("/")) return url;
2766
- try {
2767
- const { pathname, search, hash } = new URL(url);
2768
- return pathname + search + hash;
2769
- } catch {
2770
- return url;
2771
- }
2772
- };
2773
- const getPageUrl = (value) => {
2774
- if (!value) return void 0;
2775
- let url;
2776
- if (value.type === "page" && value.page) url = value.page.url;
2777
- else url = value.url;
2778
- return url ? toRelativeUrl(url) : void 0;
2784
+ const useMediaUrl = (value) => {
2785
+ const [url, setUrl] = useState(void 0);
2786
+ const [loading, setLoading] = useState(false);
2787
+ const mediaId = value?.type === "media" ? value.media?.id : void 0;
2788
+ const directUrl = value?.type === "url" ? value.url : void 0;
2789
+ useEffect(() => {
2790
+ if (directUrl !== void 0) {
2791
+ setUrl(directUrl || void 0);
2792
+ return;
2793
+ }
2794
+ if (mediaId !== void 0) {
2795
+ let cancelled = false;
2796
+ setLoading(true);
2797
+ fetchMediaById(mediaId).then((media) => {
2798
+ if (!cancelled) setUrl(media ? media.url : void 0);
2799
+ }).catch(() => {
2800
+ if (!cancelled) setUrl(void 0);
2801
+ }).finally(() => {
2802
+ if (!cancelled) setLoading(false);
2803
+ });
2804
+ return () => {
2805
+ cancelled = true;
2806
+ };
2807
+ }
2808
+ setUrl(void 0);
2809
+ }, [mediaId, directUrl]);
2810
+ return {
2811
+ url,
2812
+ loading
2813
+ };
2779
2814
  };
2780
2815
 
2781
2816
  //#endregion
@@ -3086,6 +3121,321 @@ function AnchoredToasts() {
3086
3121
  });
3087
3122
  }
3088
3123
 
3124
+ //#endregion
3125
+ //#region src/blocks/Template/index.tsx
3126
+ const usePuck = createUsePuck();
3127
+ /**
3128
+ * Module-level cache keyed by storageKey.
3129
+ * Populated when the field is rendered; consumed by resolveData.
3130
+ */
3131
+ const _resolveCache = /* @__PURE__ */ new Map();
3132
+ const resolveApiUrl = (apiUrl) => {
3133
+ if (!apiUrl) return void 0;
3134
+ return typeof apiUrl === "function" ? apiUrl() : apiUrl;
3135
+ };
3136
+ /**
3137
+ * Factory that returns a ready-to-use Puck `ComponentConfig` for a Template
3138
+ * block.
3139
+ *
3140
+ * Without `apiUrl` — templates are saved in `localStorage` (per-browser).
3141
+ * With `apiUrl` — templates are saved in a database and shared across all
3142
+ * users and devices.
3143
+ *
3144
+ * @example
3145
+ * // Basic (localStorage)
3146
+ * Template: createTemplateBlock({ storageKey: 'my-project' })
3147
+ *
3148
+ * // Database-backed (shared)
3149
+ * Template: createTemplateBlock({
3150
+ * storageKey: 'my-project',
3151
+ * apiUrl: () => document.getElementById('editor')?.dataset.templatesUrl,
3152
+ * getHeaders: () => ({ 'X-CSRF-TOKEN': getCsrfToken() }),
3153
+ * })
3154
+ */
3155
+ function createTemplateBlock(options = {}) {
3156
+ const { storageKey = "puck-template", defaultTemplates = {}, apiUrl, getHeaders } = options;
3157
+ const localStorageKey = `puck-templates:${storageKey}`;
3158
+ const useApi = !!apiUrl;
3159
+ /** Read saved templates from the appropriate storage. */
3160
+ const getStoredTemplates = () => {
3161
+ if (useApi) return _resolveCache.get(storageKey) ?? {};
3162
+ try {
3163
+ return JSON.parse(localStorage.getItem(localStorageKey) ?? "{}");
3164
+ } catch {
3165
+ return {};
3166
+ }
3167
+ };
3168
+ return {
3169
+ fields: {
3170
+ template: {
3171
+ type: "custom",
3172
+ render: ({ name, value, onChange }) => {
3173
+ const config = usePuck((s) => s.config);
3174
+ const props = usePuck((s) => s.selectedItem?.props);
3175
+ const [apiTemplates, setApiTemplates] = useState([]);
3176
+ const [localTemplates, setLocalTemplates] = useState(useApi ? {} : JSON.parse(localStorage.getItem(localStorageKey) ?? "{}"));
3177
+ const [isLoading, setIsLoading] = useState(useApi);
3178
+ const [isSaving, setIsSaving] = useState(false);
3179
+ const [newTemplateName, setNewTemplateName] = useState("");
3180
+ useEffect(() => {
3181
+ if (!useApi) return;
3182
+ const url = resolveApiUrl(apiUrl);
3183
+ if (!url) {
3184
+ setIsLoading(false);
3185
+ return;
3186
+ }
3187
+ setIsLoading(true);
3188
+ fetch(`${url}?key=${encodeURIComponent(storageKey)}`, {
3189
+ headers: {
3190
+ Accept: "application/json",
3191
+ ...getHeaders?.() ?? {}
3192
+ },
3193
+ credentials: "same-origin"
3194
+ }).then((r) => r.json()).then((json) => {
3195
+ const tpls = json.templates ?? [];
3196
+ setApiTemplates(tpls);
3197
+ syncCache(tpls);
3198
+ }).catch(() => {}).finally(() => setIsLoading(false));
3199
+ }, []);
3200
+ const syncCache = (tpls) => {
3201
+ const cached = {};
3202
+ tpls.forEach((t) => {
3203
+ cached[String(t.id)] = {
3204
+ label: t.name,
3205
+ data: t.data
3206
+ };
3207
+ });
3208
+ _resolveCache.set(storageKey, cached);
3209
+ };
3210
+ const handleSave = async () => {
3211
+ if (!props?.children?.length) return;
3212
+ setIsSaving(true);
3213
+ try {
3214
+ const data = props.children.map((child) => {
3215
+ return walkTree({
3216
+ type: child.type,
3217
+ props: {
3218
+ ...child.props,
3219
+ id: crypto.randomUUID()
3220
+ }
3221
+ }, config, (content) => content.map((item) => ({
3222
+ ...item,
3223
+ props: {
3224
+ ...item.props,
3225
+ id: crypto.randomUUID()
3226
+ }
3227
+ })));
3228
+ });
3229
+ const label = newTemplateName.trim() || (/* @__PURE__ */ new Date()).toLocaleString();
3230
+ if (useApi) {
3231
+ const url = resolveApiUrl(apiUrl);
3232
+ const created = (await (await fetch(url, {
3233
+ method: "POST",
3234
+ headers: {
3235
+ "Content-Type": "application/json",
3236
+ Accept: "application/json",
3237
+ ...getHeaders?.() ?? {}
3238
+ },
3239
+ credentials: "same-origin",
3240
+ body: JSON.stringify({
3241
+ key: storageKey,
3242
+ name: label,
3243
+ data
3244
+ })
3245
+ })).json()).template;
3246
+ const updated = [...apiTemplates, created];
3247
+ setApiTemplates(updated);
3248
+ syncCache(updated);
3249
+ onChange(String(created.id));
3250
+ } else {
3251
+ const templateId = crypto.randomUUID();
3252
+ const updated = {
3253
+ ...localTemplates,
3254
+ [templateId]: {
3255
+ label,
3256
+ data
3257
+ }
3258
+ };
3259
+ localStorage.setItem(localStorageKey, JSON.stringify(updated));
3260
+ setLocalTemplates(updated);
3261
+ onChange(templateId);
3262
+ }
3263
+ setNewTemplateName("");
3264
+ } finally {
3265
+ setIsSaving(false);
3266
+ }
3267
+ };
3268
+ const handleDelete = async (templateValue) => {
3269
+ if (useApi) {
3270
+ const url = resolveApiUrl(apiUrl);
3271
+ await fetch(`${url}/${templateValue}`, {
3272
+ method: "DELETE",
3273
+ headers: {
3274
+ Accept: "application/json",
3275
+ ...getHeaders?.() ?? {}
3276
+ },
3277
+ credentials: "same-origin"
3278
+ });
3279
+ const updated = apiTemplates.filter((t) => String(t.id) !== templateValue);
3280
+ setApiTemplates(updated);
3281
+ syncCache(updated);
3282
+ } else {
3283
+ const { [templateValue]: _, ...rest } = localTemplates;
3284
+ localStorage.setItem(localStorageKey, JSON.stringify(rest));
3285
+ setLocalTemplates(rest);
3286
+ }
3287
+ if (value === templateValue) onChange("blank");
3288
+ };
3289
+ const builtInOptions = [{
3290
+ label: "Blank",
3291
+ value: "blank"
3292
+ }, ...Object.entries(defaultTemplates).map(([k, t]) => ({
3293
+ value: k,
3294
+ label: t.label
3295
+ }))];
3296
+ const savedOptions = useApi ? apiTemplates.map((t) => ({
3297
+ value: String(t.id),
3298
+ label: t.name
3299
+ })) : Object.entries(localTemplates).map(([k, t]) => ({
3300
+ value: k,
3301
+ label: t.label
3302
+ }));
3303
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
3304
+ className: "flex flex-col gap-3",
3305
+ children: [isLoading ? /* @__PURE__ */ jsxs(Label$2, {
3306
+ className: "justify-start",
3307
+ children: [/* @__PURE__ */ jsx(Loader2Icon, {
3308
+ size: 16,
3309
+ className: "animate-spin"
3310
+ }), "Templates loading..."]
3311
+ }) : /* @__PURE__ */ jsx(AutoField, {
3312
+ value,
3313
+ onChange,
3314
+ field: {
3315
+ label: "Select a template",
3316
+ type: "select",
3317
+ options: [...builtInOptions, ...savedOptions]
3318
+ }
3319
+ }), savedOptions.length > 0 && /* @__PURE__ */ jsx("div", {
3320
+ style: {
3321
+ marginTop: 8,
3322
+ borderTop: "1px solid var(--puck-color-grey-09)",
3323
+ paddingTop: 8
3324
+ },
3325
+ children: savedOptions.map((opt) => /* @__PURE__ */ jsxs("div", {
3326
+ style: {
3327
+ display: "flex",
3328
+ alignItems: "center",
3329
+ justifyContent: "space-between",
3330
+ padding: "3px 0",
3331
+ fontSize: 11,
3332
+ color: "var(--puck-color-grey-04)"
3333
+ },
3334
+ children: [/* @__PURE__ */ jsx("span", {
3335
+ style: {
3336
+ overflow: "hidden",
3337
+ textOverflow: "ellipsis",
3338
+ whiteSpace: "nowrap",
3339
+ marginRight: 4
3340
+ },
3341
+ children: opt.label
3342
+ }), /* @__PURE__ */ jsx("button", {
3343
+ onClick: () => handleDelete(opt.value),
3344
+ style: {
3345
+ background: "none",
3346
+ border: "none",
3347
+ cursor: "pointer",
3348
+ padding: 2,
3349
+ color: "var(--puck-color-rose-06, #e11d48)",
3350
+ flexShrink: 0,
3351
+ display: "flex",
3352
+ alignItems: "center"
3353
+ },
3354
+ title: "Supprimer ce template",
3355
+ type: "button",
3356
+ children: /* @__PURE__ */ jsx(Trash2Icon, { size: 12 })
3357
+ })]
3358
+ }, opt.value))
3359
+ })]
3360
+ }), /* @__PURE__ */ jsxs("div", {
3361
+ className: "flex flex-col gap-3",
3362
+ children: [
3363
+ /* @__PURE__ */ jsx(Label$2, {
3364
+ className: "mb-0",
3365
+ children: "Nom du template"
3366
+ }),
3367
+ /* @__PURE__ */ jsx(Input, {
3368
+ type: "text",
3369
+ value: newTemplateName,
3370
+ onChange: (e) => setNewTemplateName(e.target.value),
3371
+ onKeyDown: (e) => {
3372
+ if (e.key === "Enter" && !isSaving && props?.children?.length) handleSave();
3373
+ },
3374
+ placeholder: (/* @__PURE__ */ new Date()).toLocaleString()
3375
+ }),
3376
+ /* @__PURE__ */ jsx(Button, {
3377
+ variant: "outline",
3378
+ onClick: handleSave,
3379
+ disabled: isSaving || !props?.children?.length,
3380
+ children: isSaving ? "Sauvegarde…" : "Sauvegarder comme template"
3381
+ })
3382
+ ]
3383
+ })] });
3384
+ }
3385
+ },
3386
+ children: { type: "slot" }
3387
+ },
3388
+ defaultProps: {
3389
+ template: "blank",
3390
+ children: []
3391
+ },
3392
+ resolveData: async (data, { changed, trigger }) => {
3393
+ if (!changed.template || trigger === "load") return data;
3394
+ const allTemplates = {
3395
+ blank: {
3396
+ label: "Blank",
3397
+ data: []
3398
+ },
3399
+ ...defaultTemplates,
3400
+ ...getStoredTemplates()
3401
+ };
3402
+ if (useApi && !allTemplates[data.props.template]) try {
3403
+ const url = resolveApiUrl(apiUrl);
3404
+ if (url) {
3405
+ const tpls = (await (await fetch(`${url}?key=${encodeURIComponent(storageKey)}`, {
3406
+ headers: {
3407
+ Accept: "application/json",
3408
+ ...getHeaders?.() ?? {}
3409
+ },
3410
+ credentials: "same-origin"
3411
+ })).json()).templates ?? [];
3412
+ const cached = {};
3413
+ tpls.forEach((t) => {
3414
+ cached[String(t.id)] = {
3415
+ label: t.name,
3416
+ data: t.data
3417
+ };
3418
+ });
3419
+ _resolveCache.set(storageKey, cached);
3420
+ Object.assign(allTemplates, cached);
3421
+ }
3422
+ } catch {}
3423
+ const children = allTemplates[data.props.template]?.data ?? allTemplates["blank"].data;
3424
+ return {
3425
+ ...data,
3426
+ props: {
3427
+ ...data.props,
3428
+ children
3429
+ }
3430
+ };
3431
+ },
3432
+ render: ({ children: Children$1 }) => /* @__PURE__ */ jsx("div", {
3433
+ className: "flex flex-col md:grid",
3434
+ children: /* @__PURE__ */ jsx(Children$1, {})
3435
+ })
3436
+ };
3437
+ }
3438
+
3089
3439
  //#endregion
3090
3440
  //#region src/utils/animation.tsx
3091
3441
  const animationField = { animation: {
@@ -3190,6 +3540,112 @@ function animationToAttributes(animation) {
3190
3540
  }
3191
3541
  const animationDefaultProps = { animation: "" };
3192
3542
 
3543
+ //#endregion
3544
+ //#region src/components/ui/group.tsx
3545
+ const groupVariants = cva("flex w-fit *:focus-visible:z-1 has-[>[data-slot=group]]:gap-2 *:has-focus-visible:z-1 dark:*:[[data-slot=separator]:has(~button:hover):not(:has(~[data-slot=separator]~[data-slot]:hover)),[data-slot=separator]:has(~[data-slot][data-pressed]):not(:has(~[data-slot=separator]~[data-slot][data-pressed]))]:before:bg-input/64 dark:*:[button:hover~[data-slot=separator]:not([data-slot]:hover~[data-slot=separator]~[data-slot=separator]),[data-slot][data-pressed]~[data-slot=separator]:not([data-slot][data-pressed]~[data-slot=separator]~[data-slot=separator])]:before:bg-input/64", {
3546
+ defaultVariants: { orientation: "horizontal" },
3547
+ variants: { orientation: {
3548
+ horizontal: "*:[[data-slot]~[data-slot]:not([data-slot=separator])]:before:-start-[0.5px] *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:-end-[0.5px] *:pointer-coarse:after:min-w-auto *:data-slot:has-[~[data-slot]]:rounded-e-none *:data-slot:has-[~[data-slot]]:border-e-0 *:data-slot:has-[~[data-slot]]:before:rounded-e-none *:[[data-slot]~[data-slot]]:rounded-s-none *:[[data-slot]~[data-slot]]:border-s-0 *:[[data-slot]~[data-slot]]:before:rounded-s-none",
3549
+ vertical: "*:[[data-slot]~[data-slot]:not([data-slot=separator])]:before:-top-[0.5px] *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:-bottom-[0.5px] flex-col *:pointer-coarse:after:min-h-auto *:data-slot:has-[~[data-slot]]:rounded-b-none *:data-slot:has-[~[data-slot]]:border-b-0 *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:hidden *:data-slot:has-[~[data-slot]]:before:rounded-b-none dark:*:last:before:hidden dark:*:first:before:block *:[[data-slot]~[data-slot]]:rounded-t-none *:[[data-slot]~[data-slot]]:border-t-0 *:[[data-slot]~[data-slot]]:before:rounded-t-none"
3550
+ } }
3551
+ });
3552
+ function Group({ className, orientation, children, ...props }) {
3553
+ return /* @__PURE__ */ jsx("div", {
3554
+ className: cn(groupVariants({ orientation }), className),
3555
+ "data-orientation": orientation,
3556
+ "data-slot": "group",
3557
+ role: "group",
3558
+ ...props,
3559
+ children
3560
+ });
3561
+ }
3562
+
3563
+ //#endregion
3564
+ //#region src/utils/customClasses.tsx
3565
+ function CustomClassesField({ value, onChange, field }) {
3566
+ const [input, setInput] = useState("");
3567
+ const tags = value || [];
3568
+ const addTag = () => {
3569
+ const trimmed = input.trim();
3570
+ if (!trimmed || tags.includes(trimmed)) {
3571
+ setInput("");
3572
+ return;
3573
+ }
3574
+ onChange([...tags, trimmed]);
3575
+ setInput("");
3576
+ };
3577
+ const removeTag = (tag) => {
3578
+ onChange(tags.filter((t) => t !== tag));
3579
+ };
3580
+ const handleKeyDown = (e) => {
3581
+ if (e.key === "Enter") {
3582
+ e.preventDefault();
3583
+ addTag();
3584
+ }
3585
+ };
3586
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Label_default, { label: field.label }), /* @__PURE__ */ jsxs("div", {
3587
+ className: "flex flex-col gap-y-2",
3588
+ children: [tags.length > 0 && /* @__PURE__ */ jsx("div", {
3589
+ className: "flex flex-wrap gap-1",
3590
+ children: tags.map((tag) => /* @__PURE__ */ jsxs("div", {
3591
+ className: "flex items-center gap-1 pl-1.5 pr-1 py-0.5 bg-secondary text-secondary-foreground rounded-md text-xs leading-none",
3592
+ children: [tag, /* @__PURE__ */ jsx(Button, {
3593
+ size: "icon-xs",
3594
+ variant: "ghost",
3595
+ className: "!size-4 rounded-sm hover:text-destructive text-secondary-foreground/50",
3596
+ type: "button",
3597
+ onClick: () => removeTag(tag),
3598
+ "aria-label": `Delete ${tag}`,
3599
+ children: /* @__PURE__ */ jsx(XIcon, { size: 10 })
3600
+ })]
3601
+ }, tag))
3602
+ }), /* @__PURE__ */ jsxs(Group, {
3603
+ "aria-label": "Custom classes",
3604
+ className: "gap-2 w-full",
3605
+ children: [/* @__PURE__ */ jsx(Input, {
3606
+ type: "text",
3607
+ value: input,
3608
+ placeholder: "Class name",
3609
+ onChange: (e) => setInput(e.currentTarget.value),
3610
+ onKeyDown: handleKeyDown
3611
+ }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, {
3612
+ size: "icon",
3613
+ variant: "primary",
3614
+ onClick: addTag,
3615
+ "aria-label": "Add",
3616
+ children: /* @__PURE__ */ jsx(PlusIcon, {})
3617
+ }) })]
3618
+ })]
3619
+ })] });
3620
+ }
3621
+ const customClassesField = { customClasses: {
3622
+ type: "custom",
3623
+ label: "Classes",
3624
+ render: ({ value, onChange, field }) => /* @__PURE__ */ jsx(CustomClassesField, {
3625
+ value,
3626
+ onChange,
3627
+ field
3628
+ })
3629
+ } };
3630
+ function customClassesToClasses(customClasses) {
3631
+ if (!customClasses || customClasses.length === 0) return "";
3632
+ return customClasses.join(" ");
3633
+ }
3634
+ const customClassesDefaultProps = { customClasses: [] };
3635
+
3636
+ //#endregion
3637
+ //#region src/utils/pagePicker.tsx
3638
+ const pageField = {
3639
+ type: "custom",
3640
+ render: ({ value, onChange, field }) => /* @__PURE__ */ jsxs(Fragment, { children: [field.label && /* @__PURE__ */ jsx(Label_default, {
3641
+ label: field.label,
3642
+ tooltip: field.tooltip
3643
+ }), /* @__PURE__ */ jsx(PagePicker, {
3644
+ value,
3645
+ onChange
3646
+ })] })
3647
+ };
3648
+
3193
3649
  //#endregion
3194
3650
  //#region src/utils/display.tsx
3195
3651
  const displayField = { display: {
@@ -3944,147 +4400,6 @@ function textAlignToClasses(textAlign) {
3944
4400
  }
3945
4401
  const textAlignDefaultProps = { textAlign: "left" };
3946
4402
 
3947
- //#endregion
3948
- //#region src/components/ColorPicker/index.tsx
3949
- const PREDEFINED_COLORS = [
3950
- {
3951
- name: "Blue",
3952
- value: "#3B82F6"
3953
- },
3954
- {
3955
- name: "Purple",
3956
- value: "#8B5CF6"
3957
- },
3958
- {
3959
- name: "Pink",
3960
- value: "#EC4899"
3961
- },
3962
- {
3963
- name: "Rose",
3964
- value: "#F43F5E"
3965
- },
3966
- {
3967
- name: "Red",
3968
- value: "#EF4444"
3969
- },
3970
- {
3971
- name: "Orange",
3972
- value: "#F97316"
3973
- },
3974
- {
3975
- name: "Amber",
3976
- value: "#F59E0B"
3977
- },
3978
- {
3979
- name: "Green",
3980
- value: "#10B981"
3981
- }
3982
- ];
3983
- const GRAY_COLORS = [
3984
- {
3985
- name: "Black",
3986
- value: "#000000"
3987
- },
3988
- {
3989
- name: "Gray 900",
3990
- value: "#18181B"
3991
- },
3992
- {
3993
- name: "Gray 600",
3994
- value: "#52525B"
3995
- },
3996
- {
3997
- name: "Gray 300",
3998
- value: "#D4D4D8"
3999
- },
4000
- {
4001
- name: "Gray 200",
4002
- value: "#E4E4E7"
4003
- },
4004
- {
4005
- name: "Gray 100",
4006
- value: "#F4F4F5"
4007
- },
4008
- {
4009
- name: "White",
4010
- value: "#FFFFFF"
4011
- }
4012
- ];
4013
- const ColorPicker = ({ value, onChange }) => {
4014
- const handleColorSelect = (color) => {
4015
- onChange(color);
4016
- };
4017
- const handleClearColor = () => {
4018
- onChange("");
4019
- };
4020
- return /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsxs(MenuTrigger, {
4021
- className: cn("border-input text-foreground focus-visible:border-primary hover:bg-accent w-full justify-between gap-2 rounded-lg border bg-white px-3 py-2 text-sm transition-colors", "flex items-center"),
4022
- children: [value ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
4023
- className: "border-border size-5 rounded-md border",
4024
- style: { backgroundColor: value }
4025
- }), /* @__PURE__ */ jsx("span", {
4026
- className: "flex-1 text-left",
4027
- children: value
4028
- })] }) : /* @__PURE__ */ jsxs("div", {
4029
- className: "flex items-center justify-start gap-2",
4030
- children: [/* @__PURE__ */ jsx("div", { className: "border-border after:bg-destructive relative size-5 rounded-md border bg-white after:absolute after:inset-0 after:top-1/2 after:left-1/2 after:z-1 after:flex after:h-0.5 after:w-7 after:-translate-x-1/2 after:-translate-y-1/2 after:-rotate-45 after:rounded-full after:content-['']" }), /* @__PURE__ */ jsx("span", { children: "No color" })]
4031
- }), /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" })]
4032
- }), /* @__PURE__ */ jsx(MenuPopup, {
4033
- align: "start",
4034
- side: "bottom",
4035
- children: /* @__PURE__ */ jsxs("div", {
4036
- className: "flex flex-col gap-3 p-2",
4037
- children: [/* @__PURE__ */ jsxs("div", {
4038
- className: "flex flex-col gap-3",
4039
- children: [/* @__PURE__ */ jsx("button", {
4040
- type: "button",
4041
- onClick: handleClearColor,
4042
- className: "border-border after:bg-destructive relative size-5 cursor-pointer rounded-md border bg-white after:absolute after:inset-0 after:top-1/2 after:left-1/2 after:z-1 after:flex after:h-0.5 after:w-7 after:-translate-x-1/2 after:-translate-y-1/2 after:-rotate-45 after:rounded-full after:content-['']",
4043
- title: "Clear color",
4044
- "aria-label": "Clear color"
4045
- }), /* @__PURE__ */ jsxs("div", {
4046
- className: "flex flex-wrap gap-1",
4047
- children: [PREDEFINED_COLORS.map((color) => /* @__PURE__ */ jsx("button", {
4048
- type: "button",
4049
- className: cn("border-primary/20 size-5 cursor-pointer rounded-md border transition-all hover:scale-105"),
4050
- style: { backgroundColor: color.value },
4051
- onClick: () => handleColorSelect(color.value),
4052
- title: color.name,
4053
- "aria-label": color.name
4054
- }, color.value)), GRAY_COLORS.map((color) => /* @__PURE__ */ jsx("button", {
4055
- type: "button",
4056
- className: cn("border-primary/20 size-5 cursor-pointer rounded-md border transition-all hover:scale-105"),
4057
- style: { backgroundColor: color.value },
4058
- onClick: () => handleColorSelect(color.value),
4059
- title: color.name,
4060
- "aria-label": color.name
4061
- }, color.value))]
4062
- })]
4063
- }), /* @__PURE__ */ jsxs("div", {
4064
- className: "flex flex-col gap-1.5",
4065
- children: [/* @__PURE__ */ jsx("div", {
4066
- className: "text-xs font-medium",
4067
- children: "Custom Color"
4068
- }), /* @__PURE__ */ jsxs("div", {
4069
- className: "flex flex-col gap-2",
4070
- children: [/* @__PURE__ */ jsx(HexColorPicker, {
4071
- color: value || "#000000",
4072
- onChange: handleColorSelect,
4073
- className: "!w-full"
4074
- }), /* @__PURE__ */ jsx(Input, {
4075
- type: "text",
4076
- value: value || "",
4077
- onChange: (e) => handleColorSelect(e.target.value),
4078
- placeholder: "Select a color",
4079
- onKeyDown: (e) => e.stopPropagation()
4080
- })]
4081
- })]
4082
- })]
4083
- })
4084
- })] });
4085
- };
4086
- var ColorPicker_default = ColorPicker;
4087
-
4088
4403
  //#endregion
4089
4404
  //#region src/utils/textColor.tsx
4090
4405
  const textColorField = { textColor: {
@@ -4380,5 +4695,5 @@ function useOptimizedImage(src) {
4380
4695
  }
4381
4696
 
4382
4697
  //#endregion
4383
- export { Accordion, AccordionHeader, AccordionItem, AccordionPanel, AccordionTrigger, AnchoredToastProvider, Button, Checkbox, Dialog, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPopup, DialogTitle, DialogTrigger, Checkbox_default as FieldCheckbox, Input_default as FieldInput, NumberUnit_default as FieldNumberUnit, Radio_default as FieldRadio, Select_default as FieldSelect, Textarea_default as FieldTextarea, Input, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, Label_default as Label, MediaPicker, Menu, MenuCheckboxItem, MenuCreateHandle, MenuGroup, MenuGroupLabel, MenuItem, MenuPopup, MenuPortal, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuShortcut, MenuSub, MenuSubPopup, MenuSubTrigger, MenuTrigger, PagePicker, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverClose, PopoverPopup as PopoverContent, PopoverPopup, PopoverCreateHandle, PopoverDescription, PopoverTitle, PopoverTrigger, RadioGroup, RadioGroupItem, RichTextMenuLink, Select, SelectGroup, SelectGroupLabel, SelectIcon, SelectItem, SelectItemIndicator, SelectItemText, SelectList, SelectPopup, SelectScrollDownArrow, SelectScrollUpArrow, SelectSeparator, SelectTrigger, SelectValue, Separator, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsPanel as TabsContent, TabsPanel, TabsList, TabsTab, TabsTab as TabsTrigger, Textarea, ToastProvider, Tooltip, TooltipPopup, TooltipProvider, TooltipTrigger, anchoredToastManager, animationDefaultProps, animationField, animationToAttributes, buttonVariants, plugin_default as createPuckOverridesPlugin, displayDefaultProps, displayField, displayToClasses, fontWeightDefaultProps, fontWeightField, fontWeightToClasses, getMediaUrl, getPageUrl, lineHeightDefaultProps, lineHeightField, lineHeightToClasses, marginDefaultProps, marginField, marginToClasses, paddingDefaultProps, paddingField, paddingToClasses, positionDefaultProps, positionField, positionToClasses, richTextMenuLinkExtension, richTextMenuLinkSelector, sizeDefaultProps, sizeField, sizeToClasses, spacingDefaultProps, spacingFieldNames, spacingFields, spacingOptions, spacingToClasses, textAlignDefaultProps, textAlignField, textAlignToClasses, textColorDefaultProps, textColorField, textColorToClasses, textDecorationDefaultProps, textDecorationField, textDecorationToClasses, textSizeDefaultProps, textSizeField, textSizeToClasses, textTransformDefaultProps, textTransformField, textTransformToClasses, toastManager, typographyDefaultProps, typographyFieldNames, typographyFields, typographyToClasses, useOptimizedImage };
4698
+ export { Accordion, AccordionItem, AccordionPanel, AccordionTrigger, ActionBar_default as ActionBar, AnchoredToastProvider, Badge, Button, Checkbox, ColorPicker, ColorPickerContent, Dialog, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPopup, DialogTitle, DialogTrigger, DrawerItem_default as DrawerItem, Checkbox_default as FieldCheckbox, FieldGroups_default as FieldGroups, Input_default as FieldInput, NumberUnit_default as FieldNumberUnit, Radio_default as FieldRadio, Select_default as FieldSelect, Textarea_default as FieldTextarea, Frame, FrameDescription, FrameFooter, FrameHeader, FramePanel, FrameTitle, GRAY_COLORS, Input, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, Label_default as Label, MediaPicker, Menu, MenuCheckboxItem, MenuCreateHandle, MenuGroup, MenuGroupLabel, MenuItem, MenuPopup, MenuPortal, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuShortcut, MenuSub, MenuSubPopup, MenuSubTrigger, MenuTrigger, PREDEFINED_COLORS, PagePicker, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PickerModal, Popover, PopoverClose, PopoverPopup as PopoverContent, PopoverPopup, PopoverCreateHandle, PopoverDescription, PopoverTitle, PopoverTrigger, RadioGroup, RadioGroupItem, RichTextMenuColorPicker, RichTextMenuLink, ScrollArea, ScrollBar, Select, SelectGroup, SelectGroupLabel, SelectItem, SelectPopup, SelectSeparator, SelectTrigger, SelectValue, Separator, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsPanel as TabsContent, TabsPanel, TabsList, TabsTab, TabsTab as TabsTrigger, Textarea, ToastProvider, Tooltip, TooltipPopup, TooltipProvider, TooltipTrigger, anchoredToastManager, animationDefaultProps, animationField, animationToAttributes, badgeVariants, buttonVariants, plugin_default as createPuckOverridesPlugin, createTemplateBlock, customClassesDefaultProps, customClassesField, customClassesToClasses, displayDefaultProps, displayField, displayToClasses, fontWeightDefaultProps, fontWeightField, fontWeightToClasses, getMediaUrl, lineHeightDefaultProps, lineHeightField, lineHeightToClasses, marginDefaultProps, marginField, marginToClasses, paddingDefaultProps, paddingField, paddingToClasses, pageField, positionDefaultProps, positionField, positionToClasses, richTextMenuColorPickerExtension, sizeDefaultProps, sizeField, sizeToClasses, spacingDefaultProps, spacingFieldNames, spacingFields, spacingOptions, spacingToClasses, textAlignDefaultProps, textAlignField, textAlignToClasses, textColorDefaultProps, textColorField, textColorToClasses, textDecorationDefaultProps, textDecorationField, textDecorationToClasses, textSizeDefaultProps, textSizeField, textSizeToClasses, textTransformDefaultProps, textTransformField, textTransformToClasses, toastManager, typographyDefaultProps, typographyFieldNames, typographyFields, typographyToClasses, useMediaUrl, useOptimizedImage, usePageUrl };
4384
4699
  //# sourceMappingURL=index.js.map