@fluid-app/portal-widgets 0.1.17

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 (145) hide show
  1. package/dist/AlertWidget-AS_8Jjbd.cjs +39 -0
  2. package/dist/AlertWidget-AS_8Jjbd.cjs.map +1 -0
  3. package/dist/AlertWidget-Dy6pBmXm.mjs +22 -0
  4. package/dist/AlertWidget-Dy6pBmXm.mjs.map +1 -0
  5. package/dist/CalendarWidget-DAHnT9Wn.mjs +424 -0
  6. package/dist/CalendarWidget-DAHnT9Wn.mjs.map +1 -0
  7. package/dist/CalendarWidget-DW7q6Q7_.cjs +441 -0
  8. package/dist/CalendarWidget-DW7q6Q7_.cjs.map +1 -0
  9. package/dist/CarouselWidget-BJvLjY7H.mjs +436 -0
  10. package/dist/CarouselWidget-BJvLjY7H.mjs.map +1 -0
  11. package/dist/CarouselWidget-Bdn0LVXT.cjs +453 -0
  12. package/dist/CarouselWidget-Bdn0LVXT.cjs.map +1 -0
  13. package/dist/CatchUpWidget-CZMptzf8.cjs +264 -0
  14. package/dist/CatchUpWidget-CZMptzf8.cjs.map +1 -0
  15. package/dist/CatchUpWidget-vEP5scfy.mjs +247 -0
  16. package/dist/CatchUpWidget-vEP5scfy.mjs.map +1 -0
  17. package/dist/ChartWidget-B3GcdLqH.mjs +415 -0
  18. package/dist/ChartWidget-B3GcdLqH.mjs.map +1 -0
  19. package/dist/ChartWidget-DQB7K6S0.cjs +432 -0
  20. package/dist/ChartWidget-DQB7K6S0.cjs.map +1 -0
  21. package/dist/ContainerWidget-B-4hcPKJ.mjs +44 -0
  22. package/dist/ContainerWidget-B-4hcPKJ.mjs.map +1 -0
  23. package/dist/ContainerWidget-CHa4gVvV.cjs +2 -0
  24. package/dist/ContainerWidget-rGsakG66.cjs +51 -0
  25. package/dist/ContainerWidget-rGsakG66.cjs.map +1 -0
  26. package/dist/EmbedWidget-ChLVA_9a.mjs +156 -0
  27. package/dist/EmbedWidget-ChLVA_9a.mjs.map +1 -0
  28. package/dist/EmbedWidget-mv5ce32s.cjs +173 -0
  29. package/dist/EmbedWidget-mv5ce32s.cjs.map +1 -0
  30. package/dist/ImageWidget-DFt4mJJx.cjs +167 -0
  31. package/dist/ImageWidget-DFt4mJJx.cjs.map +1 -0
  32. package/dist/ImageWidget-DMubcgat.mjs +150 -0
  33. package/dist/ImageWidget-DMubcgat.mjs.map +1 -0
  34. package/dist/LayoutWidget-BEi0yFpz.mjs +107 -0
  35. package/dist/LayoutWidget-BEi0yFpz.mjs.map +1 -0
  36. package/dist/LayoutWidget-C4-ka0Ge.cjs +114 -0
  37. package/dist/LayoutWidget-C4-ka0Ge.cjs.map +1 -0
  38. package/dist/LayoutWidget-D4haEqTQ.cjs +2 -0
  39. package/dist/ListWidget-C-jcsCb4.mjs +901 -0
  40. package/dist/ListWidget-C-jcsCb4.mjs.map +1 -0
  41. package/dist/ListWidget-RHQ2fQXa.cjs +919 -0
  42. package/dist/ListWidget-RHQ2fQXa.cjs.map +1 -0
  43. package/dist/MediaRenderer-CcJvyOJ1.cjs +181 -0
  44. package/dist/MediaRenderer-CcJvyOJ1.cjs.map +1 -0
  45. package/dist/MediaRenderer-Uq90PZcY.mjs +163 -0
  46. package/dist/MediaRenderer-Uq90PZcY.mjs.map +1 -0
  47. package/dist/MySiteWidget-A_cYFgxJ.cjs +279 -0
  48. package/dist/MySiteWidget-A_cYFgxJ.cjs.map +1 -0
  49. package/dist/MySiteWidget-DariqlfU.mjs +262 -0
  50. package/dist/MySiteWidget-DariqlfU.mjs.map +1 -0
  51. package/dist/NestedWidget-CNkwGwhM.mjs +330 -0
  52. package/dist/NestedWidget-CNkwGwhM.mjs.map +1 -0
  53. package/dist/NestedWidget-ofk9O-t1.cjs +346 -0
  54. package/dist/NestedWidget-ofk9O-t1.cjs.map +1 -0
  55. package/dist/QuickShareWidget-DWvgEy74.cjs +262 -0
  56. package/dist/QuickShareWidget-DWvgEy74.cjs.map +1 -0
  57. package/dist/QuickShareWidget-DXq5lcDn.mjs +245 -0
  58. package/dist/QuickShareWidget-DXq5lcDn.mjs.map +1 -0
  59. package/dist/RecentActivityWidget-BvncOdax.mjs +391 -0
  60. package/dist/RecentActivityWidget-BvncOdax.mjs.map +1 -0
  61. package/dist/RecentActivityWidget-wODng8dt.cjs +408 -0
  62. package/dist/RecentActivityWidget-wODng8dt.cjs.map +1 -0
  63. package/dist/RegistryContext-CscXrsRa.mjs +36 -0
  64. package/dist/RegistryContext-CscXrsRa.mjs.map +1 -0
  65. package/dist/RegistryContext-xjea4xVV.cjs +55 -0
  66. package/dist/RegistryContext-xjea4xVV.cjs.map +1 -0
  67. package/dist/ScreenRenderer-D52h5VQr.mjs +76 -0
  68. package/dist/ScreenRenderer-D52h5VQr.mjs.map +1 -0
  69. package/dist/ScreenRenderer-DZAxcg7x.cjs +82 -0
  70. package/dist/ScreenRenderer-DZAxcg7x.cjs.map +1 -0
  71. package/dist/ScreenRendererContext-CK1IsFTn.cjs +36 -0
  72. package/dist/ScreenRendererContext-CK1IsFTn.cjs.map +1 -0
  73. package/dist/ScreenRendererContext-DKcdcmiT.mjs +23 -0
  74. package/dist/ScreenRendererContext-DKcdcmiT.mjs.map +1 -0
  75. package/dist/SpacerWidget-Bgz6701y.cjs +60 -0
  76. package/dist/SpacerWidget-Bgz6701y.cjs.map +1 -0
  77. package/dist/SpacerWidget-DHGoW6eu.mjs +43 -0
  78. package/dist/SpacerWidget-DHGoW6eu.mjs.map +1 -0
  79. package/dist/TableWidget--yLJTqoW.mjs +438 -0
  80. package/dist/TableWidget--yLJTqoW.mjs.map +1 -0
  81. package/dist/TableWidget-TfQfFHft.cjs +455 -0
  82. package/dist/TableWidget-TfQfFHft.cjs.map +1 -0
  83. package/dist/TextWidget-CL2H3vei.mjs +129 -0
  84. package/dist/TextWidget-CL2H3vei.mjs.map +1 -0
  85. package/dist/TextWidget-D6Ug_2Z1.cjs +146 -0
  86. package/dist/TextWidget-D6Ug_2Z1.cjs.map +1 -0
  87. package/dist/ToDoWidget-D8YIsl7y.mjs +274 -0
  88. package/dist/ToDoWidget-D8YIsl7y.mjs.map +1 -0
  89. package/dist/ToDoWidget-Dvs0GDkx.cjs +291 -0
  90. package/dist/ToDoWidget-Dvs0GDkx.cjs.map +1 -0
  91. package/dist/VideoWidget-D6C_jHOF.mjs +192 -0
  92. package/dist/VideoWidget-D6C_jHOF.mjs.map +1 -0
  93. package/dist/VideoWidget-SODAPZO4.cjs +209 -0
  94. package/dist/VideoWidget-SODAPZO4.cjs.map +1 -0
  95. package/dist/chunk-CZWwpsFl.cjs +43 -0
  96. package/dist/components/index.cjs +14 -0
  97. package/dist/components/index.cjs.map +1 -0
  98. package/dist/components/index.d.cts +11 -0
  99. package/dist/components/index.d.cts.map +1 -0
  100. package/dist/components/index.d.mts +11 -0
  101. package/dist/components/index.d.mts.map +1 -0
  102. package/dist/components/index.mjs +11 -0
  103. package/dist/components/index.mjs.map +1 -0
  104. package/dist/contexts/index.cjs +8 -0
  105. package/dist/contexts/index.d.cts +77 -0
  106. package/dist/contexts/index.d.cts.map +1 -0
  107. package/dist/contexts/index.d.mts +77 -0
  108. package/dist/contexts/index.d.mts.map +1 -0
  109. package/dist/contexts/index.mjs +3 -0
  110. package/dist/core/index.cjs +51 -0
  111. package/dist/core/index.d.cts +77 -0
  112. package/dist/core/index.d.cts.map +1 -0
  113. package/dist/core/index.d.mts +77 -0
  114. package/dist/core/index.d.mts.map +1 -0
  115. package/dist/core/index.mjs +4 -0
  116. package/dist/error-state-DErSxZwH.mjs +18 -0
  117. package/dist/error-state-DErSxZwH.mjs.map +1 -0
  118. package/dist/error-state-DSzVUtEl.cjs +24 -0
  119. package/dist/error-state-DSzVUtEl.cjs.map +1 -0
  120. package/dist/fields-4FC6JUNH.d.mts +2 -0
  121. package/dist/fields-DjLFJmz6.d.cts +2 -0
  122. package/dist/fields-wPOk-SmZ.mjs +2 -0
  123. package/dist/rolldown-runtime-wcPFST8Q.mjs +13 -0
  124. package/dist/scroll-arrows-BZIlsE_x.cjs +35 -0
  125. package/dist/scroll-arrows-BZIlsE_x.cjs.map +1 -0
  126. package/dist/scroll-arrows-BevCYRNT.mjs +29 -0
  127. package/dist/scroll-arrows-BevCYRNT.mjs.map +1 -0
  128. package/dist/ui/index.cjs +101 -0
  129. package/dist/ui/index.d.cts +15 -0
  130. package/dist/ui/index.d.cts.map +1 -0
  131. package/dist/ui/index.d.mts +15 -0
  132. package/dist/ui/index.d.mts.map +1 -0
  133. package/dist/ui/index.mjs +3 -0
  134. package/dist/widgets/index.cjs +92 -0
  135. package/dist/widgets/index.cjs.map +1 -0
  136. package/dist/widgets/index.d.cts +689 -0
  137. package/dist/widgets/index.d.cts.map +1 -0
  138. package/dist/widgets/index.d.mts +689 -0
  139. package/dist/widgets/index.d.mts.map +1 -0
  140. package/dist/widgets/index.mjs +46 -0
  141. package/dist/widgets/index.mjs.map +1 -0
  142. package/package.json +104 -0
  143. package/src/styles/globals.css +23 -0
  144. package/src/styles/index.ts +1 -0
  145. package/tailwind.config.ts +61 -0
@@ -0,0 +1,291 @@
1
+ const require_chunk = require("./chunk-CZWwpsFl.cjs");
2
+ const require_error_state = require("./error-state-DSzVUtEl.cjs");
3
+ let react_jsx_runtime = require("react/jsx-runtime");
4
+ let _tanstack_react_query = require("@tanstack/react-query");
5
+ let _fluid_app_portal_core_data_sources_context = require("@fluid-app/portal-core/data-sources/context");
6
+ let _fluid_app_portal_core_data_sources_preview_context = require("@fluid-app/portal-core/data-sources/preview-context");
7
+ let _fortawesome_react_fontawesome = require("@fortawesome/react-fontawesome");
8
+ let _fortawesome_pro_regular_svg_icons = require("@fortawesome/pro-regular-svg-icons");
9
+ let _fluid_app_portal_core_registries = require("@fluid-app/portal-core/registries");
10
+ //#region src/hooks/use-todos.preview.ts
11
+ const now = /* @__PURE__ */ new Date();
12
+ function daysFromNow(days) {
13
+ const d = new Date(now);
14
+ d.setDate(d.getDate() + days);
15
+ return d.toISOString();
16
+ }
17
+ const PREVIEW_DATA = [
18
+ {
19
+ id: 1,
20
+ body: "Send follow-up email to new leads",
21
+ dueAt: daysFromNow(1),
22
+ completedAt: null,
23
+ createdAt: daysFromNow(-2),
24
+ contactName: "Sarah Johnson"
25
+ },
26
+ {
27
+ id: 2,
28
+ body: "Prepare slides for team training",
29
+ dueAt: daysFromNow(3),
30
+ completedAt: null,
31
+ createdAt: daysFromNow(-1),
32
+ contactName: null
33
+ },
34
+ {
35
+ id: 3,
36
+ body: "Review monthly sales report",
37
+ dueAt: daysFromNow(-1),
38
+ completedAt: null,
39
+ createdAt: daysFromNow(-5),
40
+ contactName: "Mike Chen"
41
+ }
42
+ ];
43
+ //#endregion
44
+ //#region src/hooks/use-todos.ts
45
+ function useTodos() {
46
+ const { baseUrl, getApiHeaders } = (0, _fluid_app_portal_core_data_sources_context.useDataSourceConfig)();
47
+ const { isPreview } = (0, _fluid_app_portal_core_data_sources_preview_context.useWidgetPreviewContext)();
48
+ return (0, _tanstack_react_query.useQuery)({
49
+ queryKey: [
50
+ "portal-widget-use",
51
+ "todos",
52
+ isPreview ? "preview" : baseUrl
53
+ ],
54
+ queryFn: async ({ signal }) => {
55
+ const url = baseUrl ? `${baseUrl}/tasks` : "/tasks";
56
+ const response = await fetch(url, {
57
+ headers: {
58
+ "content-type": "application/json",
59
+ ...getApiHeaders?.()
60
+ },
61
+ signal
62
+ });
63
+ if (!response.ok) throw new Error(`Failed to fetch todos: ${response.status}`);
64
+ return transformTodos(await response.json());
65
+ },
66
+ enabled: !isPreview,
67
+ ...isPreview && { placeholderData: PREVIEW_DATA }
68
+ });
69
+ }
70
+ function transformTodos(rawData) {
71
+ return rawData.map((todo) => ({
72
+ id: todo.id,
73
+ body: todo.body,
74
+ dueAt: todo.due_at,
75
+ completedAt: todo.completed_at,
76
+ createdAt: todo.created_at,
77
+ contactName: todo.contact ? `${todo.contact.first_name} ${todo.contact.last_name}` : null
78
+ }));
79
+ }
80
+ //#endregion
81
+ //#region src/widgets/ToDoWidget.tsx
82
+ var ToDoWidget_exports = /* @__PURE__ */ require_chunk.__exportAll({
83
+ ToDoWidget: () => ToDoWidget,
84
+ toDoWidgetPropertySchema: () => toDoWidgetPropertySchema
85
+ });
86
+ function ToDoWidget({ titleEnabled = true, titleText = "To-Do", titleFontSize = "lg", titleColor = "foreground", background = {
87
+ type: "solid",
88
+ color: "background"
89
+ }, textColor = "foreground", accentColor = "primary", padding = 4, borderRadius = "md", maxItems = 5, className, ...props }) {
90
+ const backgroundColor = background.color || "background";
91
+ const backgroundImage = (background.resource?.image_url || background.resource?.imageUrl) && background.type === "image" ? `url(${background.resource.image_url || background.resource.imageUrl})` : "none";
92
+ const { data: todos = [], isLoading, isError } = useTodos();
93
+ const activeTodos = (todos.length > 0 ? todos : []).filter((todo) => !todo.completedAt);
94
+ const todosToShow = activeTodos.slice(0, maxItems);
95
+ const remainingCount = activeTodos.length - todosToShow.length;
96
+ const isEmpty = activeTodos.length === 0;
97
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
98
+ className: `overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} p-${padding} ${className ?? ""}`,
99
+ style: { backgroundImage },
100
+ ...props,
101
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
102
+ className: "mb-3 flex items-center justify-between",
103
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
104
+ className: "flex items-center gap-3",
105
+ children: titleEnabled && titleText && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
106
+ className: `text-${titleFontSize} font-bold text-${titleColor}`,
107
+ children: titleText
108
+ })
109
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
110
+ className: "flex items-center gap-2",
111
+ children: [!isEmpty && !isLoading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
112
+ className: `text-2xl font-bold text-${accentColor}`,
113
+ children: activeTodos.length
114
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
115
+ className: `flex h-10 w-10 shrink-0 items-center justify-center`,
116
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_fortawesome_react_fontawesome.FontAwesomeIcon, {
117
+ icon: _fortawesome_pro_regular_svg_icons.faListCheck,
118
+ className: `h-5 w-5 text-${accentColor}-foreground`
119
+ })
120
+ })]
121
+ })]
122
+ }), isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
123
+ className: "flex min-h-[120px] items-center justify-center",
124
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-current border-t-transparent" })
125
+ }) : isError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_error_state.ErrorState, {}) : isEmpty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
126
+ className: "flex flex-col items-center justify-center py-8",
127
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
128
+ className: `text-center text-${textColor}/60`,
129
+ children: "You've got nothing else To-Do!"
130
+ })
131
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
132
+ className: "flex flex-col",
133
+ children: todosToShow.map((todo, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
134
+ className: `flex items-center gap-3 py-2.5 ${index !== todosToShow.length - 1 ? `border-b border-${textColor}/10` : ""}`,
135
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
136
+ type: "checkbox",
137
+ className: `h-5 w-5 rounded-full border-2 border-${textColor}/30 bg-transparent`,
138
+ checked: !!todo.completedAt,
139
+ readOnly: true
140
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
141
+ className: "line-clamp-1 flex-1 text-sm",
142
+ children: todo.body
143
+ })]
144
+ }, todo.id))
145
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
146
+ className: "mt-2 flex items-center justify-between",
147
+ children: [remainingCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
148
+ className: `text-sm text-${textColor}/50 underline`,
149
+ children: [
150
+ remainingCount,
151
+ " more task",
152
+ remainingCount > 1 ? "s" : ""
153
+ ]
154
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
155
+ className: "ml-auto",
156
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_fortawesome_react_fontawesome.FontAwesomeIcon, {
157
+ icon: _fortawesome_pro_regular_svg_icons.faPlus,
158
+ className: `h-5 w-5 text-${textColor}/50`
159
+ })
160
+ })]
161
+ })] })]
162
+ });
163
+ }
164
+ const toDoWidgetPropertySchema = {
165
+ widgetType: "ToDoWidget",
166
+ displayName: "To-Do Widget",
167
+ tabsConfig: [{
168
+ id: "styling",
169
+ label: "Styling"
170
+ }],
171
+ fields: [
172
+ {
173
+ key: "titleEnabled",
174
+ label: "Widget Title",
175
+ type: "boolean",
176
+ description: "Enable the title displayed above the todo list",
177
+ defaultValue: true,
178
+ tab: "styling",
179
+ group: "Title"
180
+ },
181
+ {
182
+ key: "titleText",
183
+ label: "Title",
184
+ type: "text",
185
+ description: "Title text displayed above the todo list",
186
+ defaultValue: "To-Do",
187
+ tab: "styling",
188
+ group: "Title",
189
+ requiresKeyToBeTrue: "titleEnabled"
190
+ },
191
+ (0, _fluid_app_portal_core_registries.getFontSizeField)({
192
+ key: "titleFontSize",
193
+ label: "Title Font Size",
194
+ description: "Font size for the widget title",
195
+ defaultValue: "xl",
196
+ tab: "styling",
197
+ group: "Title",
198
+ requiresKeyToBeTrue: "titleEnabled"
199
+ }),
200
+ (0, _fluid_app_portal_core_registries.getColorField)({
201
+ key: "titleColor",
202
+ label: "Title Color",
203
+ description: "Color for the widget title",
204
+ defaultValue: "foreground",
205
+ tab: "styling",
206
+ group: "Title",
207
+ requiresKeyToBeTrue: "titleEnabled"
208
+ }),
209
+ {
210
+ type: "background",
211
+ key: "background",
212
+ label: "Background",
213
+ description: "Background for the widget container",
214
+ defaultValue: "background",
215
+ tab: "styling",
216
+ group: "Design"
217
+ },
218
+ (0, _fluid_app_portal_core_registries.getColorField)({
219
+ key: "textColor",
220
+ label: "Text Color",
221
+ description: "Default text color for todo items",
222
+ defaultValue: "foreground",
223
+ tab: "styling",
224
+ group: "Design"
225
+ }),
226
+ (0, _fluid_app_portal_core_registries.getColorField)({
227
+ key: "accentColor",
228
+ label: "Accent Color",
229
+ description: "Color used for count badge and icon",
230
+ defaultValue: "primary",
231
+ tab: "styling",
232
+ group: "Design"
233
+ }),
234
+ {
235
+ key: "separator",
236
+ type: "separator",
237
+ label: "Separator",
238
+ tab: "styling",
239
+ group: "Design"
240
+ },
241
+ {
242
+ key: "maxItems",
243
+ label: "Max Items",
244
+ type: "number",
245
+ description: "Maximum number of todo items to display",
246
+ min: 1,
247
+ max: 20,
248
+ step: 1,
249
+ defaultValue: 5,
250
+ tab: "styling",
251
+ group: "Design"
252
+ },
253
+ (0, _fluid_app_portal_core_registries.getPaddingField)({
254
+ key: "padding",
255
+ label: "Padding",
256
+ description: "Padding around the widget container",
257
+ defaultValue: 4,
258
+ tab: "styling",
259
+ group: "Design"
260
+ }),
261
+ (0, _fluid_app_portal_core_registries.getBorderRadiusField)({
262
+ key: "borderRadius",
263
+ label: "Border Radius",
264
+ description: "Border radius for the widget container",
265
+ defaultValue: "md",
266
+ tab: "styling",
267
+ group: "Design"
268
+ })
269
+ ]
270
+ };
271
+ //#endregion
272
+ Object.defineProperty(exports, "ToDoWidget", {
273
+ enumerable: true,
274
+ get: function() {
275
+ return ToDoWidget;
276
+ }
277
+ });
278
+ Object.defineProperty(exports, "ToDoWidget_exports", {
279
+ enumerable: true,
280
+ get: function() {
281
+ return ToDoWidget_exports;
282
+ }
283
+ });
284
+ Object.defineProperty(exports, "toDoWidgetPropertySchema", {
285
+ enumerable: true,
286
+ get: function() {
287
+ return toDoWidgetPropertySchema;
288
+ }
289
+ });
290
+
291
+ //# sourceMappingURL=ToDoWidget-Dvs0GDkx.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToDoWidget-Dvs0GDkx.cjs","names":["FontAwesomeIcon","faListCheck","ErrorState","faPlus"],"sources":["../src/hooks/use-todos.preview.ts","../src/hooks/use-todos.ts","../src/widgets/ToDoWidget.tsx"],"sourcesContent":["import type { Todo } from \"./use-todos.types\";\n\nconst now = new Date();\n\nfunction daysFromNow(days: number): string {\n const d = new Date(now);\n d.setDate(d.getDate() + days);\n return d.toISOString();\n}\n\nexport const PREVIEW_DATA: Todo[] = [\n {\n id: 1,\n body: \"Send follow-up email to new leads\",\n dueAt: daysFromNow(1),\n completedAt: null,\n createdAt: daysFromNow(-2),\n contactName: \"Sarah Johnson\",\n },\n {\n id: 2,\n body: \"Prepare slides for team training\",\n dueAt: daysFromNow(3),\n completedAt: null,\n createdAt: daysFromNow(-1),\n contactName: null,\n },\n {\n id: 3,\n body: \"Review monthly sales report\",\n dueAt: daysFromNow(-1),\n completedAt: null,\n createdAt: daysFromNow(-5),\n contactName: \"Mike Chen\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useDataSourceConfig } from \"@fluid-app/portal-core/data-sources/context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-core/data-sources/preview-context\";\nimport { PREVIEW_DATA } from \"./use-todos.preview\";\nimport type { ApiTodo, Todo } from \"./use-todos.types\";\n\nexport type { TodoContact, ApiTodo, Todo } from \"./use-todos.types\";\n\nexport function useTodos(): UseQueryResult<Todo[], Error> {\n const { baseUrl, getApiHeaders } = useDataSourceConfig();\n const { isPreview } = useWidgetPreviewContext();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"todos\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: async ({ signal }): Promise<Todo[]> => {\n const url = baseUrl ? `${baseUrl}/tasks` : \"/tasks\";\n const response = await fetch(url, {\n headers: {\n \"content-type\": \"application/json\",\n ...getApiHeaders?.(),\n },\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch todos: ${response.status}`);\n }\n\n const data: ApiTodo[] = await response.json();\n return transformTodos(data);\n },\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n\nfunction transformTodos(rawData: ApiTodo[]): Todo[] {\n return rawData.map((todo) => ({\n id: todo.id,\n body: todo.body,\n dueAt: todo.due_at,\n completedAt: todo.completed_at,\n createdAt: todo.created_at,\n contactName: todo.contact\n ? `${todo.contact.first_name} ${todo.contact.last_name}`\n : null,\n }));\n}\n","import type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport { faListCheck, faPlus } from \"@fortawesome/pro-regular-svg-icons\";\nimport { useTodos } from \"../hooks/use-todos\";\nimport { ErrorState } from \"../components/error-state\";\n\ntype ToDoWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Content\n maxItems?: number;\n};\n\nexport function ToDoWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"To-Do\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n // Content defaults\n maxItems = 5,\n\n className,\n ...props\n}: ToDoWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n const { data: todos = [], isLoading, isError } = useTodos();\n\n // Use API data if available, otherwise fall back to demo data\n const displayTodos = todos.length > 0 ? todos : [];\n\n // Filter out completed tasks\n const activeTodos = displayTodos.filter((todo) => !todo.completedAt);\n const todosToShow = activeTodos.slice(0, maxItems);\n const remainingCount = activeTodos.length - todosToShow.length;\n const isEmpty = activeTodos.length === 0;\n\n return (\n <div\n className={`overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} p-${padding} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {/* Header */}\n <div className=\"mb-3 flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n {titleEnabled && titleText && (\n <h2\n className={`text-${titleFontSize} font-bold text-${titleColor}`}\n >\n {titleText}\n </h2>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {!isEmpty && !isLoading && (\n <span className={`text-2xl font-bold text-${accentColor}`}>\n {activeTodos.length}\n </span>\n )}\n <div\n className={`flex h-10 w-10 shrink-0 items-center justify-center`}\n >\n <FontAwesomeIcon\n icon={faListCheck}\n className={`h-5 w-5 text-${accentColor}-foreground`}\n />\n </div>\n </div>\n </div>\n\n {/* Loading state */}\n {isLoading ? (\n <div className=\"flex min-h-[120px] items-center justify-center\">\n <div className=\"h-6 w-6 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n /* Error state */\n <ErrorState />\n ) : isEmpty ? (\n /* Empty state */\n <div className=\"flex flex-col items-center justify-center py-8\">\n <p className={`text-center text-${textColor}/60`}>\n You&apos;ve got nothing else To-Do!\n </p>\n </div>\n ) : (\n /* Todo List */\n <>\n <div className=\"flex flex-col\">\n {todosToShow.map((todo, index) => (\n <div\n key={todo.id}\n className={`flex items-center gap-3 py-2.5 ${\n index !== todosToShow.length - 1\n ? `border-b border-${textColor}/10`\n : \"\"\n }`}\n >\n <input\n type=\"checkbox\"\n className={`h-5 w-5 rounded-full border-2 border-${textColor}/30 bg-transparent`}\n checked={!!todo.completedAt}\n readOnly\n />\n <span className=\"line-clamp-1 flex-1 text-sm\">{todo.body}</span>\n </div>\n ))}\n </div>\n\n {/* Footer */}\n <div className=\"mt-2 flex items-center justify-between\">\n {remainingCount > 0 && (\n <span className={`text-sm text-${textColor}/50 underline`}>\n {remainingCount} more task{remainingCount > 1 ? \"s\" : \"\"}\n </span>\n )}\n <div className=\"ml-auto\">\n <FontAwesomeIcon\n icon={faPlus}\n className={`h-5 w-5 text-${textColor}/50`}\n />\n </div>\n </div>\n </>\n )}\n </div>\n );\n}\n\nexport const toDoWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"ToDoWidget\",\n displayName: \"To-Do Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the todo list\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the todo list\",\n defaultValue: \"To-Do\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for todo items\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color used for count badge and icon\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"maxItems\",\n label: \"Max Items\",\n type: \"number\",\n description: \"Maximum number of todo items to display\",\n min: 1,\n max: 20,\n step: 1,\n defaultValue: 5,\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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P,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;uDACY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,MAAM;GACN,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;uDACa;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;uDACY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACR;yDACe;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;8DACmB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
@@ -0,0 +1,192 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs";
2
+ import { t as MediaRenderer } from "./MediaRenderer-Uq90PZcY.mjs";
3
+ import { getBorderRadiusField, getHeightField } from "@fluid-app/portal-core/registries";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/widgets/VideoWidget.tsx
6
+ var VideoWidget_exports = /* @__PURE__ */ __exportAll({
7
+ VideoWidget: () => VideoWidget,
8
+ videoWidgetPropertySchema: () => videoWidgetPropertySchema
9
+ });
10
+ function VideoWidget({ src = "", poster = "", borderRadius = "md", verticalSizing = "auto", fixedHeight = "200px", displayFit = "cover", focusPoint, controls = true, autoplay = false, loop = false, muted = false, resource, useCustomUrl }) {
11
+ const effectiveSrc = useCustomUrl ? src : resource?.videoUrl ?? src;
12
+ const effectivePoster = useCustomUrl ? poster : resource?.imageUrl ?? poster;
13
+ const isFixed = verticalSizing === "fixed";
14
+ return /* @__PURE__ */ jsx("div", {
15
+ className: `relative w-full overflow-hidden rounded-${borderRadius}`,
16
+ style: isFixed ? { height: fixedHeight } : void 0,
17
+ children: /* @__PURE__ */ jsx(MediaRenderer, {
18
+ mediaType: "video",
19
+ src: effectiveSrc,
20
+ poster: effectivePoster,
21
+ objectFit: isFixed ? displayFit : void 0,
22
+ focusPoint: isFixed ? focusPoint : void 0,
23
+ controls,
24
+ autoplay,
25
+ loop,
26
+ muted
27
+ })
28
+ });
29
+ }
30
+ const videoWidgetPropertySchema = {
31
+ widgetType: "VideoWidget",
32
+ displayName: "Video",
33
+ tabsConfig: [{
34
+ id: "styling",
35
+ label: "Styling"
36
+ }, {
37
+ id: "behavior",
38
+ label: "Behavior"
39
+ }],
40
+ fields: [
41
+ {
42
+ key: "resource",
43
+ label: "Select Video",
44
+ type: "resource",
45
+ description: "Browse and select a video",
46
+ allowedTypes: ["Medium"],
47
+ tab: "styling",
48
+ group: "Content"
49
+ },
50
+ {
51
+ key: "useCustomUrl",
52
+ label: "Use Custom URL",
53
+ type: "boolean",
54
+ description: "Enter a custom video URL instead of selecting media",
55
+ defaultValue: false,
56
+ tab: "styling",
57
+ group: "Content"
58
+ },
59
+ {
60
+ key: "src",
61
+ label: "Video URL",
62
+ type: "text",
63
+ description: "The source URL of the video",
64
+ defaultValue: "",
65
+ tab: "styling",
66
+ group: "Content",
67
+ requiresKeyToBeTrue: "useCustomUrl"
68
+ },
69
+ {
70
+ key: "poster",
71
+ label: "Poster Image URL",
72
+ type: "text",
73
+ description: "Thumbnail image displayed before video plays",
74
+ defaultValue: "",
75
+ tab: "styling",
76
+ group: "Content",
77
+ requiresKeyToBeTrue: "useCustomUrl"
78
+ },
79
+ getBorderRadiusField({
80
+ key: "borderRadius",
81
+ label: "Border Radius",
82
+ description: "Border radius for the calendar container",
83
+ defaultValue: "md",
84
+ tab: "styling",
85
+ group: "Design"
86
+ }),
87
+ {
88
+ key: "verticalSizing",
89
+ label: "Vertical Sizing",
90
+ type: "buttonGroup",
91
+ description: "How the video height is determined",
92
+ options: [{
93
+ label: "Auto",
94
+ value: "auto"
95
+ }, {
96
+ label: "Fixed",
97
+ value: "fixed"
98
+ }],
99
+ defaultValue: "auto",
100
+ tab: "styling",
101
+ group: "Design"
102
+ },
103
+ getHeightField({
104
+ key: "fixedHeight",
105
+ label: "Height",
106
+ description: "Fixed height of the video container",
107
+ min: 10,
108
+ max: 1200,
109
+ step: 10,
110
+ defaultValue: "200px",
111
+ tab: "styling",
112
+ group: "Design",
113
+ requiresKeyValue: {
114
+ key: "verticalSizing",
115
+ value: "fixed"
116
+ }
117
+ }),
118
+ {
119
+ key: "displayFit",
120
+ label: "Display Fit",
121
+ type: "buttonGroup",
122
+ description: "How the video fills its container",
123
+ options: [{
124
+ label: "Cover",
125
+ value: "cover"
126
+ }, {
127
+ label: "Contain",
128
+ value: "contain"
129
+ }],
130
+ defaultValue: "cover",
131
+ tab: "styling",
132
+ group: "Design",
133
+ requiresKeyValue: {
134
+ key: "verticalSizing",
135
+ value: "fixed"
136
+ }
137
+ },
138
+ {
139
+ key: "focusPoint",
140
+ label: "Focus Point",
141
+ type: "contentPosition",
142
+ description: "The focal point of the video within its container",
143
+ defaultValue: "center",
144
+ tab: "styling",
145
+ group: "Design",
146
+ requiresKeyValue: {
147
+ key: "verticalSizing",
148
+ value: "fixed"
149
+ }
150
+ },
151
+ {
152
+ key: "controls",
153
+ label: "Show Controls",
154
+ type: "boolean",
155
+ description: "Display video playback controls",
156
+ defaultValue: true,
157
+ tab: "behavior",
158
+ group: "Behavior"
159
+ },
160
+ {
161
+ key: "autoplay",
162
+ label: "Autoplay",
163
+ type: "boolean",
164
+ description: "Automatically start playing the video",
165
+ defaultValue: false,
166
+ tab: "behavior",
167
+ group: "Behavior"
168
+ },
169
+ {
170
+ key: "loop",
171
+ label: "Loop",
172
+ type: "boolean",
173
+ description: "Repeat the video when it ends",
174
+ defaultValue: false,
175
+ tab: "behavior",
176
+ group: "Behavior"
177
+ },
178
+ {
179
+ key: "muted",
180
+ label: "Muted",
181
+ type: "boolean",
182
+ description: "Start with audio muted",
183
+ defaultValue: false,
184
+ tab: "behavior",
185
+ group: "Behavior"
186
+ }
187
+ ]
188
+ };
189
+ //#endregion
190
+ export { VideoWidget_exports as n, videoWidgetPropertySchema as r, VideoWidget as t };
191
+
192
+ //# sourceMappingURL=VideoWidget-D6C_jHOF.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoWidget-D6C_jHOF.mjs","names":[],"sources":["../src/widgets/VideoWidget.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n getBorderRadiusField,\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport type {\n BorderRadiusOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport { MediaRenderer } from \"../components/MediaRenderer\";\n\ntype VideoWidgetProps = ComponentProps<\"div\"> & {\n src?: string;\n poster?: string;\n borderRadius?: BorderRadiusOptions;\n verticalSizing?: \"auto\" | \"fixed\";\n fixedHeight?: string;\n displayFit?: \"cover\" | \"contain\";\n focusPoint?: string;\n controls?: boolean;\n autoplay?: boolean;\n loop?: boolean;\n muted?: boolean;\n resource?: ShareableItem;\n useCustomUrl?: boolean;\n};\n\nexport function VideoWidget({\n src = \"\",\n poster = \"\",\n borderRadius = \"md\",\n verticalSizing = \"auto\",\n fixedHeight = \"200px\",\n displayFit = \"cover\",\n focusPoint,\n controls = true,\n autoplay = false,\n loop = false,\n muted = false,\n resource,\n useCustomUrl,\n}: VideoWidgetProps): React.JSX.Element {\n const effectiveSrc = useCustomUrl ? src : (resource?.videoUrl ?? src);\n const effectivePoster = useCustomUrl\n ? poster\n : (resource?.imageUrl ?? poster);\n\n const isFixed = verticalSizing === \"fixed\";\n\n return (\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius}`}\n style={isFixed ? { height: fixedHeight } : undefined}\n >\n <MediaRenderer\n mediaType=\"video\"\n src={effectiveSrc}\n poster={effectivePoster}\n objectFit={isFixed ? displayFit : undefined}\n focusPoint={isFixed ? focusPoint : undefined}\n controls={controls}\n autoplay={autoplay}\n loop={loop}\n muted={muted}\n />\n </div>\n );\n}\n\nexport const videoWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"VideoWidget\",\n displayName: \"Video\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n ],\n fields: [\n // Styling tab - Content group\n {\n key: \"resource\",\n label: \"Select Video\",\n type: \"resource\",\n description: \"Browse and select a video\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n {\n key: \"useCustomUrl\",\n label: \"Use Custom URL\",\n type: \"boolean\",\n description: \"Enter a custom video URL instead of selecting media\",\n defaultValue: false,\n tab: \"styling\",\n group: \"Content\",\n },\n {\n key: \"src\",\n label: \"Video URL\",\n type: \"text\",\n description: \"The source URL of the video\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Content\",\n requiresKeyToBeTrue: \"useCustomUrl\",\n },\n {\n key: \"poster\",\n label: \"Poster Image URL\",\n type: \"text\",\n description: \"Thumbnail image displayed before video plays\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Content\",\n requiresKeyToBeTrue: \"useCustomUrl\",\n },\n\n // Styling tab - Design group\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the calendar container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"verticalSizing\",\n label: \"Vertical Sizing\",\n type: \"buttonGroup\",\n description: \"How the video height is determined\",\n options: [\n { label: \"Auto\", value: \"auto\" },\n { label: \"Fixed\", value: \"fixed\" },\n ],\n defaultValue: \"auto\",\n tab: \"styling\",\n group: \"Design\",\n },\n getHeightField({\n key: \"fixedHeight\",\n label: \"Height\",\n description: \"Fixed height of the video container\",\n min: 10,\n max: 1200,\n step: 10,\n defaultValue: \"200px\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n }),\n {\n key: \"displayFit\",\n label: \"Display Fit\",\n type: \"buttonGroup\",\n description: \"How the video fills its container\",\n options: [\n { label: \"Cover\", value: \"cover\" },\n { label: \"Contain\", value: \"contain\" },\n ],\n defaultValue: \"cover\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n },\n {\n key: \"focusPoint\",\n label: \"Focus Point\",\n type: \"contentPosition\",\n description: \"The focal point of the video within its container\",\n defaultValue: \"center\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n },\n\n // Behavior tab\n {\n key: \"controls\",\n label: \"Show Controls\",\n type: \"boolean\",\n description: \"Display video playback controls\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Behavior\",\n },\n {\n key: \"autoplay\",\n label: \"Autoplay\",\n type: \"boolean\",\n description: \"Automatically start playing the video\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Behavior\",\n },\n {\n key: \"loop\",\n label: \"Loop\",\n type: \"boolean\",\n description: \"Repeat the video when it ends\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Behavior\",\n },\n {\n key: \"muted\",\n label: \"Muted\",\n type: \"boolean\",\n description: \"Start with audio muted\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Behavior\",\n },\n ],\n};\n"],"mappings":";;;;;;;;;AA6BA,SAAgB,YAAY,EAC1B,MAAM,IACN,SAAS,IACT,eAAe,MACf,iBAAiB,QACjB,cAAc,SACd,aAAa,SACb,YACA,WAAW,MACX,WAAW,OACX,OAAO,OACP,QAAQ,OACR,UACA,gBACsC;CACtC,MAAM,eAAe,eAAe,MAAO,UAAU,YAAY;CACjE,MAAM,kBAAkB,eACpB,SACC,UAAU,YAAY;CAE3B,MAAM,UAAU,mBAAmB;AAEnC,QACE,oBAAC,OAAD;EACE,WAAW,2CAA2C;EACtD,OAAO,UAAU,EAAE,QAAQ,aAAa,GAAG,KAAA;YAE3C,oBAAC,eAAD;GACE,WAAU;GACV,KAAK;GACL,QAAQ;GACR,WAAW,UAAU,aAAa,KAAA;GAClC,YAAY,UAAU,aAAa,KAAA;GACzB;GACA;GACJ;GACC;GACP,CAAA;EACE,CAAA;;AAIV,MAAa,4BAAkD;CAC7D,YAAY;CACZ,aAAa;CACb,YAAY,CACV;EAAE,IAAI;EAAW,OAAO;EAAW,EACnC;EAAE,IAAI;EAAY,OAAO;EAAY,CACtC;CACD,QAAQ;EAEN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc,CAAC,SAAS;GACxB,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAGD,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,SAAS,CACP;IAAE,OAAO;IAAQ,OAAO;IAAQ,EAChC;IAAE,OAAO;IAAS,OAAO;IAAS,CACnC;GACD,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD,eAAe;GACb,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAkB,OAAO;IAAS;GAC5D,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAW,OAAO;IAAW,CACvC;GACD,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAkB,OAAO;IAAS;GAC5D;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAkB,OAAO;IAAS;GAC5D;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACF;CACF"}