@webstudio-is/sdk-components-react-radix 0.83.0 → 0.85.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.
Files changed (103) hide show
  1. package/lib/__generated__/dialog.props.js +2120 -0
  2. package/lib/__generated__/popover.props.js +468 -0
  3. package/lib/__generated__/sheet.props.js +2159 -0
  4. package/lib/__generated__/tabs.props.js +1286 -0
  5. package/lib/__generated__/tooltip.props.js +478 -0
  6. package/lib/cjs/__generated__/dialog.props.js +2140 -0
  7. package/lib/cjs/__generated__/popover.props.js +488 -0
  8. package/lib/cjs/__generated__/sheet.props.js +2179 -0
  9. package/lib/cjs/__generated__/tabs.props.js +1306 -0
  10. package/lib/cjs/__generated__/tooltip.props.js +498 -0
  11. package/lib/cjs/collapsible.js +34 -4
  12. package/lib/cjs/collapsible.ws.js +14 -9
  13. package/lib/cjs/components.js +30 -1
  14. package/lib/cjs/dialog.js +57 -0
  15. package/lib/cjs/dialog.ws.js +311 -0
  16. package/lib/cjs/hooks.js +25 -0
  17. package/lib/cjs/metas.js +30 -1
  18. package/lib/cjs/popover.js +58 -0
  19. package/lib/cjs/popover.ws.js +141 -0
  20. package/lib/cjs/props.js +30 -1
  21. package/lib/cjs/sheet.js +63 -0
  22. package/lib/cjs/sheet.ws.js +317 -0
  23. package/lib/cjs/tabs.js +41 -0
  24. package/lib/cjs/tabs.ws.js +213 -0
  25. package/lib/cjs/theme/radix-common-types.js +16 -0
  26. package/lib/cjs/theme/tailwind-classes.js +547 -0
  27. package/lib/cjs/theme/tailwind-colors.js +35 -0
  28. package/lib/cjs/theme/tailwind-theme.js +46 -0
  29. package/lib/cjs/tooltip.js +55 -0
  30. package/lib/cjs/tooltip.ws.js +142 -0
  31. package/lib/collapsible.js +35 -7
  32. package/lib/collapsible.ws.js +19 -10
  33. package/lib/components.js +46 -1
  34. package/lib/dialog.js +30 -0
  35. package/lib/dialog.ws.js +298 -0
  36. package/lib/hooks.js +5 -0
  37. package/lib/metas.js +59 -1
  38. package/lib/popover.js +31 -0
  39. package/lib/popover.ws.js +116 -0
  40. package/lib/props.js +59 -1
  41. package/lib/sheet.js +35 -0
  42. package/lib/sheet.ws.js +304 -0
  43. package/lib/tabs.js +24 -0
  44. package/lib/tabs.ws.js +193 -0
  45. package/lib/theme/radix-common-types.js +0 -0
  46. package/lib/theme/tailwind-classes.js +527 -0
  47. package/lib/theme/tailwind-colors.js +15 -0
  48. package/lib/theme/tailwind-theme.js +16 -0
  49. package/lib/tooltip.js +28 -0
  50. package/lib/tooltip.ws.js +117 -0
  51. package/lib/types/__generated__/dialog.props.d.ts +8 -0
  52. package/lib/types/__generated__/popover.props.d.ts +4 -0
  53. package/lib/types/__generated__/sheet.props.d.ts +8 -0
  54. package/lib/types/__generated__/tabs.props.d.ts +5 -0
  55. package/lib/types/__generated__/tooltip.props.d.ts +4 -0
  56. package/lib/types/collapsible.d.ts +4 -3
  57. package/lib/types/components.d.ts +5 -0
  58. package/lib/types/dialog.d.ts +25 -0
  59. package/lib/types/dialog.ws.d.ts +23 -0
  60. package/lib/types/hooks.d.ts +2 -0
  61. package/lib/types/metas.d.ts +5 -0
  62. package/lib/types/popover.d.ts +21 -0
  63. package/lib/types/popover.ws.d.ts +15 -0
  64. package/lib/types/props.d.ts +5 -0
  65. package/lib/types/sheet.d.ts +15 -0
  66. package/lib/types/sheet.ws.d.ts +23 -0
  67. package/lib/types/tabs.d.ts +15 -0
  68. package/lib/types/tabs.ws.d.ts +9 -0
  69. package/lib/types/theme/radix-common-types.d.ts +84 -0
  70. package/lib/types/theme/tailwind-classes.d.ts +83 -0
  71. package/lib/types/theme/tailwind-colors.d.ts +21 -0
  72. package/lib/types/theme/tailwind-theme.d.ts +72 -0
  73. package/lib/types/tooltip.d.ts +21 -0
  74. package/lib/types/tooltip.ws.d.ts +15 -0
  75. package/package.json +23 -6
  76. package/src/__generated__/dialog.props.ts +2363 -0
  77. package/src/__generated__/popover.props.ts +515 -0
  78. package/src/__generated__/sheet.props.ts +2402 -0
  79. package/src/__generated__/tabs.props.ts +1434 -0
  80. package/src/__generated__/tooltip.props.ts +526 -0
  81. package/src/collapsible.stories.tsx +21 -0
  82. package/src/collapsible.tsx +44 -21
  83. package/src/collapsible.ws.ts +21 -10
  84. package/src/components.ts +21 -0
  85. package/src/dialog.tsx +66 -0
  86. package/src/dialog.ws.tsx +315 -0
  87. package/src/hooks.ts +4 -0
  88. package/src/metas.ts +34 -0
  89. package/src/popover.tsx +70 -0
  90. package/src/popover.ws.tsx +127 -0
  91. package/src/props.ts +34 -0
  92. package/src/sheet.stories.tsx +21 -0
  93. package/src/sheet.tsx +40 -0
  94. package/src/sheet.ws.tsx +326 -0
  95. package/src/tabs.stories.tsx +21 -0
  96. package/src/tabs.tsx +46 -0
  97. package/src/tabs.ws.ts +211 -0
  98. package/src/theme/radix-common-types.ts +495 -0
  99. package/src/theme/tailwind-classes.ts +695 -0
  100. package/src/theme/tailwind-colors.ts +45 -0
  101. package/src/theme/tailwind-theme.ts +24 -0
  102. package/src/tooltip.tsx +69 -0
  103. package/src/tooltip.ws.tsx +128 -0
@@ -1,5 +1,10 @@
1
- import { RadioUncheckedIcon, RadioCheckedIcon } from "@webstudio-is/icons/svg";
1
+ import {
2
+ CollapsibleIcon,
3
+ TriggerIcon,
4
+ ContentIcon,
5
+ } from "@webstudio-is/icons/svg";
2
6
  import type {
7
+ PresetStyle,
3
8
  WsComponentMeta,
4
9
  WsComponentPropsMeta,
5
10
  } from "@webstudio-is/react-sdk";
@@ -8,25 +13,30 @@ import {
8
13
  propsCollapsibleContent,
9
14
  propsCollapsibleTrigger,
10
15
  } from "./__generated__/collapsible.props";
16
+ import { div } from "@webstudio-is/react-sdk/css-normalize";
17
+
18
+ const presetStyle = {
19
+ div,
20
+ } satisfies PresetStyle<"div">;
11
21
 
12
22
  export const metaCollapsible: WsComponentMeta = {
13
23
  category: "radix",
14
24
  type: "container",
25
+ presetStyle,
15
26
  label: "Collapsible",
16
- icon: RadioUncheckedIcon,
27
+ icon: CollapsibleIcon,
17
28
  template: [
18
29
  {
19
30
  type: "instance",
20
31
  component: "Collapsible",
32
+ dataSources: {
33
+ collapsibleOpen: { type: "variable", initialValue: false },
34
+ },
21
35
  props: [
22
36
  {
37
+ type: "dataSource",
23
38
  name: "open",
24
- type: "boolean",
25
- value: false,
26
- dataSourceRef: {
27
- type: "variable",
28
- name: "collapsibleOpen",
29
- },
39
+ dataSourceName: "collapsibleOpen",
30
40
  },
31
41
  {
32
42
  name: "onOpenChange",
@@ -72,7 +82,7 @@ export const metaCollapsibleTrigger: WsComponentMeta = {
72
82
  category: "hidden",
73
83
  type: "container",
74
84
  label: "Collapsible Trigger",
75
- icon: RadioCheckedIcon,
85
+ icon: TriggerIcon,
76
86
  stylable: false,
77
87
  detachable: false,
78
88
  };
@@ -80,8 +90,9 @@ export const metaCollapsibleTrigger: WsComponentMeta = {
80
90
  export const metaCollapsibleContent: WsComponentMeta = {
81
91
  category: "hidden",
82
92
  type: "container",
93
+ presetStyle,
83
94
  label: "Collapsible Content",
84
- icon: RadioCheckedIcon,
95
+ icon: ContentIcon,
85
96
  detachable: false,
86
97
  };
87
98
 
package/src/components.ts CHANGED
@@ -3,3 +3,24 @@ export {
3
3
  CollapsibleTrigger,
4
4
  CollapsibleContent,
5
5
  } from "./collapsible";
6
+ export {
7
+ Dialog,
8
+ DialogTrigger,
9
+ DialogOverlay,
10
+ DialogContent,
11
+ DialogClose,
12
+ DialogTitle,
13
+ DialogDescription,
14
+ } from "./dialog";
15
+ export { Popover, PopoverTrigger, PopoverContent } from "./popover";
16
+ export { Tooltip, TooltipTrigger, TooltipContent } from "./tooltip";
17
+ export {
18
+ Sheet,
19
+ SheetTrigger,
20
+ SheetOverlay,
21
+ SheetContent,
22
+ SheetClose,
23
+ SheetTitle,
24
+ SheetDescription,
25
+ } from "./sheet";
26
+ export { Tabs, TabsList, TabsTrigger, TabsContent } from "./tabs";
package/src/dialog.tsx ADDED
@@ -0,0 +1,66 @@
1
+ /* eslint-disable react/display-name */
2
+ // We can't use .displayName until this is merged https://github.com/styleguidist/react-docgen-typescript/pull/449
3
+
4
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
5
+
6
+ import {
7
+ forwardRef,
8
+ type ElementRef,
9
+ type ComponentPropsWithoutRef,
10
+ Children,
11
+ type ReactNode,
12
+ } from "react";
13
+
14
+ /**
15
+ * We don't have support for boolean or undefined nor in UI not at Data variables,
16
+ * instead of binding on "open" prop we bind variable on a isOpen prop to be able to show Dialog in the builder
17
+ **/
18
+ type BuilderDialogProps = {
19
+ isOpen: "initial" | "open" | "closed";
20
+ };
21
+
22
+ export const Dialog = forwardRef<
23
+ ElementRef<"div">,
24
+ ComponentPropsWithoutRef<typeof DialogPrimitive.Root> & BuilderDialogProps
25
+ >(({ open: openProp, isOpen, ...props }, ref) => {
26
+ const open =
27
+ openProp ??
28
+ (isOpen === "open" ? true : isOpen === "closed" ? false : undefined);
29
+
30
+ return <DialogPrimitive.Root open={open} {...props} />;
31
+ });
32
+
33
+ /**
34
+ * We're not exposing the 'asChild' property for the Trigger.
35
+ * Instead, we're enforcing 'asChild=true' for the Trigger and making it style-less.
36
+ * This avoids situations where the Trigger inadvertently passes all styles to its child,
37
+ * which would prevent us from displaying styles properly in the builder.
38
+ */
39
+ export const DialogTrigger = forwardRef<
40
+ ElementRef<"div">,
41
+ { children: ReactNode }
42
+ >(({ children, ...props }, ref) => {
43
+ const firstChild = Children.toArray(children)[0];
44
+
45
+ return (
46
+ <DialogPrimitive.Trigger asChild={true} {...props}>
47
+ {firstChild ?? <button>Add button or link</button>}
48
+ </DialogPrimitive.Trigger>
49
+ );
50
+ });
51
+
52
+ export const DialogOverlay = forwardRef<
53
+ ElementRef<"div">,
54
+ ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
55
+ >((props, ref) => {
56
+ return (
57
+ <DialogPrimitive.DialogPortal>
58
+ <DialogPrimitive.Overlay ref={ref} {...props} />
59
+ </DialogPrimitive.DialogPortal>
60
+ );
61
+ });
62
+
63
+ export const DialogContent = DialogPrimitive.Content;
64
+ export const DialogClose = DialogPrimitive.Close;
65
+ export const DialogTitle = DialogPrimitive.Title;
66
+ export const DialogDescription = DialogPrimitive.Description;
@@ -0,0 +1,315 @@
1
+ import {
2
+ DialogIcon,
3
+ TriggerIcon,
4
+ ContentIcon,
5
+ OverlayIcon,
6
+ HeadingIcon,
7
+ TextIcon,
8
+ ButtonElementIcon,
9
+ } from "@webstudio-is/icons/svg";
10
+ import {
11
+ type PresetStyle,
12
+ type WsComponentMeta,
13
+ type WsComponentPropsMeta,
14
+ } from "@webstudio-is/react-sdk";
15
+ import * as tc from "./theme/tailwind-classes";
16
+ import {
17
+ propsDialog,
18
+ propsDialogContent,
19
+ propsDialogTrigger,
20
+ propsDialogOverlay,
21
+ propsDialogClose,
22
+ propsDialogTitle,
23
+ propsDialogDescription,
24
+ } from "./__generated__/dialog.props";
25
+
26
+ import { div, button, h2, p } from "@webstudio-is/react-sdk/css-normalize";
27
+
28
+ const presetStyle = {
29
+ div,
30
+ } satisfies PresetStyle<"div">;
31
+
32
+ const buttonPresetStyle = {
33
+ button,
34
+ } satisfies PresetStyle<"button">;
35
+
36
+ const titlePresetStyle = {
37
+ h2,
38
+ } satisfies PresetStyle<"h2">;
39
+
40
+ const descriptionPresetStyle = {
41
+ p,
42
+ } satisfies PresetStyle<"p">;
43
+
44
+ // @todo add [data-state] to button and link
45
+ export const metaDialogTrigger: WsComponentMeta = {
46
+ category: "hidden",
47
+ invalidAncestors: [],
48
+ type: "container",
49
+ label: "Dialog Trigger",
50
+ icon: TriggerIcon,
51
+ stylable: false,
52
+ detachable: false,
53
+ };
54
+
55
+ export const metaDialogContent: WsComponentMeta = {
56
+ category: "hidden",
57
+ invalidAncestors: [],
58
+ type: "container",
59
+ label: "Dialog Content",
60
+ presetStyle,
61
+ icon: ContentIcon,
62
+ detachable: false,
63
+ };
64
+
65
+ export const metaDialogOverlay: WsComponentMeta = {
66
+ category: "hidden",
67
+ invalidAncestors: [],
68
+ type: "container",
69
+ label: "Dialog Overlay",
70
+ presetStyle,
71
+ icon: OverlayIcon,
72
+ detachable: false,
73
+ };
74
+
75
+ export const metaDialogTitle: WsComponentMeta = {
76
+ category: "hidden",
77
+ invalidAncestors: [],
78
+ type: "container",
79
+ presetStyle: titlePresetStyle,
80
+ label: "Dialog Title",
81
+ icon: HeadingIcon,
82
+ };
83
+
84
+ export const metaDialogDescription: WsComponentMeta = {
85
+ category: "hidden",
86
+ invalidAncestors: [],
87
+ type: "container",
88
+ presetStyle: descriptionPresetStyle,
89
+ label: "Dialog Description",
90
+ icon: TextIcon,
91
+ };
92
+
93
+ export const metaDialogClose: WsComponentMeta = {
94
+ category: "hidden",
95
+ invalidAncestors: [],
96
+ type: "container",
97
+ presetStyle: buttonPresetStyle,
98
+ label: "Dialog Close",
99
+ icon: ButtonElementIcon,
100
+ };
101
+
102
+ /**
103
+ * Styles source without animations:
104
+ * https://github.com/shadcn-ui/ui/blob/main/apps/www/registry/default/ui/dialog.tsx
105
+ *
106
+ * Attributions
107
+ * MIT License
108
+ * Copyright (c) 2023 shadcn
109
+ **/
110
+ export const metaDialog: WsComponentMeta = {
111
+ category: "radix",
112
+ invalidAncestors: [],
113
+ type: "container",
114
+ label: "Dialog",
115
+ icon: DialogIcon,
116
+ order: 15,
117
+ stylable: false,
118
+ template: [
119
+ {
120
+ type: "instance",
121
+ component: "Dialog",
122
+ dataSources: {
123
+ // We don't have support for boolean or undefined, instead of binding on open we bind on a string
124
+ isOpen: { type: "variable", initialValue: "initial" },
125
+ },
126
+ props: [
127
+ {
128
+ type: "dataSource",
129
+ name: "isOpen",
130
+ dataSourceName: "isOpen",
131
+ },
132
+ ],
133
+ children: [
134
+ {
135
+ type: "instance",
136
+ component: "DialogTrigger",
137
+ props: [],
138
+ children: [
139
+ {
140
+ type: "instance",
141
+ component: "Button",
142
+ children: [{ type: "text", value: "Button" }],
143
+ },
144
+ ],
145
+ },
146
+ {
147
+ type: "instance",
148
+ component: "DialogOverlay",
149
+ props: [],
150
+ /**
151
+ * fixed inset-0 z-50 bg-background/80 backdrop-blur-sm
152
+ * flex
153
+ **/
154
+ styles: [
155
+ tc.fixed(),
156
+ tc.inset(0),
157
+ tc.z(50),
158
+ tc.bg("background", 80),
159
+ tc.backdropBlur("sm"),
160
+ // To allow positioning Content
161
+ tc.flex(),
162
+ ].flat(),
163
+ children: [
164
+ {
165
+ type: "instance",
166
+ component: "DialogContent",
167
+ props: [],
168
+ /**
169
+ * fixed w-full z-50
170
+ * grid gap-4 max-w-lg
171
+ * m-auto
172
+ * border bg-background p-6 shadow-lg
173
+ **/
174
+ styles: [
175
+ tc.w("full"),
176
+ tc.z(50),
177
+ tc.flex(),
178
+ tc.flex("col"),
179
+ tc.gap(4),
180
+ tc.m("auto"),
181
+ tc.maxW("lg"),
182
+ tc.border(),
183
+ tc.bg("background"),
184
+ tc.p(6),
185
+ tc.shadow("lg"),
186
+ tc.relative(),
187
+ ].flat(),
188
+ children: [
189
+ {
190
+ type: "instance",
191
+ component: "Box",
192
+ label: "Dialog Header",
193
+ props: [],
194
+ styles: [tc.flex(), tc.flex("col"), tc.gap(1)].flat(),
195
+ children: [
196
+ {
197
+ type: "instance",
198
+ component: "DialogTitle",
199
+ props: [],
200
+ /**
201
+ * text-lg leading-none tracking-tight
202
+ **/
203
+ styles: [
204
+ tc.my(0),
205
+ tc.leading("none"),
206
+ tc.text("lg"),
207
+ tc.tracking("tight"),
208
+ ].flat(),
209
+ children: [
210
+ {
211
+ type: "text",
212
+ value: "Dialog Title",
213
+ },
214
+ ],
215
+ },
216
+ {
217
+ type: "instance",
218
+ component: "DialogDescription",
219
+ props: [],
220
+ /**
221
+ * text-sm text-muted-foreground
222
+ **/
223
+ styles: [
224
+ tc.my(0),
225
+ tc.text("sm"),
226
+ tc.text("mutedForeground"),
227
+ ].flat(),
228
+ children: [
229
+ {
230
+ type: "text",
231
+ value: "dialog description text you can edit",
232
+ },
233
+ ],
234
+ },
235
+ ],
236
+ },
237
+
238
+ {
239
+ type: "instance",
240
+ component: "Text",
241
+ children: [{ type: "text", value: "The text you can edit" }],
242
+ },
243
+
244
+ {
245
+ type: "instance",
246
+ component: "DialogClose",
247
+ props: [],
248
+ /**
249
+ * absolute right-4 top-4
250
+ * rounded-sm opacity-70
251
+ * ring-offset-background
252
+ * hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2
253
+ * flex items-center justify-center h-4 w-4
254
+ **/
255
+ styles: [
256
+ tc.absolute(),
257
+ tc.right(4),
258
+ tc.top(4),
259
+ tc.rounded("sm"),
260
+ tc.opacity(70),
261
+ tc.flex(),
262
+ tc.items("center"),
263
+ tc.justify("center"),
264
+ tc.h(4),
265
+ tc.w(4),
266
+ tc.border(0),
267
+ tc.bg("transparent"),
268
+ tc.outline("none"),
269
+ tc.hover(tc.opacity(100)),
270
+ tc.focus(tc.ring("ring", 2, "background", 2)),
271
+ ].flat(),
272
+ children: [{ type: "text", value: "✕" }],
273
+ },
274
+ ],
275
+ },
276
+ ],
277
+ },
278
+ ],
279
+ },
280
+ ],
281
+ };
282
+
283
+ export const propsMetaDialog: WsComponentPropsMeta = {
284
+ props: propsDialog,
285
+ initialProps: ["isOpen", "modal"],
286
+ };
287
+
288
+ export const propsMetaDialogTrigger: WsComponentPropsMeta = {
289
+ props: propsDialogTrigger,
290
+ };
291
+
292
+ export const propsMetaDialogContent: WsComponentPropsMeta = {
293
+ props: propsDialogContent,
294
+ initialProps: [],
295
+ };
296
+
297
+ export const propsMetaDialogOverlay: WsComponentPropsMeta = {
298
+ props: propsDialogOverlay,
299
+ initialProps: [],
300
+ };
301
+
302
+ export const propsMetaDialogClose: WsComponentPropsMeta = {
303
+ props: propsDialogClose,
304
+ initialProps: [],
305
+ };
306
+
307
+ export const propsMetaDialogTitle: WsComponentPropsMeta = {
308
+ props: propsDialogTitle,
309
+ initialProps: [],
310
+ };
311
+
312
+ export const propsMetaDialogDescription: WsComponentPropsMeta = {
313
+ props: propsDialogDescription,
314
+ initialProps: [],
315
+ };
package/src/hooks.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { Hook } from "@webstudio-is/react-sdk";
2
+ import { hooksCollapsible } from "./collapsible";
3
+
4
+ export const hooks: Hook[] = [hooksCollapsible];
package/src/metas.ts CHANGED
@@ -3,3 +3,37 @@ export {
3
3
  metaCollapsibleTrigger as CollapsibleTrigger,
4
4
  metaCollapsibleContent as CollapsibleContent,
5
5
  } from "./collapsible.ws";
6
+ export {
7
+ metaDialog as Dialog,
8
+ metaDialogTrigger as DialogTrigger,
9
+ metaDialogOverlay as DialogOverlay,
10
+ metaDialogContent as DialogContent,
11
+ metaDialogClose as DialogClose,
12
+ metaDialogTitle as DialogTitle,
13
+ metaDialogDescription as DialogDescription,
14
+ } from "./dialog.ws";
15
+ export {
16
+ metaPopover as Popover,
17
+ metaPopoverTrigger as PopoverTrigger,
18
+ metaPopoverContent as PopoverContent,
19
+ } from "./popover.ws";
20
+ export {
21
+ metaTooltip as Tooltip,
22
+ metaTooltipTrigger as TooltipTrigger,
23
+ metaTooltipContent as TooltipContent,
24
+ } from "./tooltip.ws";
25
+ export {
26
+ metaSheet as Sheet,
27
+ metaSheetTrigger as SheetTrigger,
28
+ metaSheetOverlay as SheetOverlay,
29
+ metaSheetContent as SheetContent,
30
+ metaSheetClose as SheetClose,
31
+ metaSheetTitle as SheetTitle,
32
+ metaSheetDescription as SheetDescription,
33
+ } from "./sheet.ws";
34
+ export {
35
+ metaTabs as Tabs,
36
+ metaTabsList as TabsList,
37
+ metaTabsTrigger as TabsTrigger,
38
+ metaTabsContent as TabsContent,
39
+ } from "./tabs.ws";
@@ -0,0 +1,70 @@
1
+ /* eslint-disable react/display-name */
2
+ // We can't use .displayName until this is merged https://github.com/styleguidist/react-docgen-typescript/pull/449
3
+
4
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
5
+
6
+ import {
7
+ forwardRef,
8
+ type ElementRef,
9
+ type ComponentPropsWithoutRef,
10
+ Children,
11
+ type ReactNode,
12
+ } from "react";
13
+
14
+ /**
15
+ * We don't have support for boolean or undefined nor in UI not at Data variables,
16
+ * instead of binding on "open" prop we bind variable on a isOpen prop to be able to show Popover in the builder
17
+ **/
18
+ type BuilderPopoverProps = {
19
+ isOpen: "initial" | "open" | "closed";
20
+ };
21
+
22
+ export const Popover = forwardRef<
23
+ ElementRef<"div">,
24
+ ComponentPropsWithoutRef<typeof PopoverPrimitive.Root> & BuilderPopoverProps
25
+ >(({ open: openProp, isOpen, ...props }, ref) => {
26
+ const open =
27
+ openProp ??
28
+ (isOpen === "open" ? true : isOpen === "closed" ? false : undefined);
29
+
30
+ return <PopoverPrimitive.Root open={open} {...props} />;
31
+ });
32
+
33
+ /**
34
+ * We're not exposing the 'asChild' property for the Trigger.
35
+ * Instead, we're enforcing 'asChild=true' for the Trigger and making it style-less.
36
+ * This avoids situations where the Trigger inadvertently passes all styles to its child,
37
+ * which would prevent us from displaying styles properly in the builder.
38
+ */
39
+ export const PopoverTrigger = forwardRef<
40
+ ElementRef<"button">,
41
+ { children: ReactNode }
42
+ >(({ children, ...props }, ref) => {
43
+ const firstChild = Children.toArray(children)[0];
44
+
45
+ return (
46
+ <PopoverPrimitive.Trigger asChild={true} ref={ref} {...props}>
47
+ {firstChild ?? <button>Add button or link</button>}
48
+ </PopoverPrimitive.Trigger>
49
+ );
50
+ });
51
+
52
+ export const PopoverContent = forwardRef<
53
+ ElementRef<typeof PopoverPrimitive.Content>,
54
+ ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
55
+ >(
56
+ (
57
+ { sideOffset = 4, align = "center", hideWhenDetached = true, ...props },
58
+ ref
59
+ ) => (
60
+ <PopoverPrimitive.Portal>
61
+ <PopoverPrimitive.Content
62
+ ref={ref}
63
+ align="center"
64
+ sideOffset={sideOffset}
65
+ hideWhenDetached={hideWhenDetached}
66
+ {...props}
67
+ />
68
+ </PopoverPrimitive.Portal>
69
+ )
70
+ );