@fluid-app/portal-sdk 0.1.364 → 0.1.366

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 (78) hide show
  1. package/dist/{AddressAutocompleteInput-cy8R9p6W.mjs → AddressAutocompleteInput-9gpjXB6B.mjs} +2 -2
  2. package/dist/{AddressAutocompleteInput-cy8R9p6W.mjs.map → AddressAutocompleteInput-9gpjXB6B.mjs.map} +1 -1
  3. package/dist/{AddressAutocompleteInput-BW0MZsjD.cjs → AddressAutocompleteInput-CFe3IfOj.cjs} +2 -2
  4. package/dist/{AddressAutocompleteInput-BW0MZsjD.cjs.map → AddressAutocompleteInput-CFe3IfOj.cjs.map} +1 -1
  5. package/dist/{EmbedWidget-BMy0C8ik.cjs → EmbedWidget-CiqR6HSo.cjs} +36 -6
  6. package/dist/EmbedWidget-CiqR6HSo.cjs.map +1 -0
  7. package/dist/{EmbedWidget-V-pGzMRC.mjs → EmbedWidget-ZPG0lFgF.mjs} +36 -6
  8. package/dist/EmbedWidget-ZPG0lFgF.mjs.map +1 -0
  9. package/dist/{FluidProvider-JmlsI08v.cjs → FluidProvider-2gVDT1i4.cjs} +11 -11
  10. package/dist/{FluidProvider-JmlsI08v.cjs.map → FluidProvider-2gVDT1i4.cjs.map} +1 -1
  11. package/dist/{FluidProvider-Cwnzfzi6.mjs → FluidProvider-2rT0X7u1.mjs} +11 -11
  12. package/dist/{FluidProvider-Cwnzfzi6.mjs.map → FluidProvider-2rT0X7u1.mjs.map} +1 -1
  13. package/dist/{ImageWidget-B6DESmDt.mjs → ImageWidget-B2FEHT-v.mjs} +2 -3
  14. package/dist/ImageWidget-B2FEHT-v.mjs.map +1 -0
  15. package/dist/{ImageWidget-Cz1W-CaS.cjs → ImageWidget-r9sPbyeC.cjs} +2 -3
  16. package/dist/ImageWidget-r9sPbyeC.cjs.map +1 -0
  17. package/dist/{ListWidget-CRsc53kj.mjs → ListWidget-C1_Fd58S.mjs} +5 -4
  18. package/dist/ListWidget-C1_Fd58S.mjs.map +1 -0
  19. package/dist/{ListWidget-IxrLNslF.cjs → ListWidget-D_C0p7HR.cjs} +5 -4
  20. package/dist/ListWidget-D_C0p7HR.cjs.map +1 -0
  21. package/dist/{ListWidget-BOH7TJJj.cjs → ListWidget-hz_xueC7.cjs} +1 -1
  22. package/dist/{MessagingScreen-BPJLhWGi.mjs → MessagingScreen-BR5ISUoK.mjs} +8 -7
  23. package/dist/{MessagingScreen-CgIlbc7d.cjs → MessagingScreen-FObvFAzr.cjs} +7 -7
  24. package/dist/{MessagingScreen-BJr7zF2A.mjs → MessagingScreen-UptArERP.mjs} +2 -2
  25. package/dist/{MessagingScreen-BJr7zF2A.mjs.map → MessagingScreen-UptArERP.mjs.map} +1 -1
  26. package/dist/{MessagingScreen-DVDFx_8s.cjs → MessagingScreen-ycXsOE9D.cjs} +2 -2
  27. package/dist/{MessagingScreen-DVDFx_8s.cjs.map → MessagingScreen-ycXsOE9D.cjs.map} +1 -1
  28. package/dist/{NestedWidget-BPTo7RQZ.mjs → NestedWidget-9eJaAdz9.mjs} +3 -3
  29. package/dist/{NestedWidget-BPTo7RQZ.mjs.map → NestedWidget-9eJaAdz9.mjs.map} +1 -1
  30. package/dist/{NestedWidget-Bg6vB_A6.cjs → NestedWidget-COMzekmy.cjs} +3 -3
  31. package/dist/{NestedWidget-Bg6vB_A6.cjs.map → NestedWidget-COMzekmy.cjs.map} +1 -1
  32. package/dist/{NestedWidget-Bep9VZwW.cjs → NestedWidget-DzBrds9R.cjs} +1 -1
  33. package/dist/{OrdersScreen-BvI394f1.cjs → OrdersScreen-B0Sg_NO1.cjs} +7 -7
  34. package/dist/{OrdersScreen-Ch9ia2Ga.mjs → OrdersScreen-BOFYWEZS.mjs} +2 -2
  35. package/dist/{OrdersScreen-Ch9ia2Ga.mjs.map → OrdersScreen-BOFYWEZS.mjs.map} +1 -1
  36. package/dist/{OrdersScreen-BC95_oBa.cjs → OrdersScreen-C__4uFwk.cjs} +2 -2
  37. package/dist/{OrdersScreen-BC95_oBa.cjs.map → OrdersScreen-C__4uFwk.cjs.map} +1 -1
  38. package/dist/{OrdersScreen-ClfjwlXi.mjs → OrdersScreen-Dm6J3112.mjs} +9 -7
  39. package/dist/{ProfileScreen-Bzfqc83K.cjs → ProfileScreen-5OPs7V99.cjs} +3 -3
  40. package/dist/{ProfileScreen-Bzfqc83K.cjs.map → ProfileScreen-5OPs7V99.cjs.map} +1 -1
  41. package/dist/{ProfileScreen-G3djGmU2.cjs → ProfileScreen-B7t-OVVJ.cjs} +8 -8
  42. package/dist/{ProfileScreen-DpUI78i1.mjs → ProfileScreen-COmd8OlO.mjs} +9 -8
  43. package/dist/{ProfileScreen-CEylhJU6.mjs → ProfileScreen-DUUPJzb4.mjs} +3 -3
  44. package/dist/{ProfileScreen-CEylhJU6.mjs.map → ProfileScreen-DUUPJzb4.mjs.map} +1 -1
  45. package/dist/{ShareablesScreen-CaVbAkb1.mjs → ShareablesScreen-BUg9Xl7e.mjs} +2 -0
  46. package/dist/{ShopScreen-CtglELsz.mjs → ShopScreen-BhrrBjS4.mjs} +8 -12
  47. package/dist/ShopScreen-BhrrBjS4.mjs.map +1 -0
  48. package/dist/{ShopScreen-g_umkXKo.cjs → ShopScreen-BqlB_GOB.cjs} +7 -7
  49. package/dist/{ShopScreen-B1HjIt1A.mjs → ShopScreen-CCYT4-tU.mjs} +9 -7
  50. package/dist/{ShopScreen-CPeoDfhv.cjs → ShopScreen-Dyl1Ne8n.cjs} +8 -12
  51. package/dist/ShopScreen-Dyl1Ne8n.cjs.map +1 -0
  52. package/dist/{SubscriptionsScreen-mAXtV4Oy.cjs → SubscriptionsScreen-05KrYqLb.cjs} +3 -3
  53. package/dist/{SubscriptionsScreen-mAXtV4Oy.cjs.map → SubscriptionsScreen-05KrYqLb.cjs.map} +1 -1
  54. package/dist/{SubscriptionsScreen-C6iOeMz4.mjs → SubscriptionsScreen-Dlw3cT_9.mjs} +10 -8
  55. package/dist/{SubscriptionsScreen-BQZQNzIu.cjs → SubscriptionsScreen-Dpg4UCwZ.cjs} +8 -8
  56. package/dist/{SubscriptionsScreen-DyZAbOFn.mjs → SubscriptionsScreen-jEcWsorf.mjs} +3 -3
  57. package/dist/{SubscriptionsScreen-DyZAbOFn.mjs.map → SubscriptionsScreen-jEcWsorf.mjs.map} +1 -1
  58. package/dist/{VideoWidget-DEG652tg.mjs → VideoWidget-CCTaBwub.mjs} +3 -3
  59. package/dist/{VideoWidget-DEG652tg.mjs.map → VideoWidget-CCTaBwub.mjs.map} +1 -1
  60. package/dist/{VideoWidget-CTByie5N.cjs → VideoWidget-rnVfjbuI.cjs} +3 -3
  61. package/dist/{VideoWidget-CTByie5N.cjs.map → VideoWidget-rnVfjbuI.cjs.map} +1 -1
  62. package/dist/index.cjs +22 -22
  63. package/dist/index.d.cts +9 -1
  64. package/dist/index.d.cts.map +1 -1
  65. package/dist/index.d.mts +9 -1
  66. package/dist/index.d.mts.map +1 -1
  67. package/dist/index.mjs +24 -24
  68. package/dist/registries-BWdQbKof.cjs.map +1 -1
  69. package/dist/registries-DT36l-bR.mjs.map +1 -1
  70. package/package.json +17 -17
  71. package/dist/EmbedWidget-BMy0C8ik.cjs.map +0 -1
  72. package/dist/EmbedWidget-V-pGzMRC.mjs.map +0 -1
  73. package/dist/ImageWidget-B6DESmDt.mjs.map +0 -1
  74. package/dist/ImageWidget-Cz1W-CaS.cjs.map +0 -1
  75. package/dist/ListWidget-CRsc53kj.mjs.map +0 -1
  76. package/dist/ListWidget-IxrLNslF.cjs.map +0 -1
  77. package/dist/ShopScreen-CPeoDfhv.cjs.map +0 -1
  78. package/dist/ShopScreen-CtglELsz.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { J as product_by_visits, Q as products_show, X as products_media_list, Y as products_list, Z as products_search, q as product_by_shares } from "./portal_tenant_content-XFmQhJPT.mjs";
2
- import { A as mergeDarkOverrides, C as DEFAULT_SPACING, D as generateThemeCSS, E as getDefaultThemeDefinition, F as RADIUS_KEYS, G as deleteDatabase, I as SEMANTIC_COLOR_NAMES, M as resolveTheme, N as FONT_FAMILY_KEYS, O as deriveDarkVariant, P as FONT_SIZE_KEYS, S as DEFAULT_RADII, T as DEFAULT_THEME_NAME, U as useAppDefinitionApi, V as useLanguagesApi, W as createPersister, _ as deserialiseTheme, a as widgetPropertySchemas, b as DEFAULT_FONT_FAMILIES, c as createWidgetRegistry, d as applyTheme, f as removeAllThemes, g as transformThemes, h as getActiveThemeId, i as DEFAULT_SDK_WIDGET_REGISTRY, j as parseColor, k as getForegroundColor, l as FluidThemeProvider, m as buildThemeDefinition, n as useFluidContext, o as createScreen, p as removeTheme, r as SUPPORTED_LANGUAGES, s as createWidgetFromShareable, t as FluidProvider, u as useThemeContext, v as serialiseTheme, w as DEFAULT_THEME_ID, x as DEFAULT_FONT_SIZES, y as DEFAULT_COLORS } from "./FluidProvider-Cwnzfzi6.mjs";
2
+ import { A as mergeDarkOverrides, C as DEFAULT_SPACING, D as generateThemeCSS, E as getDefaultThemeDefinition, F as RADIUS_KEYS, G as deleteDatabase, I as SEMANTIC_COLOR_NAMES, M as resolveTheme, N as FONT_FAMILY_KEYS, O as deriveDarkVariant, P as FONT_SIZE_KEYS, S as DEFAULT_RADII, T as DEFAULT_THEME_NAME, U as useAppDefinitionApi, V as useLanguagesApi, W as createPersister, _ as deserialiseTheme, a as widgetPropertySchemas, b as DEFAULT_FONT_FAMILIES, c as createWidgetRegistry, d as applyTheme, f as removeAllThemes, g as transformThemes, h as getActiveThemeId, i as DEFAULT_SDK_WIDGET_REGISTRY, j as parseColor, k as getForegroundColor, l as FluidThemeProvider, m as buildThemeDefinition, n as useFluidContext, o as createScreen, p as removeTheme, r as SUPPORTED_LANGUAGES, s as createWidgetFromShareable, t as FluidProvider, u as useThemeContext, v as serialiseTheme, w as DEFAULT_THEME_ID, x as DEFAULT_FONT_SIZES, y as DEFAULT_COLORS } from "./FluidProvider-2rT0X7u1.mjs";
3
3
  import { a as assertNever, i as assertDefined, n as DataAwareWidget, o as isWidgetType, r as WIDGET_TYPE_NAMES, s as isWidgetTypeName, u as useRegistry } from "./ScreenRenderer-BTSp4KZp.mjs";
4
4
  import "./store-api-context-B_vtKkXO.mjs";
5
5
  import "./mysite-api-context-CoLr9vIf.mjs";
@@ -8,7 +8,7 @@ import "./task-composer-form-Cb8v-cYd.mjs";
8
8
  import { n as usePortalTenantClient } from "./PortalTenantClientProvider-RJI-iE2U.mjs";
9
9
  import "./registry-context-CSsT6Rtk.mjs";
10
10
  import { t as WidgetInteractionProvider } from "./WidgetInteractionContext-CDHSzzws.mjs";
11
- import { a as useRepUser, i as RepUserProvider, r as embedWidgetPropertySchema, t as EmbedWidget } from "./EmbedWidget-V-pGzMRC.mjs";
11
+ import { a as useRepUser, i as RepUserProvider, r as embedWidgetPropertySchema, t as EmbedWidget } from "./EmbedWidget-ZPG0lFgF.mjs";
12
12
  import { r as quickLinksWidgetPropertySchema, t as QuickLinksWidget } from "./QuickLinksWidget-j2lahwOn.mjs";
13
13
  import { a as useActiveLocale, n as createDomainTranslations, r as useDomainDict, t as createStaticDictAdapter } from "./static-dict-adapter-DpHMB055.mjs";
14
14
  import "./error-state-OMcqVS6p.mjs";
@@ -27,15 +27,15 @@ import "./MediaRenderer-13Jlf38P.mjs";
27
27
  import { r as carouselWidgetPropertySchema, t as CarouselWidget } from "./CarouselWidget-CuXoSlOs.mjs";
28
28
  import { r as catchUpWidgetPropertySchema, t as CatchUpWidget } from "./CatchUpWidget-BCe8hmdk.mjs";
29
29
  import { At as CardTitle, Dt as CardDescription, En as Button, Ot as CardFooter, Vn as cn$1, _t as CollapsibleContent, g as Skeleton$1, gt as Collapsible, kt as CardHeader, lt as PopoverContent, m as Toaster, st as Popover, ut as PopoverTrigger, vt as CollapsibleTrigger, wt as Card } from "./src-Cn1_6Nn3.mjs";
30
- import { a as useMessagingAuth, i as useMessagingConfig, n as messagingScreenPropertySchema, r as createFluidFileUploader, t as MessagingScreen } from "./MessagingScreen-BJr7zF2A.mjs";
31
- import { n as subscriptionsScreenPropertySchema, t as SubscriptionsScreen } from "./SubscriptionsScreen-DyZAbOFn.mjs";
30
+ import { a as useMessagingAuth, i as useMessagingConfig, n as messagingScreenPropertySchema, r as createFluidFileUploader, t as MessagingScreen } from "./MessagingScreen-UptArERP.mjs";
31
+ import { n as subscriptionsScreenPropertySchema, t as SubscriptionsScreen } from "./SubscriptionsScreen-jEcWsorf.mjs";
32
32
  import { r as chartWidgetPropertySchema, t as ChartWidget } from "./ChartWidget-BiKW7lEN.mjs";
33
33
  import { r as containerWidgetPropertySchema, t as ContainerWidget } from "./ContainerWidget-Bdq6CaDc.mjs";
34
- import { r as imageWidgetPropertySchema, t as ImageWidget } from "./ImageWidget-B6DESmDt.mjs";
34
+ import { r as imageWidgetPropertySchema, t as ImageWidget } from "./ImageWidget-B2FEHT-v.mjs";
35
35
  import { r as linkWidgetPropertySchema, t as LinkWidget } from "./LinkWidget-B6wehYgt.mjs";
36
- import { r as listWidgetPropertySchema, t as ListWidget } from "./ListWidget-CRsc53kj.mjs";
36
+ import { r as listWidgetPropertySchema, t as ListWidget } from "./ListWidget-C1_Fd58S.mjs";
37
37
  import { r as mySiteWidgetPropertySchema, t as MySiteWidget } from "./MySiteWidget-BvFHv9me.mjs";
38
- import { r as nestedWidgetPropertySchema, t as NestedWidget } from "./NestedWidget-BPTo7RQZ.mjs";
38
+ import { r as nestedWidgetPropertySchema, t as NestedWidget } from "./NestedWidget-9eJaAdz9.mjs";
39
39
  import { r as pointsWidgetPropertySchema, t as PointsWidget } from "./PointsWidget-BvLIjvRG.mjs";
40
40
  import { r as quickShareWidgetPropertySchema, t as QuickShareWidget } from "./QuickShareWidget-BGTVy4BT.mjs";
41
41
  import { r as recentActivityWidgetPropertySchema, t as RecentActivityWidget } from "./RecentActivityWidget-ziAimCYB.mjs";
@@ -43,7 +43,7 @@ import { r as separatorWidgetPropertySchema, t as SeparatorWidget } from "./Sepa
43
43
  import { r as spacerWidgetPropertySchema, t as SpacerWidget } from "./SpacerWidget-BpV1WYuj.mjs";
44
44
  import { r as tableWidgetPropertySchema, t as TableWidget } from "./TableWidget-DeZe6uuy.mjs";
45
45
  import { r as toDoWidgetPropertySchema, t as ToDoWidget } from "./ToDoWidget-C6Kk46b7.mjs";
46
- import { r as videoWidgetPropertySchema, t as VideoWidget } from "./VideoWidget-DEG652tg.mjs";
46
+ import { r as videoWidgetPropertySchema, t as VideoWidget } from "./VideoWidget-CCTaBwub.mjs";
47
47
  import { o as PortalProductsCoreProvider } from "./SearchSort-BvSVfOgh.mjs";
48
48
  import { o as ShopTranslationProvider } from "./ShopWidget-C7L8Z0dp.mjs";
49
49
  import { a as matchSlugPrefix, c as getSystemNavigationBySection, d as normalizeSlug, i as isSlugInSection, l as isRepOnlySlug, n as collectNavSlugs, o as slugifyName, r as extractSlugFromPathname, s as SYSTEM_NAVIGATION_ITEMS, u as isSystemNavigationItem } from "./use-navigation-parent-D1jkodSF.mjs";
@@ -53,19 +53,19 @@ import { r as storeKeys } from "./query-keys-xJy_fapN.mjs";
53
53
  import { t as useStore } from "./use-store-CfKYYLnj.mjs";
54
54
  import { t as useAccount } from "./use-account-DEj6E1PK.mjs";
55
55
  import { n as useAppNavigation, t as AppNavigationProvider } from "./AppNavigationContext-lkEJQu3Y.mjs";
56
- import "./AddressAutocompleteInput-cy8R9p6W.mjs";
56
+ import "./AddressAutocompleteInput-9gpjXB6B.mjs";
57
57
  import "./Combobox-DusCsueR.mjs";
58
58
  import "./use-mysite-portal-DOUSRysS.mjs";
59
- import { n as profileScreenPropertySchema, t as ProfileScreen } from "./ProfileScreen-CEylhJU6.mjs";
59
+ import { n as profileScreenPropertySchema, t as ProfileScreen } from "./ProfileScreen-DUUPJzb4.mjs";
60
60
  import "./dist-D7_77Mei.mjs";
61
61
  import "./es-Cqc_xegn.mjs";
62
62
  import { r as contactsScreenPropertySchema, t as ContactsScreen } from "./ContactsScreen-Co6JOwmr.mjs";
63
63
  import "./dist-xbW6G60Y.mjs";
64
- import { n as ordersScreenPropertySchema, t as OrdersScreen } from "./OrdersScreen-Ch9ia2Ga.mjs";
64
+ import { n as ordersScreenPropertySchema, t as OrdersScreen } from "./OrdersScreen-BOFYWEZS.mjs";
65
65
  import { r as mySiteScreenPropertySchema, t as MySiteScreen } from "./MySiteScreen-B_EkUsf3.mjs";
66
66
  import "./sortable.esm-buJuQqW4.mjs";
67
67
  import { n as shareablesScreenPropertySchema, t as ShareablesScreen } from "./ShareablesScreen-NPWkQkoM.mjs";
68
- import { n as shopScreenPropertySchema, t as ShopScreen } from "./ShopScreen-CtglELsz.mjs";
68
+ import { n as shopScreenPropertySchema, t as ShopScreen } from "./ShopScreen-BhrrBjS4.mjs";
69
69
  import "./UpgradeScreen-qiXlAydW.mjs";
70
70
  import "./AppDownloadScreen-3xiLZXHs.mjs";
71
71
  import * as React$1 from "react";
@@ -1977,14 +1977,14 @@ function BuilderScreenViewImpl({ screen, className }) {
1977
1977
  const BuilderScreenView = memo(BuilderScreenViewImpl);
1978
1978
  //#endregion
1979
1979
  //#region src/shell/system-screen-map.ts
1980
- const ProfileScreen$1 = lazy(() => import("./ProfileScreen-DpUI78i1.mjs").then((m) => ({ default: m.ProfileScreen })));
1981
- const OrdersScreen$1 = lazy(() => import("./OrdersScreen-ClfjwlXi.mjs").then((m) => ({ default: m.OrdersScreen })));
1982
- const SubscriptionsScreen$1 = lazy(() => import("./SubscriptionsScreen-C6iOeMz4.mjs").then((m) => ({ default: m.SubscriptionsScreen })));
1983
- const MessagingScreen$1 = lazy(() => import("./MessagingScreen-BPJLhWGi.mjs").then((m) => ({ default: m.MessagingScreen })));
1980
+ const ProfileScreen$1 = lazy(() => import("./ProfileScreen-COmd8OlO.mjs").then((m) => ({ default: m.ProfileScreen })));
1981
+ const OrdersScreen$1 = lazy(() => import("./OrdersScreen-Dm6J3112.mjs").then((m) => ({ default: m.OrdersScreen })));
1982
+ const SubscriptionsScreen$1 = lazy(() => import("./SubscriptionsScreen-Dlw3cT_9.mjs").then((m) => ({ default: m.SubscriptionsScreen })));
1983
+ const MessagingScreen$1 = lazy(() => import("./MessagingScreen-BR5ISUoK.mjs").then((m) => ({ default: m.MessagingScreen })));
1984
1984
  const ContactsScreen$1 = lazy(() => import("./ContactsScreen-Co6JOwmr.mjs").then((n) => n.n).then((m) => ({ default: m.ContactsScreen })));
1985
- const ShopScreen$1 = lazy(() => import("./ShopScreen-B1HjIt1A.mjs").then((m) => ({ default: m.ShopScreen })));
1985
+ const ShopScreen$1 = lazy(() => import("./ShopScreen-CCYT4-tU.mjs").then((m) => ({ default: m.ShopScreen })));
1986
1986
  const CustomersScreen$1 = lazy(() => import("./CustomersScreen-Bn9TBAXn.mjs").then((n) => n.n).then((m) => ({ default: m.CustomersScreen })));
1987
- const ShareablesScreen$1 = lazy(() => import("./ShareablesScreen-CaVbAkb1.mjs").then((m) => ({ default: m.ShareablesScreen })));
1987
+ const ShareablesScreen$1 = lazy(() => import("./ShareablesScreen-BUg9Xl7e.mjs").then((m) => ({ default: m.ShareablesScreen })));
1988
1988
  const MySiteScreen$1 = lazy(() => import("./MySiteScreen-B_EkUsf3.mjs").then((n) => n.n).then((m) => ({ default: m.MySiteScreen })));
1989
1989
  const UpgradeScreen = lazy(() => import("./UpgradeScreen-qiXlAydW.mjs").then((n) => n.t).then((m) => ({ default: m.UpgradeScreen })));
1990
1990
  const AppDownloadScreen = lazy(() => import("./AppDownloadScreen-3xiLZXHs.mjs").then((n) => n.t).then((m) => ({ default: m.AppDownloadScreen })));
@@ -3898,15 +3898,15 @@ z.object({
3898
3898
  //#endregion
3899
3899
  //#region src/screens/index.ts
3900
3900
  const screenPropertySchemas = {
3901
- ProfileScreen: () => import("./ProfileScreen-DpUI78i1.mjs").then((m) => m.profileScreenPropertySchema),
3902
- MessagingScreen: () => import("./MessagingScreen-BPJLhWGi.mjs").then((m) => m.messagingScreenPropertySchema),
3901
+ ProfileScreen: () => import("./ProfileScreen-COmd8OlO.mjs").then((m) => m.profileScreenPropertySchema),
3902
+ MessagingScreen: () => import("./MessagingScreen-BR5ISUoK.mjs").then((m) => m.messagingScreenPropertySchema),
3903
3903
  ContactsScreen: () => import("./ContactsScreen-Co6JOwmr.mjs").then((n) => n.n).then((m) => m.contactsScreenPropertySchema),
3904
- OrdersScreen: () => import("./OrdersScreen-ClfjwlXi.mjs").then((m) => m.ordersScreenPropertySchema),
3905
- SubscriptionsScreen: () => import("./SubscriptionsScreen-C6iOeMz4.mjs").then((m) => m.subscriptionsScreenPropertySchema),
3904
+ OrdersScreen: () => import("./OrdersScreen-Dm6J3112.mjs").then((m) => m.ordersScreenPropertySchema),
3905
+ SubscriptionsScreen: () => import("./SubscriptionsScreen-Dlw3cT_9.mjs").then((m) => m.subscriptionsScreenPropertySchema),
3906
3906
  CustomersScreen: () => import("./CustomersScreen-Bn9TBAXn.mjs").then((n) => n.n).then((m) => m.customersScreenPropertySchema),
3907
3907
  MySiteScreen: () => import("./MySiteScreen-B_EkUsf3.mjs").then((n) => n.n).then((m) => m.mySiteScreenPropertySchema),
3908
- ShareablesScreen: () => import("./ShareablesScreen-CaVbAkb1.mjs").then((m) => m.shareablesScreenPropertySchema),
3909
- ShopScreen: () => import("./ShopScreen-B1HjIt1A.mjs").then((m) => m.shopScreenPropertySchema),
3908
+ ShareablesScreen: () => import("./ShareablesScreen-BUg9Xl7e.mjs").then((m) => m.shareablesScreenPropertySchema),
3909
+ ShopScreen: () => import("./ShopScreen-CCYT4-tU.mjs").then((m) => m.shopScreenPropertySchema),
3910
3910
  UpgradeScreen: () => import("./UpgradeScreen-qiXlAydW.mjs").then((n) => n.t).then((m) => m.upgradeScreenPropertySchema),
3911
3911
  AppDownloadScreen: () => import("./AppDownloadScreen-3xiLZXHs.mjs").then((n) => n.t).then((m) => m.appDownloadScreenPropertySchema)
3912
3912
  };
@@ -1 +1 @@
1
- {"version":3,"file":"registries-BWdQbKof.cjs","names":["Ban"],"sources":["../../core/src/registries/property-schema-types.ts","../../core/src/registries/field-helpers.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport type {\n WidgetType,\n WidgetSchema,\n AlignOptions,\n ColorOptions,\n FontSizeOptions,\n SectionLayoutType,\n StrictOmit,\n BorderRadiusOptions,\n} from \"../types\";\n\n/**\n * Tab configuration for organizing properties\n */\nexport interface TabConfig {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n}\n\n// ============================================================================\n// Property Field Types - Derive from constant for single source of truth\n// ============================================================================\n\n/**\n * Property field type constant - single source of truth for field types.\n * Use PROPERTY_FIELD_TYPES.text instead of \"text\" for type-safe comparisons.\n */\nexport const PROPERTY_FIELD_TYPES = {\n text: \"text\",\n textarea: \"textarea\",\n number: \"number\",\n boolean: \"boolean\",\n select: \"select\",\n color: \"color\",\n range: \"range\",\n dataSource: \"dataSource\",\n resource: \"resource\",\n image: \"image\",\n alignment: \"alignment\",\n slider: \"slider\",\n colorPicker: \"colorPicker\",\n sectionHeader: \"sectionHeader\",\n separator: \"separator\",\n buttonGroup: \"buttonGroup\",\n colorSelect: \"colorSelect\",\n sectionLayoutSelect: \"sectionLayoutSelect\",\n background: \"background\",\n contentPosition: \"contentPosition\",\n textSizeSelect: \"textSizeSelect\",\n cssUnit: \"cssUnit\",\n fontPicker: \"fontPicker\",\n stringArray: \"stringArray\",\n borderRadius: \"borderRadius\",\n screenPicker: \"screenPicker\",\n} as const;\n\n/**\n * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant.\n * @see deriving-typeof-for-object-keys pattern\n */\nexport type PropertyFieldType =\n (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES];\n\n/**\n * Runtime validation for property field types.\n * @param value - The value to check\n * @returns true if value is a valid PropertyFieldType\n */\nexport function isPropertyFieldType(value: string): value is PropertyFieldType {\n return Object.values(PROPERTY_FIELD_TYPES).includes(\n value as PropertyFieldType,\n );\n}\n\n/**\n * Group label for fields that override theme-derived styling.\n * Rendered last within a tab and collapsed by default so the primary\n * configuration surface stays clean.\n */\nexport const CUSTOM_STYLING_GROUP = \"Custom styling\";\n\n/**\n * Base schema for a property field\n */\nexport interface PropertyFieldSchema {\n /** Property key in the widget props */\n key: string;\n /** Display label for the field */\n label: string;\n /** Field type determines the input control */\n type: PropertyFieldType;\n /** Optional description/help text */\n description?: string;\n /** Optional default value */\n defaultValue?: unknown;\n /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */\n tab?: string;\n /** Optional group for organizing fields within a tab */\n group?: string;\n /**\n * When true, this field is treated as an override of a value that can\n * otherwise be inherited from the active theme (e.g. border radius,\n * padding, border width). Advanced fields are automatically bucketed\n * into the `CUSTOM_STYLING_GROUP` at the bottom of their tab and\n * rendered collapsed by default so the default surface area stays\n * minimal.\n */\n advanced?: boolean;\n /**\n * @deprecated Use requiresKeyValue instead\n */\n requiresKeyToBeTrue?: string;\n /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */\n requiresKeyValue?:\n | { key: string; value: unknown }\n | Array<{ key: string; value: unknown }>;\n}\n\n/**\n * Text field schema\n */\nexport interface TextFieldSchema extends PropertyFieldSchema {\n type: \"text\";\n placeholder?: string;\n maxLength?: number;\n /**\n * Optional quick-insert chips rendered below the input. Clicking a chip\n * inserts `{{value}}` at the caret. Used for URL template tokens\n * (e.g. `{{username}}`, `{{replicated_url || /signup}}`) so admins\n * don't have to remember the exact spelling.\n */\n tokenSuggestions?: ReadonlyArray<{\n /** Chip label shown to the admin (e.g. `username`). */\n label: string;\n /** Token body inserted between `{{` and `}}` (e.g. `username || /signup`). */\n value: string;\n }>;\n}\n\n/**\n * Textarea field schema\n */\nexport interface TextareaFieldSchema extends PropertyFieldSchema {\n type: \"textarea\";\n placeholder?: string;\n rows?: number;\n maxLength?: number;\n}\n\n/**\n * Number field schema\n */\nexport interface NumberFieldSchema extends PropertyFieldSchema {\n type: \"number\";\n min?: number;\n max?: number;\n step?: number;\n}\n\n/**\n * Boolean field schema\n */\nexport interface BooleanFieldSchema extends PropertyFieldSchema {\n type: \"boolean\";\n}\n\n/**\n * Select field schema with type-safe option values.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface SelectFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"select\";\n options: Array<{ label: string; value: T }>;\n defaultValue?: T;\n}\n\n/**\n * Color field schema\n */\nexport interface ColorFieldSchema extends PropertyFieldSchema {\n type: \"color\";\n}\n\n/**\n * Range slider field schema\n */\nexport interface RangeFieldSchema extends PropertyFieldSchema {\n type: \"range\";\n min: number;\n max: number;\n step?: number;\n}\n\n/**\n * Data source field schema for configuring widget data sources\n */\nexport interface DataSourceFieldSchema extends PropertyFieldSchema {\n type: \"dataSource\";\n}\n\n/**\n * Resource field schema for selecting a single resource from the selection modal\n */\nexport interface ResourceFieldSchema extends PropertyFieldSchema {\n type: \"resource\";\n /** Optional filter to specific shareable types */\n allowedTypes?: string[];\n}\n\n/**\n * Image field schema for selecting a single image from the image picker\n */\nexport interface ImageFieldSchema extends PropertyFieldSchema {\n type: \"image\";\n}\n\n/**\n * Alignment field schema\n */\nexport interface AlignmentFieldSchema extends PropertyFieldSchema {\n type: \"alignment\";\n options: {\n verticalEnabled: boolean;\n horizontalEnabled: boolean;\n };\n defaultValue?: AlignOptions;\n}\n\n/**\n * Slider field schema with optional unit suffix (e.g., \"rem\", \"px\")\n */\nexport interface SliderFieldSchema extends PropertyFieldSchema {\n type: \"slider\";\n min: number;\n max: number;\n step?: number;\n unit?: string;\n}\n\n/**\n * Color picker field schema with optional swatches\n */\nexport interface ColorPickerFieldSchema extends PropertyFieldSchema {\n type: \"colorPicker\";\n swatches?: string[];\n}\n\n/**\n * Section header field schema for visual grouping\n */\nexport interface SectionHeaderFieldSchema extends PropertyFieldSchema {\n type: \"sectionHeader\";\n subtitle?: string;\n}\n\n/**\n * Separator field schema for visual separation\n */\nexport interface SeparatorFieldSchema extends PropertyFieldSchema {\n type: \"separator\";\n}\n\n/**\n * Button group field schema.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface ButtonGroupFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"buttonGroup\";\n options: Array<{\n label?: string;\n ariaLabel?: string;\n icon?: LucideIcon;\n value: T;\n }>;\n defaultValue?: T;\n}\n\n/**\n * Color select field schema\n */\nexport interface ColorSelectFieldSchema extends PropertyFieldSchema {\n type: \"colorSelect\";\n defaultValue?: ColorOptions;\n excludeColors?: ColorOptions[];\n}\n\n/**\n * Section layout select field schema for visual masonry layout selector\n */\nexport interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema {\n type: \"sectionLayoutSelect\";\n defaultValue?: SectionLayoutType;\n}\n\n/**\n * Background field combines resource selection and color properties.\n * Uses StrictOmit to exclude conflicting \"type\" discriminant from parents.\n */\nexport interface BackgroundFieldSchema\n extends\n StrictOmit<ResourceFieldSchema, \"type\">,\n StrictOmit<ColorFieldSchema, \"type\"> {\n type: \"background\";\n}\n\n/**\n * Content position field schema for 3x3 grid position picker\n */\nexport interface ContentPositionFieldSchema extends PropertyFieldSchema {\n type: \"contentPosition\";\n defaultValue?: string;\n}\n\n/**\n * Text size select field schema for visual font size selector\n */\nexport interface TextSizeSelectFieldSchema extends PropertyFieldSchema {\n type: \"textSizeSelect\";\n defaultValue?: FontSizeOptions;\n}\n\n/**\n * CSS unit type for height/width fields\n */\nexport type CssUnit = \"px\" | \"rem\" | \"vh\" | \"%\";\n\n/**\n * CSS unit field schema for numeric values with selectable units (px, rem, vh, %)\n */\nexport interface CssUnitFieldSchema extends PropertyFieldSchema {\n type: \"cssUnit\";\n minByUnit?: Partial<Record<CssUnit, number>>;\n maxByUnit?: Partial<Record<CssUnit, number>>;\n stepByUnit?: Partial<Record<CssUnit, number>>;\n allowedUnits?: CssUnit[];\n defaultUnit?: CssUnit;\n}\n\n/**\n * Font picker field schema for Google Fonts selection\n */\nexport interface FontPickerFieldSchema extends PropertyFieldSchema {\n type: \"fontPicker\";\n placeholder?: string;\n}\n\n/**\n * String array field schema for managing lists of text items\n */\nexport interface StringArrayFieldSchema extends PropertyFieldSchema {\n type: \"stringArray\";\n placeholder?: string;\n defaultValue?: string[];\n}\n\n/**\n * Border radius composite field schema for controlling 4 corners with a single field.\n * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight).\n */\nexport interface BorderRadiusFieldSchema extends PropertyFieldSchema {\n type: \"borderRadius\";\n keys: {\n topLeft: string;\n topRight: string;\n bottomLeft: string;\n bottomRight: string;\n };\n defaultValue?: BorderRadiusOptions;\n}\n\n/**\n * Screen picker field schema for selecting a portal screen (navigation, system, or available)\n */\nexport interface ScreenPickerFieldSchema extends PropertyFieldSchema {\n type: \"screenPicker\";\n /** Whether to include system navigation items in the picker */\n includeSystemItems?: boolean;\n}\n\n/**\n * Union of all field schema types\n */\nexport type PropertyField =\n | TextFieldSchema\n | TextareaFieldSchema\n | NumberFieldSchema\n | BooleanFieldSchema\n | SelectFieldSchema<string | number>\n | ColorFieldSchema\n | RangeFieldSchema\n | DataSourceFieldSchema\n | ResourceFieldSchema\n | ImageFieldSchema\n | AlignmentFieldSchema\n | SliderFieldSchema\n | ColorPickerFieldSchema\n | SectionHeaderFieldSchema\n | SeparatorFieldSchema\n | ButtonGroupFieldSchema<string | number>\n | ColorSelectFieldSchema\n | SectionLayoutSelectFieldSchema\n | BackgroundFieldSchema\n | ContentPositionFieldSchema\n | TextSizeSelectFieldSchema\n | CssUnitFieldSchema\n | FontPickerFieldSchema\n | StringArrayFieldSchema\n | BorderRadiusFieldSchema\n | ScreenPickerFieldSchema;\n\n/**\n * Schema for per-item configuration in custom data sources.\n * Widgets can define this to allow users to configure widget-specific\n * settings for each selected item (e.g., title, description, button).\n */\nexport interface ItemConfigSchema {\n /** Fields available for per-item configuration */\n fields: PropertyField[];\n /** Optional description shown at top of item config panel */\n description?: string;\n}\n\n/**\n * Schema for a widget's editable properties\n */\nexport interface WidgetPropertySchema {\n /** Widget type this schema applies to */\n widgetType: WidgetType;\n /** Display name for the widget */\n displayName: string;\n /** Optional tab configuration - if present, tabs are enabled */\n tabsConfig?: TabConfig[];\n /** Editable property fields */\n fields: PropertyField[];\n /** Optional custom validator function */\n validate?: (props: Record<string, unknown>) => string | null;\n /** Props that can be populated from data sources */\n dataSourceTargetProps?: string[];\n /** Optional schema for per-item configurations in custom data sources */\n itemConfigSchema?: ItemConfigSchema;\n}\n\n/**\n * Registry mapping widget types to their property schemas\n */\nexport type PropertySchemaRegistry = Record<WidgetType, WidgetPropertySchema>;\n\n/**\n * Group property fields by their group property.\n *\n * Fields flagged with `advanced: true` are collected into the\n * `CUSTOM_STYLING_GROUP` bucket regardless of their declared `group`,\n * and that bucket is always placed last so it renders at the bottom of\n * the tab. Non-advanced fields keep their author-declared group and\n * their relative insertion order, including fields that explicitly use\n * `CUSTOM_STYLING_GROUP`.\n */\nexport function groupPropertyFields(\n fields: readonly PropertyField[],\n): Record<string, PropertyField[]> {\n const grouped: Record<string, PropertyField[]> = {};\n const advancedFields: PropertyField[] = [];\n\n fields.forEach((field) => {\n if (field.advanced) {\n advancedFields.push(field);\n return;\n }\n const group = field.group || \"General\";\n if (!grouped[group]) {\n grouped[group] = [];\n }\n grouped[group].push(field);\n });\n\n if (advancedFields.length > 0) {\n const customStylingFields = grouped[CUSTOM_STYLING_GROUP] ?? [];\n delete grouped[CUSTOM_STYLING_GROUP];\n grouped[CUSTOM_STYLING_GROUP] = [...customStylingFields, ...advancedFields];\n }\n\n return grouped;\n}\n\n/**\n * Extract current values from widget props based on property fields\n */\nexport function extractPropertyValues(\n widget: Readonly<WidgetSchema>,\n fields: readonly PropertyField[],\n): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n\n fields.forEach((field) => {\n // For borderRadius composite fields, skip the top-level key —\n // it is a schema grouping identifier, not a real widget prop.\n if (field.type === \"borderRadius\") {\n for (const subKey of Object.values(field.keys)) {\n const subValue = widget.props[subKey];\n values[subKey] = subValue !== undefined ? subValue : field.defaultValue;\n }\n return;\n }\n\n // dataSource config is stored at widget.dataSource (top-level),\n // not in widget.props. Surface it under the field key so schema\n // visibility checks (requiresKeyValue) can gate on its presence.\n if (field.type === \"dataSource\") {\n values[field.key] = widget.dataSource;\n return;\n }\n\n const value = widget.props[field.key];\n values[field.key] = value !== undefined ? value : field.defaultValue;\n });\n\n return values;\n}\n\n/**\n * Apply property values to widget props\n */\nexport function applyPropertyValues(\n widget: Readonly<WidgetSchema>,\n values: Readonly<Record<string, unknown>>,\n): WidgetSchema {\n return {\n ...widget,\n props: {\n ...widget.props,\n ...values,\n },\n };\n}\n","import type {\n BorderRadiusFieldSchema,\n ButtonGroupFieldSchema,\n ColorSelectFieldSchema,\n CssUnitFieldSchema,\n TextSizeSelectFieldSchema,\n} from \"./property-schema-types\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontWeightOptions,\n PaddingOptions,\n ButtonSizeOptions,\n GapOptions,\n} from \"../types\";\nimport { Ban } from \"lucide-react\";\n\nexport const getColorField = (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n): ColorSelectFieldSchema => {\n return {\n ...props,\n type: \"colorSelect\",\n };\n};\n\nexport const getBorderRadiusField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderRadiusOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderRadiusOptions> => {\n return {\n // Border radius inherits from the active theme by default. Mark as\n // advanced so widget-level overrides collapse into the \"Custom\n // styling\" disclosure.\n //\n // Note: `groupPropertyFields` ignores `field.group` whenever\n // `field.advanced` is true. If a widget explicitly wants this\n // control to live in its own group, pass `advanced: false`\n // alongside `group: \"...\"` to opt out.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No radius\", value: \"none\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n { label: \"FULL\", value: \"full\" },\n ],\n };\n};\n\nexport const getPaddingField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<PaddingOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<PaddingOptions> => {\n return {\n // Padding follows the theme's global spacing scale by default.\n // Mark as advanced so widget-level overrides collapse into the\n // \"Custom styling\" disclosure. To keep this field in a different\n // group, pass `advanced: false` alongside `group: \"...\"`.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No padding\", value: 0 },\n { label: \"SM\", value: 2 },\n { label: \"MD\", value: 4 },\n { label: \"LG\", value: 6 },\n { label: \"XL\", value: 8 },\n { label: \"FULL\", value: 10 },\n ],\n };\n};\n\nexport const getButtonSizeField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<ButtonSizeOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<ButtonSizeOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"default\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getFontWeightField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<FontWeightOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<FontWeightOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"Normal\", value: \"normal\" },\n { label: \"Medium\", value: \"medium\" },\n { label: \"Semibold\", value: \"semibold\" },\n { label: \"Bold\", value: \"bold\" },\n ],\n };\n};\n\nexport const getFontSizeField = (\n props: Readonly<Omit<TextSizeSelectFieldSchema, \"type\">>,\n): TextSizeSelectFieldSchema => {\n return {\n ...props,\n type: \"textSizeSelect\",\n };\n};\n\nexport const getGapField = (\n props: Readonly<Omit<ButtonGroupFieldSchema<GapOptions>, \"options\" | \"type\">>,\n): ButtonGroupFieldSchema<GapOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No gap\", value: \"none\" },\n { label: \"XS\", value: \"xs\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getHeightField = (\n props: Readonly<\n Omit<\n CssUnitFieldSchema,\n \"type\" | \"minByUnit\" | \"maxByUnit\" | \"stepByUnit\" | \"allowedUnits\"\n >\n >,\n): CssUnitFieldSchema => {\n return {\n ...props,\n type: \"cssUnit\",\n allowedUnits: [\"px\", \"vh\", \"rem\"],\n minByUnit: { px: 10, vh: 1, rem: 1 },\n maxByUnit: { px: 1200, vh: 100, rem: 75 },\n stepByUnit: { px: 10, vh: 1, rem: 1 },\n };\n};\n\nexport const getBorderRadiusCompositeField = (\n props: Readonly<\n Omit<BorderRadiusFieldSchema, \"type\" | \"keys\"> & {\n keys?: BorderRadiusFieldSchema[\"keys\"];\n }\n >,\n): BorderRadiusFieldSchema => {\n return {\n // Per-corner radius controls are theme-derivable in the same way as\n // the simpler `getBorderRadiusField`. Pass `advanced: false`\n // alongside `group: \"...\"` to opt out of Custom Styling.\n advanced: true,\n ...props,\n type: \"borderRadius\",\n keys: props.keys ?? {\n topLeft: \"borderRadiusTL\",\n topRight: \"borderRadiusTR\",\n bottomLeft: \"borderRadiusBL\",\n bottomRight: \"borderRadiusBR\",\n },\n };\n};\n\n/**\n * Gap value mapping - use `as const satisfies` for compile-time validation\n * with literal type preservation.\n */\nexport const gapValues: {\n readonly none: 0;\n readonly xs: 1;\n readonly sm: 2;\n readonly md: 4;\n readonly lg: 6;\n readonly xl: 8;\n} = {\n none: 0,\n xs: 1,\n sm: 2,\n md: 4,\n lg: 6,\n xl: 8,\n} as const satisfies Record<GapOptions, number>;\n\nexport const getBorderWidthField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderWidthOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderWidthOptions> => ({\n // Border width is a styling override of a theme-derivable decision.\n // Pass `advanced: false` alongside `group: \"...\"` to opt out of\n // Custom Styling.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No border\", value: \"none\" },\n { label: \"THIN\", value: \"thin\" },\n { label: \"MD\", value: \"medium\" },\n { label: \"THICK\", value: \"thick\" },\n ],\n});\n\nexport const getBorderColorField: (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n) => ColorSelectFieldSchema = getColorField;\n\n/**\n * Border width class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderWidthClasses: {\n readonly none: \"border-0\";\n readonly thin: \"border\";\n readonly medium: \"border-2\";\n readonly thick: \"border-4\";\n} = {\n none: \"border-0\",\n thin: \"border\",\n medium: \"border-2\",\n thick: \"border-4\",\n} as const satisfies Record<BorderWidthOptions, string>;\n\n/**\n * Border color class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderColorClasses: {\n readonly background: \"border-background\";\n readonly foreground: \"border-foreground\";\n readonly primary: \"border-primary\";\n readonly secondary: \"border-secondary\";\n readonly accent: \"border-accent\";\n readonly border: \"border-border\";\n readonly muted: \"border-muted\";\n readonly destructive: \"border-destructive\";\n readonly transparent: \"border-transparent\";\n} = {\n background: \"border-background\",\n foreground: \"border-foreground\",\n primary: \"border-primary\",\n secondary: \"border-secondary\",\n accent: \"border-accent\",\n border: \"border-border\",\n muted: \"border-muted\",\n destructive: \"border-destructive\",\n transparent: \"border-transparent\",\n} as const satisfies Record<ColorOptions, string>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"registries-BWdQbKof.cjs","names":["Ban"],"sources":["../../core/src/registries/property-schema-types.ts","../../core/src/registries/field-helpers.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport type {\n WidgetType,\n WidgetSchema,\n AlignOptions,\n ColorOptions,\n FontSizeOptions,\n SectionLayoutType,\n StrictOmit,\n BorderRadiusOptions,\n} from \"../types\";\n\n/**\n * Tab configuration for organizing properties\n */\nexport interface TabConfig {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n}\n\n// ============================================================================\n// Property Field Types - Derive from constant for single source of truth\n// ============================================================================\n\n/**\n * Property field type constant - single source of truth for field types.\n * Use PROPERTY_FIELD_TYPES.text instead of \"text\" for type-safe comparisons.\n */\nexport const PROPERTY_FIELD_TYPES = {\n text: \"text\",\n textarea: \"textarea\",\n number: \"number\",\n boolean: \"boolean\",\n select: \"select\",\n color: \"color\",\n range: \"range\",\n dataSource: \"dataSource\",\n resource: \"resource\",\n image: \"image\",\n alignment: \"alignment\",\n slider: \"slider\",\n colorPicker: \"colorPicker\",\n sectionHeader: \"sectionHeader\",\n separator: \"separator\",\n buttonGroup: \"buttonGroup\",\n colorSelect: \"colorSelect\",\n sectionLayoutSelect: \"sectionLayoutSelect\",\n background: \"background\",\n contentPosition: \"contentPosition\",\n textSizeSelect: \"textSizeSelect\",\n cssUnit: \"cssUnit\",\n fontPicker: \"fontPicker\",\n stringArray: \"stringArray\",\n borderRadius: \"borderRadius\",\n screenPicker: \"screenPicker\",\n} as const;\n\n/**\n * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant.\n * @see deriving-typeof-for-object-keys pattern\n */\nexport type PropertyFieldType =\n (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES];\n\n/**\n * Runtime validation for property field types.\n * @param value - The value to check\n * @returns true if value is a valid PropertyFieldType\n */\nexport function isPropertyFieldType(value: string): value is PropertyFieldType {\n return Object.values(PROPERTY_FIELD_TYPES).includes(\n value as PropertyFieldType,\n );\n}\n\n/**\n * Group label for fields that override theme-derived styling.\n * Rendered last within a tab and collapsed by default so the primary\n * configuration surface stays clean.\n */\nexport const CUSTOM_STYLING_GROUP = \"Custom styling\";\n\n/**\n * Base schema for a property field\n */\nexport interface PropertyFieldSchema {\n /** Property key in the widget props */\n key: string;\n /** Display label for the field */\n label: string;\n /** Field type determines the input control */\n type: PropertyFieldType;\n /** Optional description/help text */\n description?: string;\n /** Optional default value */\n defaultValue?: unknown;\n /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */\n tab?: string;\n /** Optional group for organizing fields within a tab */\n group?: string;\n /**\n * When true, this field is treated as an override of a value that can\n * otherwise be inherited from the active theme (e.g. border radius,\n * padding, border width). Advanced fields are automatically bucketed\n * into the `CUSTOM_STYLING_GROUP` at the bottom of their tab and\n * rendered collapsed by default so the default surface area stays\n * minimal.\n */\n advanced?: boolean;\n /**\n * @deprecated Use requiresKeyValue instead\n */\n requiresKeyToBeTrue?: string;\n /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */\n requiresKeyValue?:\n | { key: string; value: unknown }\n | Array<{ key: string; value: unknown }>;\n}\n\n/**\n * Text field schema\n */\nexport interface TextFieldSchema extends PropertyFieldSchema {\n type: \"text\";\n placeholder?: string;\n maxLength?: number;\n /**\n * Optional quick-insert chips rendered below the input. Clicking a chip\n * inserts `{{value}}` at the caret. Used for URL template tokens\n * (e.g. `{{username}}`, `{{replicated_url || /signup}}`) so admins\n * don't have to remember the exact spelling.\n */\n tokenSuggestions?: ReadonlyArray<{\n /** Chip label shown to the admin (e.g. `username`). */\n label: string;\n /** Token body inserted between `{{` and `}}` (e.g. `username || /signup`). */\n value: string;\n }>;\n}\n\n/**\n * Textarea field schema\n */\nexport interface TextareaFieldSchema extends PropertyFieldSchema {\n type: \"textarea\";\n placeholder?: string;\n rows?: number;\n maxLength?: number;\n}\n\n/**\n * Number field schema\n */\nexport interface NumberFieldSchema extends PropertyFieldSchema {\n type: \"number\";\n min?: number;\n max?: number;\n step?: number;\n}\n\n/**\n * Boolean field schema\n */\nexport interface BooleanFieldSchema extends PropertyFieldSchema {\n type: \"boolean\";\n}\n\n/**\n * Select field schema with type-safe option values.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface SelectFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"select\";\n options: Array<{ label: string; value: T }>;\n defaultValue?: T;\n}\n\n/**\n * Color field schema\n */\nexport interface ColorFieldSchema extends PropertyFieldSchema {\n type: \"color\";\n}\n\n/**\n * Range slider field schema\n */\nexport interface RangeFieldSchema extends PropertyFieldSchema {\n type: \"range\";\n min: number;\n max: number;\n step?: number;\n}\n\n/**\n * Data source field schema for configuring widget data sources\n */\nexport interface DataSourceFieldSchema extends PropertyFieldSchema {\n type: \"dataSource\";\n}\n\n/**\n * Resource field schema for selecting a single resource from the selection modal\n */\nexport interface ResourceFieldSchema extends PropertyFieldSchema {\n type: \"resource\";\n /** Optional filter to specific shareable types */\n allowedTypes?: string[];\n}\n\n/**\n * Image field schema for selecting a single asset (image or video) from the\n * image picker. Despite the legacy \"image\" name, this field supports video\n * picking via the `accept` parameter — `VideoWidget`, `ListWidget` Featured\n * Asset, and `NestedWidget` Primary Media all use it for video-or-mixed\n * content.\n */\nexport interface ImageFieldSchema extends PropertyFieldSchema {\n type: \"image\";\n /**\n * Restricts which MIME categories the picker offers. Defaults to \"image\".\n */\n accept?: \"image\" | \"video\" | \"any\";\n}\n\n/**\n * Alignment field schema\n */\nexport interface AlignmentFieldSchema extends PropertyFieldSchema {\n type: \"alignment\";\n options: {\n verticalEnabled: boolean;\n horizontalEnabled: boolean;\n };\n defaultValue?: AlignOptions;\n}\n\n/**\n * Slider field schema with optional unit suffix (e.g., \"rem\", \"px\")\n */\nexport interface SliderFieldSchema extends PropertyFieldSchema {\n type: \"slider\";\n min: number;\n max: number;\n step?: number;\n unit?: string;\n}\n\n/**\n * Color picker field schema with optional swatches\n */\nexport interface ColorPickerFieldSchema extends PropertyFieldSchema {\n type: \"colorPicker\";\n swatches?: string[];\n}\n\n/**\n * Section header field schema for visual grouping\n */\nexport interface SectionHeaderFieldSchema extends PropertyFieldSchema {\n type: \"sectionHeader\";\n subtitle?: string;\n}\n\n/**\n * Separator field schema for visual separation\n */\nexport interface SeparatorFieldSchema extends PropertyFieldSchema {\n type: \"separator\";\n}\n\n/**\n * Button group field schema.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface ButtonGroupFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"buttonGroup\";\n options: Array<{\n label?: string;\n ariaLabel?: string;\n icon?: LucideIcon;\n value: T;\n }>;\n defaultValue?: T;\n}\n\n/**\n * Color select field schema\n */\nexport interface ColorSelectFieldSchema extends PropertyFieldSchema {\n type: \"colorSelect\";\n defaultValue?: ColorOptions;\n excludeColors?: ColorOptions[];\n}\n\n/**\n * Section layout select field schema for visual masonry layout selector\n */\nexport interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema {\n type: \"sectionLayoutSelect\";\n defaultValue?: SectionLayoutType;\n}\n\n/**\n * Background field combines resource selection and color properties.\n * Uses StrictOmit to exclude conflicting \"type\" discriminant from parents.\n */\nexport interface BackgroundFieldSchema\n extends\n StrictOmit<ResourceFieldSchema, \"type\">,\n StrictOmit<ColorFieldSchema, \"type\"> {\n type: \"background\";\n}\n\n/**\n * Content position field schema for 3x3 grid position picker\n */\nexport interface ContentPositionFieldSchema extends PropertyFieldSchema {\n type: \"contentPosition\";\n defaultValue?: string;\n}\n\n/**\n * Text size select field schema for visual font size selector\n */\nexport interface TextSizeSelectFieldSchema extends PropertyFieldSchema {\n type: \"textSizeSelect\";\n defaultValue?: FontSizeOptions;\n}\n\n/**\n * CSS unit type for height/width fields\n */\nexport type CssUnit = \"px\" | \"rem\" | \"vh\" | \"%\";\n\n/**\n * CSS unit field schema for numeric values with selectable units (px, rem, vh, %)\n */\nexport interface CssUnitFieldSchema extends PropertyFieldSchema {\n type: \"cssUnit\";\n minByUnit?: Partial<Record<CssUnit, number>>;\n maxByUnit?: Partial<Record<CssUnit, number>>;\n stepByUnit?: Partial<Record<CssUnit, number>>;\n allowedUnits?: CssUnit[];\n defaultUnit?: CssUnit;\n}\n\n/**\n * Font picker field schema for Google Fonts selection\n */\nexport interface FontPickerFieldSchema extends PropertyFieldSchema {\n type: \"fontPicker\";\n placeholder?: string;\n}\n\n/**\n * String array field schema for managing lists of text items\n */\nexport interface StringArrayFieldSchema extends PropertyFieldSchema {\n type: \"stringArray\";\n placeholder?: string;\n defaultValue?: string[];\n}\n\n/**\n * Border radius composite field schema for controlling 4 corners with a single field.\n * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight).\n */\nexport interface BorderRadiusFieldSchema extends PropertyFieldSchema {\n type: \"borderRadius\";\n keys: {\n topLeft: string;\n topRight: string;\n bottomLeft: string;\n bottomRight: string;\n };\n defaultValue?: BorderRadiusOptions;\n}\n\n/**\n * Screen picker field schema for selecting a portal screen (navigation, system, or available)\n */\nexport interface ScreenPickerFieldSchema extends PropertyFieldSchema {\n type: \"screenPicker\";\n /** Whether to include system navigation items in the picker */\n includeSystemItems?: boolean;\n}\n\n/**\n * Union of all field schema types\n */\nexport type PropertyField =\n | TextFieldSchema\n | TextareaFieldSchema\n | NumberFieldSchema\n | BooleanFieldSchema\n | SelectFieldSchema<string | number>\n | ColorFieldSchema\n | RangeFieldSchema\n | DataSourceFieldSchema\n | ResourceFieldSchema\n | ImageFieldSchema\n | AlignmentFieldSchema\n | SliderFieldSchema\n | ColorPickerFieldSchema\n | SectionHeaderFieldSchema\n | SeparatorFieldSchema\n | ButtonGroupFieldSchema<string | number>\n | ColorSelectFieldSchema\n | SectionLayoutSelectFieldSchema\n | BackgroundFieldSchema\n | ContentPositionFieldSchema\n | TextSizeSelectFieldSchema\n | CssUnitFieldSchema\n | FontPickerFieldSchema\n | StringArrayFieldSchema\n | BorderRadiusFieldSchema\n | ScreenPickerFieldSchema;\n\n/**\n * Schema for per-item configuration in custom data sources.\n * Widgets can define this to allow users to configure widget-specific\n * settings for each selected item (e.g., title, description, button).\n */\nexport interface ItemConfigSchema {\n /** Fields available for per-item configuration */\n fields: PropertyField[];\n /** Optional description shown at top of item config panel */\n description?: string;\n}\n\n/**\n * Schema for a widget's editable properties\n */\nexport interface WidgetPropertySchema {\n /** Widget type this schema applies to */\n widgetType: WidgetType;\n /** Display name for the widget */\n displayName: string;\n /** Optional tab configuration - if present, tabs are enabled */\n tabsConfig?: TabConfig[];\n /** Editable property fields */\n fields: PropertyField[];\n /** Optional custom validator function */\n validate?: (props: Record<string, unknown>) => string | null;\n /** Props that can be populated from data sources */\n dataSourceTargetProps?: string[];\n /** Optional schema for per-item configurations in custom data sources */\n itemConfigSchema?: ItemConfigSchema;\n}\n\n/**\n * Registry mapping widget types to their property schemas\n */\nexport type PropertySchemaRegistry = Record<WidgetType, WidgetPropertySchema>;\n\n/**\n * Group property fields by their group property.\n *\n * Fields flagged with `advanced: true` are collected into the\n * `CUSTOM_STYLING_GROUP` bucket regardless of their declared `group`,\n * and that bucket is always placed last so it renders at the bottom of\n * the tab. Non-advanced fields keep their author-declared group and\n * their relative insertion order, including fields that explicitly use\n * `CUSTOM_STYLING_GROUP`.\n */\nexport function groupPropertyFields(\n fields: readonly PropertyField[],\n): Record<string, PropertyField[]> {\n const grouped: Record<string, PropertyField[]> = {};\n const advancedFields: PropertyField[] = [];\n\n fields.forEach((field) => {\n if (field.advanced) {\n advancedFields.push(field);\n return;\n }\n const group = field.group || \"General\";\n if (!grouped[group]) {\n grouped[group] = [];\n }\n grouped[group].push(field);\n });\n\n if (advancedFields.length > 0) {\n const customStylingFields = grouped[CUSTOM_STYLING_GROUP] ?? [];\n delete grouped[CUSTOM_STYLING_GROUP];\n grouped[CUSTOM_STYLING_GROUP] = [...customStylingFields, ...advancedFields];\n }\n\n return grouped;\n}\n\n/**\n * Extract current values from widget props based on property fields\n */\nexport function extractPropertyValues(\n widget: Readonly<WidgetSchema>,\n fields: readonly PropertyField[],\n): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n\n fields.forEach((field) => {\n // For borderRadius composite fields, skip the top-level key —\n // it is a schema grouping identifier, not a real widget prop.\n if (field.type === \"borderRadius\") {\n for (const subKey of Object.values(field.keys)) {\n const subValue = widget.props[subKey];\n values[subKey] = subValue !== undefined ? subValue : field.defaultValue;\n }\n return;\n }\n\n // dataSource config is stored at widget.dataSource (top-level),\n // not in widget.props. Surface it under the field key so schema\n // visibility checks (requiresKeyValue) can gate on its presence.\n if (field.type === \"dataSource\") {\n values[field.key] = widget.dataSource;\n return;\n }\n\n const value = widget.props[field.key];\n values[field.key] = value !== undefined ? value : field.defaultValue;\n });\n\n return values;\n}\n\n/**\n * Apply property values to widget props\n */\nexport function applyPropertyValues(\n widget: Readonly<WidgetSchema>,\n values: Readonly<Record<string, unknown>>,\n): WidgetSchema {\n return {\n ...widget,\n props: {\n ...widget.props,\n ...values,\n },\n };\n}\n","import type {\n BorderRadiusFieldSchema,\n ButtonGroupFieldSchema,\n ColorSelectFieldSchema,\n CssUnitFieldSchema,\n TextSizeSelectFieldSchema,\n} from \"./property-schema-types\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontWeightOptions,\n PaddingOptions,\n ButtonSizeOptions,\n GapOptions,\n} from \"../types\";\nimport { Ban } from \"lucide-react\";\n\nexport const getColorField = (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n): ColorSelectFieldSchema => {\n return {\n ...props,\n type: \"colorSelect\",\n };\n};\n\nexport const getBorderRadiusField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderRadiusOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderRadiusOptions> => {\n return {\n // Border radius inherits from the active theme by default. Mark as\n // advanced so widget-level overrides collapse into the \"Custom\n // styling\" disclosure.\n //\n // Note: `groupPropertyFields` ignores `field.group` whenever\n // `field.advanced` is true. If a widget explicitly wants this\n // control to live in its own group, pass `advanced: false`\n // alongside `group: \"...\"` to opt out.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No radius\", value: \"none\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n { label: \"FULL\", value: \"full\" },\n ],\n };\n};\n\nexport const getPaddingField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<PaddingOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<PaddingOptions> => {\n return {\n // Padding follows the theme's global spacing scale by default.\n // Mark as advanced so widget-level overrides collapse into the\n // \"Custom styling\" disclosure. To keep this field in a different\n // group, pass `advanced: false` alongside `group: \"...\"`.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No padding\", value: 0 },\n { label: \"SM\", value: 2 },\n { label: \"MD\", value: 4 },\n { label: \"LG\", value: 6 },\n { label: \"XL\", value: 8 },\n { label: \"FULL\", value: 10 },\n ],\n };\n};\n\nexport const getButtonSizeField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<ButtonSizeOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<ButtonSizeOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"default\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getFontWeightField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<FontWeightOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<FontWeightOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"Normal\", value: \"normal\" },\n { label: \"Medium\", value: \"medium\" },\n { label: \"Semibold\", value: \"semibold\" },\n { label: \"Bold\", value: \"bold\" },\n ],\n };\n};\n\nexport const getFontSizeField = (\n props: Readonly<Omit<TextSizeSelectFieldSchema, \"type\">>,\n): TextSizeSelectFieldSchema => {\n return {\n ...props,\n type: \"textSizeSelect\",\n };\n};\n\nexport const getGapField = (\n props: Readonly<Omit<ButtonGroupFieldSchema<GapOptions>, \"options\" | \"type\">>,\n): ButtonGroupFieldSchema<GapOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No gap\", value: \"none\" },\n { label: \"XS\", value: \"xs\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getHeightField = (\n props: Readonly<\n Omit<\n CssUnitFieldSchema,\n \"type\" | \"minByUnit\" | \"maxByUnit\" | \"stepByUnit\" | \"allowedUnits\"\n >\n >,\n): CssUnitFieldSchema => {\n return {\n ...props,\n type: \"cssUnit\",\n allowedUnits: [\"px\", \"vh\", \"rem\"],\n minByUnit: { px: 10, vh: 1, rem: 1 },\n maxByUnit: { px: 1200, vh: 100, rem: 75 },\n stepByUnit: { px: 10, vh: 1, rem: 1 },\n };\n};\n\nexport const getBorderRadiusCompositeField = (\n props: Readonly<\n Omit<BorderRadiusFieldSchema, \"type\" | \"keys\"> & {\n keys?: BorderRadiusFieldSchema[\"keys\"];\n }\n >,\n): BorderRadiusFieldSchema => {\n return {\n // Per-corner radius controls are theme-derivable in the same way as\n // the simpler `getBorderRadiusField`. Pass `advanced: false`\n // alongside `group: \"...\"` to opt out of Custom Styling.\n advanced: true,\n ...props,\n type: \"borderRadius\",\n keys: props.keys ?? {\n topLeft: \"borderRadiusTL\",\n topRight: \"borderRadiusTR\",\n bottomLeft: \"borderRadiusBL\",\n bottomRight: \"borderRadiusBR\",\n },\n };\n};\n\n/**\n * Gap value mapping - use `as const satisfies` for compile-time validation\n * with literal type preservation.\n */\nexport const gapValues: {\n readonly none: 0;\n readonly xs: 1;\n readonly sm: 2;\n readonly md: 4;\n readonly lg: 6;\n readonly xl: 8;\n} = {\n none: 0,\n xs: 1,\n sm: 2,\n md: 4,\n lg: 6,\n xl: 8,\n} as const satisfies Record<GapOptions, number>;\n\nexport const getBorderWidthField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderWidthOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderWidthOptions> => ({\n // Border width is a styling override of a theme-derivable decision.\n // Pass `advanced: false` alongside `group: \"...\"` to opt out of\n // Custom Styling.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No border\", value: \"none\" },\n { label: \"THIN\", value: \"thin\" },\n { label: \"MD\", value: \"medium\" },\n { label: \"THICK\", value: \"thick\" },\n ],\n});\n\nexport const getBorderColorField: (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n) => ColorSelectFieldSchema = getColorField;\n\n/**\n * Border width class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderWidthClasses: {\n readonly none: \"border-0\";\n readonly thin: \"border\";\n readonly medium: \"border-2\";\n readonly thick: \"border-4\";\n} = {\n none: \"border-0\",\n thin: \"border\",\n medium: \"border-2\",\n thick: \"border-4\",\n} as const satisfies Record<BorderWidthOptions, string>;\n\n/**\n * Border color class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderColorClasses: {\n readonly background: \"border-background\";\n readonly foreground: \"border-foreground\";\n readonly primary: \"border-primary\";\n readonly secondary: \"border-secondary\";\n readonly accent: \"border-accent\";\n readonly border: \"border-border\";\n readonly muted: \"border-muted\";\n readonly destructive: \"border-destructive\";\n readonly transparent: \"border-transparent\";\n} = {\n background: \"border-background\",\n foreground: \"border-foreground\",\n primary: \"border-primary\",\n secondary: \"border-secondary\",\n accent: \"border-accent\",\n border: \"border-border\",\n muted: \"border-muted\",\n destructive: \"border-destructive\",\n transparent: \"border-transparent\",\n} as const satisfies Record<ColorOptions, string>;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"registries-DT36l-bR.mjs","names":[],"sources":["../../core/src/registries/property-schema-types.ts","../../core/src/registries/field-helpers.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport type {\n WidgetType,\n WidgetSchema,\n AlignOptions,\n ColorOptions,\n FontSizeOptions,\n SectionLayoutType,\n StrictOmit,\n BorderRadiusOptions,\n} from \"../types\";\n\n/**\n * Tab configuration for organizing properties\n */\nexport interface TabConfig {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n}\n\n// ============================================================================\n// Property Field Types - Derive from constant for single source of truth\n// ============================================================================\n\n/**\n * Property field type constant - single source of truth for field types.\n * Use PROPERTY_FIELD_TYPES.text instead of \"text\" for type-safe comparisons.\n */\nexport const PROPERTY_FIELD_TYPES = {\n text: \"text\",\n textarea: \"textarea\",\n number: \"number\",\n boolean: \"boolean\",\n select: \"select\",\n color: \"color\",\n range: \"range\",\n dataSource: \"dataSource\",\n resource: \"resource\",\n image: \"image\",\n alignment: \"alignment\",\n slider: \"slider\",\n colorPicker: \"colorPicker\",\n sectionHeader: \"sectionHeader\",\n separator: \"separator\",\n buttonGroup: \"buttonGroup\",\n colorSelect: \"colorSelect\",\n sectionLayoutSelect: \"sectionLayoutSelect\",\n background: \"background\",\n contentPosition: \"contentPosition\",\n textSizeSelect: \"textSizeSelect\",\n cssUnit: \"cssUnit\",\n fontPicker: \"fontPicker\",\n stringArray: \"stringArray\",\n borderRadius: \"borderRadius\",\n screenPicker: \"screenPicker\",\n} as const;\n\n/**\n * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant.\n * @see deriving-typeof-for-object-keys pattern\n */\nexport type PropertyFieldType =\n (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES];\n\n/**\n * Runtime validation for property field types.\n * @param value - The value to check\n * @returns true if value is a valid PropertyFieldType\n */\nexport function isPropertyFieldType(value: string): value is PropertyFieldType {\n return Object.values(PROPERTY_FIELD_TYPES).includes(\n value as PropertyFieldType,\n );\n}\n\n/**\n * Group label for fields that override theme-derived styling.\n * Rendered last within a tab and collapsed by default so the primary\n * configuration surface stays clean.\n */\nexport const CUSTOM_STYLING_GROUP = \"Custom styling\";\n\n/**\n * Base schema for a property field\n */\nexport interface PropertyFieldSchema {\n /** Property key in the widget props */\n key: string;\n /** Display label for the field */\n label: string;\n /** Field type determines the input control */\n type: PropertyFieldType;\n /** Optional description/help text */\n description?: string;\n /** Optional default value */\n defaultValue?: unknown;\n /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */\n tab?: string;\n /** Optional group for organizing fields within a tab */\n group?: string;\n /**\n * When true, this field is treated as an override of a value that can\n * otherwise be inherited from the active theme (e.g. border radius,\n * padding, border width). Advanced fields are automatically bucketed\n * into the `CUSTOM_STYLING_GROUP` at the bottom of their tab and\n * rendered collapsed by default so the default surface area stays\n * minimal.\n */\n advanced?: boolean;\n /**\n * @deprecated Use requiresKeyValue instead\n */\n requiresKeyToBeTrue?: string;\n /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */\n requiresKeyValue?:\n | { key: string; value: unknown }\n | Array<{ key: string; value: unknown }>;\n}\n\n/**\n * Text field schema\n */\nexport interface TextFieldSchema extends PropertyFieldSchema {\n type: \"text\";\n placeholder?: string;\n maxLength?: number;\n /**\n * Optional quick-insert chips rendered below the input. Clicking a chip\n * inserts `{{value}}` at the caret. Used for URL template tokens\n * (e.g. `{{username}}`, `{{replicated_url || /signup}}`) so admins\n * don't have to remember the exact spelling.\n */\n tokenSuggestions?: ReadonlyArray<{\n /** Chip label shown to the admin (e.g. `username`). */\n label: string;\n /** Token body inserted between `{{` and `}}` (e.g. `username || /signup`). */\n value: string;\n }>;\n}\n\n/**\n * Textarea field schema\n */\nexport interface TextareaFieldSchema extends PropertyFieldSchema {\n type: \"textarea\";\n placeholder?: string;\n rows?: number;\n maxLength?: number;\n}\n\n/**\n * Number field schema\n */\nexport interface NumberFieldSchema extends PropertyFieldSchema {\n type: \"number\";\n min?: number;\n max?: number;\n step?: number;\n}\n\n/**\n * Boolean field schema\n */\nexport interface BooleanFieldSchema extends PropertyFieldSchema {\n type: \"boolean\";\n}\n\n/**\n * Select field schema with type-safe option values.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface SelectFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"select\";\n options: Array<{ label: string; value: T }>;\n defaultValue?: T;\n}\n\n/**\n * Color field schema\n */\nexport interface ColorFieldSchema extends PropertyFieldSchema {\n type: \"color\";\n}\n\n/**\n * Range slider field schema\n */\nexport interface RangeFieldSchema extends PropertyFieldSchema {\n type: \"range\";\n min: number;\n max: number;\n step?: number;\n}\n\n/**\n * Data source field schema for configuring widget data sources\n */\nexport interface DataSourceFieldSchema extends PropertyFieldSchema {\n type: \"dataSource\";\n}\n\n/**\n * Resource field schema for selecting a single resource from the selection modal\n */\nexport interface ResourceFieldSchema extends PropertyFieldSchema {\n type: \"resource\";\n /** Optional filter to specific shareable types */\n allowedTypes?: string[];\n}\n\n/**\n * Image field schema for selecting a single image from the image picker\n */\nexport interface ImageFieldSchema extends PropertyFieldSchema {\n type: \"image\";\n}\n\n/**\n * Alignment field schema\n */\nexport interface AlignmentFieldSchema extends PropertyFieldSchema {\n type: \"alignment\";\n options: {\n verticalEnabled: boolean;\n horizontalEnabled: boolean;\n };\n defaultValue?: AlignOptions;\n}\n\n/**\n * Slider field schema with optional unit suffix (e.g., \"rem\", \"px\")\n */\nexport interface SliderFieldSchema extends PropertyFieldSchema {\n type: \"slider\";\n min: number;\n max: number;\n step?: number;\n unit?: string;\n}\n\n/**\n * Color picker field schema with optional swatches\n */\nexport interface ColorPickerFieldSchema extends PropertyFieldSchema {\n type: \"colorPicker\";\n swatches?: string[];\n}\n\n/**\n * Section header field schema for visual grouping\n */\nexport interface SectionHeaderFieldSchema extends PropertyFieldSchema {\n type: \"sectionHeader\";\n subtitle?: string;\n}\n\n/**\n * Separator field schema for visual separation\n */\nexport interface SeparatorFieldSchema extends PropertyFieldSchema {\n type: \"separator\";\n}\n\n/**\n * Button group field schema.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface ButtonGroupFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"buttonGroup\";\n options: Array<{\n label?: string;\n ariaLabel?: string;\n icon?: LucideIcon;\n value: T;\n }>;\n defaultValue?: T;\n}\n\n/**\n * Color select field schema\n */\nexport interface ColorSelectFieldSchema extends PropertyFieldSchema {\n type: \"colorSelect\";\n defaultValue?: ColorOptions;\n excludeColors?: ColorOptions[];\n}\n\n/**\n * Section layout select field schema for visual masonry layout selector\n */\nexport interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema {\n type: \"sectionLayoutSelect\";\n defaultValue?: SectionLayoutType;\n}\n\n/**\n * Background field combines resource selection and color properties.\n * Uses StrictOmit to exclude conflicting \"type\" discriminant from parents.\n */\nexport interface BackgroundFieldSchema\n extends\n StrictOmit<ResourceFieldSchema, \"type\">,\n StrictOmit<ColorFieldSchema, \"type\"> {\n type: \"background\";\n}\n\n/**\n * Content position field schema for 3x3 grid position picker\n */\nexport interface ContentPositionFieldSchema extends PropertyFieldSchema {\n type: \"contentPosition\";\n defaultValue?: string;\n}\n\n/**\n * Text size select field schema for visual font size selector\n */\nexport interface TextSizeSelectFieldSchema extends PropertyFieldSchema {\n type: \"textSizeSelect\";\n defaultValue?: FontSizeOptions;\n}\n\n/**\n * CSS unit type for height/width fields\n */\nexport type CssUnit = \"px\" | \"rem\" | \"vh\" | \"%\";\n\n/**\n * CSS unit field schema for numeric values with selectable units (px, rem, vh, %)\n */\nexport interface CssUnitFieldSchema extends PropertyFieldSchema {\n type: \"cssUnit\";\n minByUnit?: Partial<Record<CssUnit, number>>;\n maxByUnit?: Partial<Record<CssUnit, number>>;\n stepByUnit?: Partial<Record<CssUnit, number>>;\n allowedUnits?: CssUnit[];\n defaultUnit?: CssUnit;\n}\n\n/**\n * Font picker field schema for Google Fonts selection\n */\nexport interface FontPickerFieldSchema extends PropertyFieldSchema {\n type: \"fontPicker\";\n placeholder?: string;\n}\n\n/**\n * String array field schema for managing lists of text items\n */\nexport interface StringArrayFieldSchema extends PropertyFieldSchema {\n type: \"stringArray\";\n placeholder?: string;\n defaultValue?: string[];\n}\n\n/**\n * Border radius composite field schema for controlling 4 corners with a single field.\n * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight).\n */\nexport interface BorderRadiusFieldSchema extends PropertyFieldSchema {\n type: \"borderRadius\";\n keys: {\n topLeft: string;\n topRight: string;\n bottomLeft: string;\n bottomRight: string;\n };\n defaultValue?: BorderRadiusOptions;\n}\n\n/**\n * Screen picker field schema for selecting a portal screen (navigation, system, or available)\n */\nexport interface ScreenPickerFieldSchema extends PropertyFieldSchema {\n type: \"screenPicker\";\n /** Whether to include system navigation items in the picker */\n includeSystemItems?: boolean;\n}\n\n/**\n * Union of all field schema types\n */\nexport type PropertyField =\n | TextFieldSchema\n | TextareaFieldSchema\n | NumberFieldSchema\n | BooleanFieldSchema\n | SelectFieldSchema<string | number>\n | ColorFieldSchema\n | RangeFieldSchema\n | DataSourceFieldSchema\n | ResourceFieldSchema\n | ImageFieldSchema\n | AlignmentFieldSchema\n | SliderFieldSchema\n | ColorPickerFieldSchema\n | SectionHeaderFieldSchema\n | SeparatorFieldSchema\n | ButtonGroupFieldSchema<string | number>\n | ColorSelectFieldSchema\n | SectionLayoutSelectFieldSchema\n | BackgroundFieldSchema\n | ContentPositionFieldSchema\n | TextSizeSelectFieldSchema\n | CssUnitFieldSchema\n | FontPickerFieldSchema\n | StringArrayFieldSchema\n | BorderRadiusFieldSchema\n | ScreenPickerFieldSchema;\n\n/**\n * Schema for per-item configuration in custom data sources.\n * Widgets can define this to allow users to configure widget-specific\n * settings for each selected item (e.g., title, description, button).\n */\nexport interface ItemConfigSchema {\n /** Fields available for per-item configuration */\n fields: PropertyField[];\n /** Optional description shown at top of item config panel */\n description?: string;\n}\n\n/**\n * Schema for a widget's editable properties\n */\nexport interface WidgetPropertySchema {\n /** Widget type this schema applies to */\n widgetType: WidgetType;\n /** Display name for the widget */\n displayName: string;\n /** Optional tab configuration - if present, tabs are enabled */\n tabsConfig?: TabConfig[];\n /** Editable property fields */\n fields: PropertyField[];\n /** Optional custom validator function */\n validate?: (props: Record<string, unknown>) => string | null;\n /** Props that can be populated from data sources */\n dataSourceTargetProps?: string[];\n /** Optional schema for per-item configurations in custom data sources */\n itemConfigSchema?: ItemConfigSchema;\n}\n\n/**\n * Registry mapping widget types to their property schemas\n */\nexport type PropertySchemaRegistry = Record<WidgetType, WidgetPropertySchema>;\n\n/**\n * Group property fields by their group property.\n *\n * Fields flagged with `advanced: true` are collected into the\n * `CUSTOM_STYLING_GROUP` bucket regardless of their declared `group`,\n * and that bucket is always placed last so it renders at the bottom of\n * the tab. Non-advanced fields keep their author-declared group and\n * their relative insertion order, including fields that explicitly use\n * `CUSTOM_STYLING_GROUP`.\n */\nexport function groupPropertyFields(\n fields: readonly PropertyField[],\n): Record<string, PropertyField[]> {\n const grouped: Record<string, PropertyField[]> = {};\n const advancedFields: PropertyField[] = [];\n\n fields.forEach((field) => {\n if (field.advanced) {\n advancedFields.push(field);\n return;\n }\n const group = field.group || \"General\";\n if (!grouped[group]) {\n grouped[group] = [];\n }\n grouped[group].push(field);\n });\n\n if (advancedFields.length > 0) {\n const customStylingFields = grouped[CUSTOM_STYLING_GROUP] ?? [];\n delete grouped[CUSTOM_STYLING_GROUP];\n grouped[CUSTOM_STYLING_GROUP] = [...customStylingFields, ...advancedFields];\n }\n\n return grouped;\n}\n\n/**\n * Extract current values from widget props based on property fields\n */\nexport function extractPropertyValues(\n widget: Readonly<WidgetSchema>,\n fields: readonly PropertyField[],\n): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n\n fields.forEach((field) => {\n // For borderRadius composite fields, skip the top-level key —\n // it is a schema grouping identifier, not a real widget prop.\n if (field.type === \"borderRadius\") {\n for (const subKey of Object.values(field.keys)) {\n const subValue = widget.props[subKey];\n values[subKey] = subValue !== undefined ? subValue : field.defaultValue;\n }\n return;\n }\n\n // dataSource config is stored at widget.dataSource (top-level),\n // not in widget.props. Surface it under the field key so schema\n // visibility checks (requiresKeyValue) can gate on its presence.\n if (field.type === \"dataSource\") {\n values[field.key] = widget.dataSource;\n return;\n }\n\n const value = widget.props[field.key];\n values[field.key] = value !== undefined ? value : field.defaultValue;\n });\n\n return values;\n}\n\n/**\n * Apply property values to widget props\n */\nexport function applyPropertyValues(\n widget: Readonly<WidgetSchema>,\n values: Readonly<Record<string, unknown>>,\n): WidgetSchema {\n return {\n ...widget,\n props: {\n ...widget.props,\n ...values,\n },\n };\n}\n","import type {\n BorderRadiusFieldSchema,\n ButtonGroupFieldSchema,\n ColorSelectFieldSchema,\n CssUnitFieldSchema,\n TextSizeSelectFieldSchema,\n} from \"./property-schema-types\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontWeightOptions,\n PaddingOptions,\n ButtonSizeOptions,\n GapOptions,\n} from \"../types\";\nimport { Ban } from \"lucide-react\";\n\nexport const getColorField = (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n): ColorSelectFieldSchema => {\n return {\n ...props,\n type: \"colorSelect\",\n };\n};\n\nexport const getBorderRadiusField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderRadiusOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderRadiusOptions> => {\n return {\n // Border radius inherits from the active theme by default. Mark as\n // advanced so widget-level overrides collapse into the \"Custom\n // styling\" disclosure.\n //\n // Note: `groupPropertyFields` ignores `field.group` whenever\n // `field.advanced` is true. If a widget explicitly wants this\n // control to live in its own group, pass `advanced: false`\n // alongside `group: \"...\"` to opt out.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No radius\", value: \"none\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n { label: \"FULL\", value: \"full\" },\n ],\n };\n};\n\nexport const getPaddingField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<PaddingOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<PaddingOptions> => {\n return {\n // Padding follows the theme's global spacing scale by default.\n // Mark as advanced so widget-level overrides collapse into the\n // \"Custom styling\" disclosure. To keep this field in a different\n // group, pass `advanced: false` alongside `group: \"...\"`.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No padding\", value: 0 },\n { label: \"SM\", value: 2 },\n { label: \"MD\", value: 4 },\n { label: \"LG\", value: 6 },\n { label: \"XL\", value: 8 },\n { label: \"FULL\", value: 10 },\n ],\n };\n};\n\nexport const getButtonSizeField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<ButtonSizeOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<ButtonSizeOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"default\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getFontWeightField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<FontWeightOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<FontWeightOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"Normal\", value: \"normal\" },\n { label: \"Medium\", value: \"medium\" },\n { label: \"Semibold\", value: \"semibold\" },\n { label: \"Bold\", value: \"bold\" },\n ],\n };\n};\n\nexport const getFontSizeField = (\n props: Readonly<Omit<TextSizeSelectFieldSchema, \"type\">>,\n): TextSizeSelectFieldSchema => {\n return {\n ...props,\n type: \"textSizeSelect\",\n };\n};\n\nexport const getGapField = (\n props: Readonly<Omit<ButtonGroupFieldSchema<GapOptions>, \"options\" | \"type\">>,\n): ButtonGroupFieldSchema<GapOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No gap\", value: \"none\" },\n { label: \"XS\", value: \"xs\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getHeightField = (\n props: Readonly<\n Omit<\n CssUnitFieldSchema,\n \"type\" | \"minByUnit\" | \"maxByUnit\" | \"stepByUnit\" | \"allowedUnits\"\n >\n >,\n): CssUnitFieldSchema => {\n return {\n ...props,\n type: \"cssUnit\",\n allowedUnits: [\"px\", \"vh\", \"rem\"],\n minByUnit: { px: 10, vh: 1, rem: 1 },\n maxByUnit: { px: 1200, vh: 100, rem: 75 },\n stepByUnit: { px: 10, vh: 1, rem: 1 },\n };\n};\n\nexport const getBorderRadiusCompositeField = (\n props: Readonly<\n Omit<BorderRadiusFieldSchema, \"type\" | \"keys\"> & {\n keys?: BorderRadiusFieldSchema[\"keys\"];\n }\n >,\n): BorderRadiusFieldSchema => {\n return {\n // Per-corner radius controls are theme-derivable in the same way as\n // the simpler `getBorderRadiusField`. Pass `advanced: false`\n // alongside `group: \"...\"` to opt out of Custom Styling.\n advanced: true,\n ...props,\n type: \"borderRadius\",\n keys: props.keys ?? {\n topLeft: \"borderRadiusTL\",\n topRight: \"borderRadiusTR\",\n bottomLeft: \"borderRadiusBL\",\n bottomRight: \"borderRadiusBR\",\n },\n };\n};\n\n/**\n * Gap value mapping - use `as const satisfies` for compile-time validation\n * with literal type preservation.\n */\nexport const gapValues: {\n readonly none: 0;\n readonly xs: 1;\n readonly sm: 2;\n readonly md: 4;\n readonly lg: 6;\n readonly xl: 8;\n} = {\n none: 0,\n xs: 1,\n sm: 2,\n md: 4,\n lg: 6,\n xl: 8,\n} as const satisfies Record<GapOptions, number>;\n\nexport const getBorderWidthField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderWidthOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderWidthOptions> => ({\n // Border width is a styling override of a theme-derivable decision.\n // Pass `advanced: false` alongside `group: \"...\"` to opt out of\n // Custom Styling.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No border\", value: \"none\" },\n { label: \"THIN\", value: \"thin\" },\n { label: \"MD\", value: \"medium\" },\n { label: \"THICK\", value: \"thick\" },\n ],\n});\n\nexport const getBorderColorField: (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n) => ColorSelectFieldSchema = getColorField;\n\n/**\n * Border width class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderWidthClasses: {\n readonly none: \"border-0\";\n readonly thin: \"border\";\n readonly medium: \"border-2\";\n readonly thick: \"border-4\";\n} = {\n none: \"border-0\",\n thin: \"border\",\n medium: \"border-2\",\n thick: \"border-4\",\n} as const satisfies Record<BorderWidthOptions, string>;\n\n/**\n * Border color class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderColorClasses: {\n readonly background: \"border-background\";\n readonly foreground: \"border-foreground\";\n readonly primary: \"border-primary\";\n readonly secondary: \"border-secondary\";\n readonly accent: \"border-accent\";\n readonly border: \"border-border\";\n readonly muted: \"border-muted\";\n readonly destructive: \"border-destructive\";\n readonly transparent: \"border-transparent\";\n} = {\n background: \"border-background\",\n foreground: \"border-foreground\",\n primary: \"border-primary\",\n secondary: \"border-secondary\",\n accent: \"border-accent\",\n border: \"border-border\",\n muted: \"border-muted\",\n destructive: \"border-destructive\",\n transparent: \"border-transparent\",\n} as const satisfies Record<ColorOptions, string>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"registries-DT36l-bR.mjs","names":[],"sources":["../../core/src/registries/property-schema-types.ts","../../core/src/registries/field-helpers.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport type {\n WidgetType,\n WidgetSchema,\n AlignOptions,\n ColorOptions,\n FontSizeOptions,\n SectionLayoutType,\n StrictOmit,\n BorderRadiusOptions,\n} from \"../types\";\n\n/**\n * Tab configuration for organizing properties\n */\nexport interface TabConfig {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n}\n\n// ============================================================================\n// Property Field Types - Derive from constant for single source of truth\n// ============================================================================\n\n/**\n * Property field type constant - single source of truth for field types.\n * Use PROPERTY_FIELD_TYPES.text instead of \"text\" for type-safe comparisons.\n */\nexport const PROPERTY_FIELD_TYPES = {\n text: \"text\",\n textarea: \"textarea\",\n number: \"number\",\n boolean: \"boolean\",\n select: \"select\",\n color: \"color\",\n range: \"range\",\n dataSource: \"dataSource\",\n resource: \"resource\",\n image: \"image\",\n alignment: \"alignment\",\n slider: \"slider\",\n colorPicker: \"colorPicker\",\n sectionHeader: \"sectionHeader\",\n separator: \"separator\",\n buttonGroup: \"buttonGroup\",\n colorSelect: \"colorSelect\",\n sectionLayoutSelect: \"sectionLayoutSelect\",\n background: \"background\",\n contentPosition: \"contentPosition\",\n textSizeSelect: \"textSizeSelect\",\n cssUnit: \"cssUnit\",\n fontPicker: \"fontPicker\",\n stringArray: \"stringArray\",\n borderRadius: \"borderRadius\",\n screenPicker: \"screenPicker\",\n} as const;\n\n/**\n * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant.\n * @see deriving-typeof-for-object-keys pattern\n */\nexport type PropertyFieldType =\n (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES];\n\n/**\n * Runtime validation for property field types.\n * @param value - The value to check\n * @returns true if value is a valid PropertyFieldType\n */\nexport function isPropertyFieldType(value: string): value is PropertyFieldType {\n return Object.values(PROPERTY_FIELD_TYPES).includes(\n value as PropertyFieldType,\n );\n}\n\n/**\n * Group label for fields that override theme-derived styling.\n * Rendered last within a tab and collapsed by default so the primary\n * configuration surface stays clean.\n */\nexport const CUSTOM_STYLING_GROUP = \"Custom styling\";\n\n/**\n * Base schema for a property field\n */\nexport interface PropertyFieldSchema {\n /** Property key in the widget props */\n key: string;\n /** Display label for the field */\n label: string;\n /** Field type determines the input control */\n type: PropertyFieldType;\n /** Optional description/help text */\n description?: string;\n /** Optional default value */\n defaultValue?: unknown;\n /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */\n tab?: string;\n /** Optional group for organizing fields within a tab */\n group?: string;\n /**\n * When true, this field is treated as an override of a value that can\n * otherwise be inherited from the active theme (e.g. border radius,\n * padding, border width). Advanced fields are automatically bucketed\n * into the `CUSTOM_STYLING_GROUP` at the bottom of their tab and\n * rendered collapsed by default so the default surface area stays\n * minimal.\n */\n advanced?: boolean;\n /**\n * @deprecated Use requiresKeyValue instead\n */\n requiresKeyToBeTrue?: string;\n /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */\n requiresKeyValue?:\n | { key: string; value: unknown }\n | Array<{ key: string; value: unknown }>;\n}\n\n/**\n * Text field schema\n */\nexport interface TextFieldSchema extends PropertyFieldSchema {\n type: \"text\";\n placeholder?: string;\n maxLength?: number;\n /**\n * Optional quick-insert chips rendered below the input. Clicking a chip\n * inserts `{{value}}` at the caret. Used for URL template tokens\n * (e.g. `{{username}}`, `{{replicated_url || /signup}}`) so admins\n * don't have to remember the exact spelling.\n */\n tokenSuggestions?: ReadonlyArray<{\n /** Chip label shown to the admin (e.g. `username`). */\n label: string;\n /** Token body inserted between `{{` and `}}` (e.g. `username || /signup`). */\n value: string;\n }>;\n}\n\n/**\n * Textarea field schema\n */\nexport interface TextareaFieldSchema extends PropertyFieldSchema {\n type: \"textarea\";\n placeholder?: string;\n rows?: number;\n maxLength?: number;\n}\n\n/**\n * Number field schema\n */\nexport interface NumberFieldSchema extends PropertyFieldSchema {\n type: \"number\";\n min?: number;\n max?: number;\n step?: number;\n}\n\n/**\n * Boolean field schema\n */\nexport interface BooleanFieldSchema extends PropertyFieldSchema {\n type: \"boolean\";\n}\n\n/**\n * Select field schema with type-safe option values.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface SelectFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"select\";\n options: Array<{ label: string; value: T }>;\n defaultValue?: T;\n}\n\n/**\n * Color field schema\n */\nexport interface ColorFieldSchema extends PropertyFieldSchema {\n type: \"color\";\n}\n\n/**\n * Range slider field schema\n */\nexport interface RangeFieldSchema extends PropertyFieldSchema {\n type: \"range\";\n min: number;\n max: number;\n step?: number;\n}\n\n/**\n * Data source field schema for configuring widget data sources\n */\nexport interface DataSourceFieldSchema extends PropertyFieldSchema {\n type: \"dataSource\";\n}\n\n/**\n * Resource field schema for selecting a single resource from the selection modal\n */\nexport interface ResourceFieldSchema extends PropertyFieldSchema {\n type: \"resource\";\n /** Optional filter to specific shareable types */\n allowedTypes?: string[];\n}\n\n/**\n * Image field schema for selecting a single asset (image or video) from the\n * image picker. Despite the legacy \"image\" name, this field supports video\n * picking via the `accept` parameter — `VideoWidget`, `ListWidget` Featured\n * Asset, and `NestedWidget` Primary Media all use it for video-or-mixed\n * content.\n */\nexport interface ImageFieldSchema extends PropertyFieldSchema {\n type: \"image\";\n /**\n * Restricts which MIME categories the picker offers. Defaults to \"image\".\n */\n accept?: \"image\" | \"video\" | \"any\";\n}\n\n/**\n * Alignment field schema\n */\nexport interface AlignmentFieldSchema extends PropertyFieldSchema {\n type: \"alignment\";\n options: {\n verticalEnabled: boolean;\n horizontalEnabled: boolean;\n };\n defaultValue?: AlignOptions;\n}\n\n/**\n * Slider field schema with optional unit suffix (e.g., \"rem\", \"px\")\n */\nexport interface SliderFieldSchema extends PropertyFieldSchema {\n type: \"slider\";\n min: number;\n max: number;\n step?: number;\n unit?: string;\n}\n\n/**\n * Color picker field schema with optional swatches\n */\nexport interface ColorPickerFieldSchema extends PropertyFieldSchema {\n type: \"colorPicker\";\n swatches?: string[];\n}\n\n/**\n * Section header field schema for visual grouping\n */\nexport interface SectionHeaderFieldSchema extends PropertyFieldSchema {\n type: \"sectionHeader\";\n subtitle?: string;\n}\n\n/**\n * Separator field schema for visual separation\n */\nexport interface SeparatorFieldSchema extends PropertyFieldSchema {\n type: \"separator\";\n}\n\n/**\n * Button group field schema.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface ButtonGroupFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"buttonGroup\";\n options: Array<{\n label?: string;\n ariaLabel?: string;\n icon?: LucideIcon;\n value: T;\n }>;\n defaultValue?: T;\n}\n\n/**\n * Color select field schema\n */\nexport interface ColorSelectFieldSchema extends PropertyFieldSchema {\n type: \"colorSelect\";\n defaultValue?: ColorOptions;\n excludeColors?: ColorOptions[];\n}\n\n/**\n * Section layout select field schema for visual masonry layout selector\n */\nexport interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema {\n type: \"sectionLayoutSelect\";\n defaultValue?: SectionLayoutType;\n}\n\n/**\n * Background field combines resource selection and color properties.\n * Uses StrictOmit to exclude conflicting \"type\" discriminant from parents.\n */\nexport interface BackgroundFieldSchema\n extends\n StrictOmit<ResourceFieldSchema, \"type\">,\n StrictOmit<ColorFieldSchema, \"type\"> {\n type: \"background\";\n}\n\n/**\n * Content position field schema for 3x3 grid position picker\n */\nexport interface ContentPositionFieldSchema extends PropertyFieldSchema {\n type: \"contentPosition\";\n defaultValue?: string;\n}\n\n/**\n * Text size select field schema for visual font size selector\n */\nexport interface TextSizeSelectFieldSchema extends PropertyFieldSchema {\n type: \"textSizeSelect\";\n defaultValue?: FontSizeOptions;\n}\n\n/**\n * CSS unit type for height/width fields\n */\nexport type CssUnit = \"px\" | \"rem\" | \"vh\" | \"%\";\n\n/**\n * CSS unit field schema for numeric values with selectable units (px, rem, vh, %)\n */\nexport interface CssUnitFieldSchema extends PropertyFieldSchema {\n type: \"cssUnit\";\n minByUnit?: Partial<Record<CssUnit, number>>;\n maxByUnit?: Partial<Record<CssUnit, number>>;\n stepByUnit?: Partial<Record<CssUnit, number>>;\n allowedUnits?: CssUnit[];\n defaultUnit?: CssUnit;\n}\n\n/**\n * Font picker field schema for Google Fonts selection\n */\nexport interface FontPickerFieldSchema extends PropertyFieldSchema {\n type: \"fontPicker\";\n placeholder?: string;\n}\n\n/**\n * String array field schema for managing lists of text items\n */\nexport interface StringArrayFieldSchema extends PropertyFieldSchema {\n type: \"stringArray\";\n placeholder?: string;\n defaultValue?: string[];\n}\n\n/**\n * Border radius composite field schema for controlling 4 corners with a single field.\n * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight).\n */\nexport interface BorderRadiusFieldSchema extends PropertyFieldSchema {\n type: \"borderRadius\";\n keys: {\n topLeft: string;\n topRight: string;\n bottomLeft: string;\n bottomRight: string;\n };\n defaultValue?: BorderRadiusOptions;\n}\n\n/**\n * Screen picker field schema for selecting a portal screen (navigation, system, or available)\n */\nexport interface ScreenPickerFieldSchema extends PropertyFieldSchema {\n type: \"screenPicker\";\n /** Whether to include system navigation items in the picker */\n includeSystemItems?: boolean;\n}\n\n/**\n * Union of all field schema types\n */\nexport type PropertyField =\n | TextFieldSchema\n | TextareaFieldSchema\n | NumberFieldSchema\n | BooleanFieldSchema\n | SelectFieldSchema<string | number>\n | ColorFieldSchema\n | RangeFieldSchema\n | DataSourceFieldSchema\n | ResourceFieldSchema\n | ImageFieldSchema\n | AlignmentFieldSchema\n | SliderFieldSchema\n | ColorPickerFieldSchema\n | SectionHeaderFieldSchema\n | SeparatorFieldSchema\n | ButtonGroupFieldSchema<string | number>\n | ColorSelectFieldSchema\n | SectionLayoutSelectFieldSchema\n | BackgroundFieldSchema\n | ContentPositionFieldSchema\n | TextSizeSelectFieldSchema\n | CssUnitFieldSchema\n | FontPickerFieldSchema\n | StringArrayFieldSchema\n | BorderRadiusFieldSchema\n | ScreenPickerFieldSchema;\n\n/**\n * Schema for per-item configuration in custom data sources.\n * Widgets can define this to allow users to configure widget-specific\n * settings for each selected item (e.g., title, description, button).\n */\nexport interface ItemConfigSchema {\n /** Fields available for per-item configuration */\n fields: PropertyField[];\n /** Optional description shown at top of item config panel */\n description?: string;\n}\n\n/**\n * Schema for a widget's editable properties\n */\nexport interface WidgetPropertySchema {\n /** Widget type this schema applies to */\n widgetType: WidgetType;\n /** Display name for the widget */\n displayName: string;\n /** Optional tab configuration - if present, tabs are enabled */\n tabsConfig?: TabConfig[];\n /** Editable property fields */\n fields: PropertyField[];\n /** Optional custom validator function */\n validate?: (props: Record<string, unknown>) => string | null;\n /** Props that can be populated from data sources */\n dataSourceTargetProps?: string[];\n /** Optional schema for per-item configurations in custom data sources */\n itemConfigSchema?: ItemConfigSchema;\n}\n\n/**\n * Registry mapping widget types to their property schemas\n */\nexport type PropertySchemaRegistry = Record<WidgetType, WidgetPropertySchema>;\n\n/**\n * Group property fields by their group property.\n *\n * Fields flagged with `advanced: true` are collected into the\n * `CUSTOM_STYLING_GROUP` bucket regardless of their declared `group`,\n * and that bucket is always placed last so it renders at the bottom of\n * the tab. Non-advanced fields keep their author-declared group and\n * their relative insertion order, including fields that explicitly use\n * `CUSTOM_STYLING_GROUP`.\n */\nexport function groupPropertyFields(\n fields: readonly PropertyField[],\n): Record<string, PropertyField[]> {\n const grouped: Record<string, PropertyField[]> = {};\n const advancedFields: PropertyField[] = [];\n\n fields.forEach((field) => {\n if (field.advanced) {\n advancedFields.push(field);\n return;\n }\n const group = field.group || \"General\";\n if (!grouped[group]) {\n grouped[group] = [];\n }\n grouped[group].push(field);\n });\n\n if (advancedFields.length > 0) {\n const customStylingFields = grouped[CUSTOM_STYLING_GROUP] ?? [];\n delete grouped[CUSTOM_STYLING_GROUP];\n grouped[CUSTOM_STYLING_GROUP] = [...customStylingFields, ...advancedFields];\n }\n\n return grouped;\n}\n\n/**\n * Extract current values from widget props based on property fields\n */\nexport function extractPropertyValues(\n widget: Readonly<WidgetSchema>,\n fields: readonly PropertyField[],\n): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n\n fields.forEach((field) => {\n // For borderRadius composite fields, skip the top-level key —\n // it is a schema grouping identifier, not a real widget prop.\n if (field.type === \"borderRadius\") {\n for (const subKey of Object.values(field.keys)) {\n const subValue = widget.props[subKey];\n values[subKey] = subValue !== undefined ? subValue : field.defaultValue;\n }\n return;\n }\n\n // dataSource config is stored at widget.dataSource (top-level),\n // not in widget.props. Surface it under the field key so schema\n // visibility checks (requiresKeyValue) can gate on its presence.\n if (field.type === \"dataSource\") {\n values[field.key] = widget.dataSource;\n return;\n }\n\n const value = widget.props[field.key];\n values[field.key] = value !== undefined ? value : field.defaultValue;\n });\n\n return values;\n}\n\n/**\n * Apply property values to widget props\n */\nexport function applyPropertyValues(\n widget: Readonly<WidgetSchema>,\n values: Readonly<Record<string, unknown>>,\n): WidgetSchema {\n return {\n ...widget,\n props: {\n ...widget.props,\n ...values,\n },\n };\n}\n","import type {\n BorderRadiusFieldSchema,\n ButtonGroupFieldSchema,\n ColorSelectFieldSchema,\n CssUnitFieldSchema,\n TextSizeSelectFieldSchema,\n} from \"./property-schema-types\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontWeightOptions,\n PaddingOptions,\n ButtonSizeOptions,\n GapOptions,\n} from \"../types\";\nimport { Ban } from \"lucide-react\";\n\nexport const getColorField = (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n): ColorSelectFieldSchema => {\n return {\n ...props,\n type: \"colorSelect\",\n };\n};\n\nexport const getBorderRadiusField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderRadiusOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderRadiusOptions> => {\n return {\n // Border radius inherits from the active theme by default. Mark as\n // advanced so widget-level overrides collapse into the \"Custom\n // styling\" disclosure.\n //\n // Note: `groupPropertyFields` ignores `field.group` whenever\n // `field.advanced` is true. If a widget explicitly wants this\n // control to live in its own group, pass `advanced: false`\n // alongside `group: \"...\"` to opt out.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No radius\", value: \"none\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n { label: \"FULL\", value: \"full\" },\n ],\n };\n};\n\nexport const getPaddingField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<PaddingOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<PaddingOptions> => {\n return {\n // Padding follows the theme's global spacing scale by default.\n // Mark as advanced so widget-level overrides collapse into the\n // \"Custom styling\" disclosure. To keep this field in a different\n // group, pass `advanced: false` alongside `group: \"...\"`.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No padding\", value: 0 },\n { label: \"SM\", value: 2 },\n { label: \"MD\", value: 4 },\n { label: \"LG\", value: 6 },\n { label: \"XL\", value: 8 },\n { label: \"FULL\", value: 10 },\n ],\n };\n};\n\nexport const getButtonSizeField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<ButtonSizeOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<ButtonSizeOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"default\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getFontWeightField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<FontWeightOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<FontWeightOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"Normal\", value: \"normal\" },\n { label: \"Medium\", value: \"medium\" },\n { label: \"Semibold\", value: \"semibold\" },\n { label: \"Bold\", value: \"bold\" },\n ],\n };\n};\n\nexport const getFontSizeField = (\n props: Readonly<Omit<TextSizeSelectFieldSchema, \"type\">>,\n): TextSizeSelectFieldSchema => {\n return {\n ...props,\n type: \"textSizeSelect\",\n };\n};\n\nexport const getGapField = (\n props: Readonly<Omit<ButtonGroupFieldSchema<GapOptions>, \"options\" | \"type\">>,\n): ButtonGroupFieldSchema<GapOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No gap\", value: \"none\" },\n { label: \"XS\", value: \"xs\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getHeightField = (\n props: Readonly<\n Omit<\n CssUnitFieldSchema,\n \"type\" | \"minByUnit\" | \"maxByUnit\" | \"stepByUnit\" | \"allowedUnits\"\n >\n >,\n): CssUnitFieldSchema => {\n return {\n ...props,\n type: \"cssUnit\",\n allowedUnits: [\"px\", \"vh\", \"rem\"],\n minByUnit: { px: 10, vh: 1, rem: 1 },\n maxByUnit: { px: 1200, vh: 100, rem: 75 },\n stepByUnit: { px: 10, vh: 1, rem: 1 },\n };\n};\n\nexport const getBorderRadiusCompositeField = (\n props: Readonly<\n Omit<BorderRadiusFieldSchema, \"type\" | \"keys\"> & {\n keys?: BorderRadiusFieldSchema[\"keys\"];\n }\n >,\n): BorderRadiusFieldSchema => {\n return {\n // Per-corner radius controls are theme-derivable in the same way as\n // the simpler `getBorderRadiusField`. Pass `advanced: false`\n // alongside `group: \"...\"` to opt out of Custom Styling.\n advanced: true,\n ...props,\n type: \"borderRadius\",\n keys: props.keys ?? {\n topLeft: \"borderRadiusTL\",\n topRight: \"borderRadiusTR\",\n bottomLeft: \"borderRadiusBL\",\n bottomRight: \"borderRadiusBR\",\n },\n };\n};\n\n/**\n * Gap value mapping - use `as const satisfies` for compile-time validation\n * with literal type preservation.\n */\nexport const gapValues: {\n readonly none: 0;\n readonly xs: 1;\n readonly sm: 2;\n readonly md: 4;\n readonly lg: 6;\n readonly xl: 8;\n} = {\n none: 0,\n xs: 1,\n sm: 2,\n md: 4,\n lg: 6,\n xl: 8,\n} as const satisfies Record<GapOptions, number>;\n\nexport const getBorderWidthField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderWidthOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderWidthOptions> => ({\n // Border width is a styling override of a theme-derivable decision.\n // Pass `advanced: false` alongside `group: \"...\"` to opt out of\n // Custom Styling.\n advanced: true,\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, ariaLabel: \"No border\", value: \"none\" },\n { label: \"THIN\", value: \"thin\" },\n { label: \"MD\", value: \"medium\" },\n { label: \"THICK\", value: \"thick\" },\n ],\n});\n\nexport const getBorderColorField: (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n) => ColorSelectFieldSchema = getColorField;\n\n/**\n * Border width class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderWidthClasses: {\n readonly none: \"border-0\";\n readonly thin: \"border\";\n readonly medium: \"border-2\";\n readonly thick: \"border-4\";\n} = {\n none: \"border-0\",\n thin: \"border\",\n medium: \"border-2\",\n thick: \"border-4\",\n} as const satisfies Record<BorderWidthOptions, string>;\n\n/**\n * Border color class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderColorClasses: {\n readonly background: \"border-background\";\n readonly foreground: \"border-foreground\";\n readonly primary: \"border-primary\";\n readonly secondary: \"border-secondary\";\n readonly accent: \"border-accent\";\n readonly border: \"border-border\";\n readonly muted: \"border-muted\";\n readonly destructive: \"border-destructive\";\n readonly transparent: \"border-transparent\";\n} = {\n background: \"border-background\",\n foreground: \"border-foreground\",\n primary: \"border-primary\",\n secondary: \"border-secondary\",\n accent: \"border-accent\",\n border: \"border-border\",\n muted: \"border-muted\",\n destructive: \"border-destructive\",\n transparent: \"border-transparent\",\n} as const satisfies Record<ColorOptions, string>;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-app/portal-sdk",
3
- "version": "0.1.364",
3
+ "version": "0.1.366",
4
4
  "description": "SDK for building custom Fluid portals",
5
5
  "files": [
6
6
  "dist",
@@ -71,31 +71,31 @@
71
71
  "tsdown": "^0.21.0",
72
72
  "typescript": "^5",
73
73
  "zod": "4.3.5",
74
+ "@fluid-app/address-autocomplete": "0.1.0",
74
75
  "@fluid-app/address-fields": "0.1.0",
75
- "@fluid-app/auth": "0.1.0",
76
76
  "@fluid-app/api-client-core": "0.1.0",
77
+ "@fluid-app/auth": "0.1.0",
77
78
  "@fluid-app/cart-ui": "0.1.23",
78
- "@fluid-app/address-autocomplete": "0.1.0",
79
79
  "@fluid-app/company-switcher-core": "0.1.0",
80
- "@fluid-app/company-switcher-ui": "0.1.0",
81
80
  "@fluid-app/contacts-core": "0.1.0",
82
- "@fluid-app/file-picker-core": "0.1.0",
83
81
  "@fluid-app/contacts-ui": "0.1.0",
84
- "@fluid-app/fluid-pay-core": "0.1.0",
85
- "@fluid-app/fluid-pay-ui": "0.1.0",
86
82
  "@fluid-app/file-picker-api-client": "0.1.0",
83
+ "@fluid-app/company-switcher-ui": "0.1.0",
84
+ "@fluid-app/fluid-pay-ui": "0.1.0",
87
85
  "@fluid-app/fluidos-api-client": "0.1.0",
88
- "@fluid-app/messaging-api-client": "0.1.0",
89
- "@fluid-app/i18n": "0.1.0",
86
+ "@fluid-app/file-picker-core": "0.1.0",
87
+ "@fluid-app/fluid-pay-core": "0.1.0",
90
88
  "@fluid-app/messaging-core": "0.1.0",
91
- "@fluid-app/messaging-ui": "0.1.0",
89
+ "@fluid-app/messaging-api-client": "0.1.0",
92
90
  "@fluid-app/mysite-core": "0.1.0",
93
- "@fluid-app/mysite-ui": "0.1.0",
94
- "@fluid-app/orders-ui": "0.1.0",
91
+ "@fluid-app/messaging-ui": "0.1.0",
95
92
  "@fluid-app/orders-core": "0.1.0",
93
+ "@fluid-app/mysite-ui": "0.1.0",
94
+ "@fluid-app/i18n": "0.1.0",
96
95
  "@fluid-app/permissions": "0.1.0",
97
- "@fluid-app/portal-app-download-ui": "0.1.0",
96
+ "@fluid-app/orders-ui": "0.1.0",
98
97
  "@fluid-app/portal-core": "0.1.23",
98
+ "@fluid-app/portal-app-download-ui": "0.1.0",
99
99
  "@fluid-app/portal-preview": "0.1.0",
100
100
  "@fluid-app/portal-pro-upgrade-ui": "0.1.0",
101
101
  "@fluid-app/portal-react": "0.1.0",
@@ -103,13 +103,13 @@
103
103
  "@fluid-app/portal-tenant-contacts-api-client": "0.1.0",
104
104
  "@fluid-app/portal-tenant-content-api-client": "0.1.0",
105
105
  "@fluid-app/portal-tenant-mysite-api-client": "0.1.0",
106
- "@fluid-app/portal-tenant-pay-api-client": "0.1.0",
107
106
  "@fluid-app/portal-tenant-store-api-client": "0.1.0",
108
- "@fluid-app/portal-widgets": "0.1.22",
107
+ "@fluid-app/portal-tenant-pay-api-client": "0.1.0",
109
108
  "@fluid-app/products-api-client": "0.1.0",
110
- "@fluid-app/products-core": "0.1.0",
111
- "@fluid-app/profile-ui": "0.1.0",
109
+ "@fluid-app/portal-widgets": "0.1.22",
112
110
  "@fluid-app/profile-core": "0.1.0",
111
+ "@fluid-app/profile-ui": "0.1.0",
112
+ "@fluid-app/products-core": "0.1.0",
113
113
  "@fluid-app/query-persister": "0.1.0",
114
114
  "@fluid-app/shareables-core": "0.1.0",
115
115
  "@fluid-app/shareables-ui": "0.1.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"EmbedWidget-BMy0C8ik.cjs","names":["BookmarkIcon","GraduationCap","Globe","borderWidthClasses","borderColorClasses","RotateCw","Maximize2","ExternalLink","X","getHeightField","getColorField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/contexts/RepUserContext.tsx","../../widgets/src/widgets/EmbedWidget.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useMemo,\n type ReactNode,\n} from \"react\";\n\nexport interface RepUser {\n name: string | null;\n email: string | null;\n imageUrl: string | null;\n publicId?: string;\n}\n\nconst RepUserContext = createContext<RepUser | null>(null);\n\nexport interface RepUserProviderProps {\n user: RepUser;\n children: ReactNode;\n}\n\nexport function RepUserProvider({\n user,\n children,\n}: RepUserProviderProps): React.JSX.Element {\n const value = useMemo(() => user, [user]);\n return (\n <RepUserContext.Provider value={value}>{children}</RepUserContext.Provider>\n );\n}\n\nexport function useRepUser(): RepUser | null {\n return useContext(RepUserContext);\n}\n","import {\n Bell,\n BookmarkIcon,\n BookOpen,\n Calendar,\n ExternalLink,\n Gift,\n Globe,\n GraduationCap,\n Heart,\n Maximize2,\n RotateCw,\n ShoppingBag,\n Sparkles,\n Star,\n Trophy,\n User,\n Video,\n X,\n Zap,\n type LucideIcon,\n} from \"lucide-react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentProps,\n type RefObject,\n} from \"react\";\nimport type React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n getBorderRadiusField,\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { useRepUser } from \"../contexts/RepUserContext\";\n\ntype EmbedWidgetMessage = {\n type: \"OPEN_FULL_SCREEN_WEBVIEW\";\n url: string;\n};\n\ntype DisplayMode = \"inline\" | \"cover\";\n\ntype EmbedUrlState = {\n normalizedUrl: string;\n isValidUrl: boolean;\n iframeSrc: string;\n};\n\nfunction isValidHttpUrl(urlString: string): boolean {\n try {\n const parsed = new URL(urlString);\n return parsed.protocol === \"https:\" || parsed.protocol === \"http:\";\n } catch {\n return false;\n }\n}\n\nfunction useEmbedUrl(url: string, publicId: string | undefined): EmbedUrlState {\n return useMemo(() => {\n const normalizedUrl =\n url && (url.startsWith(\"http://\") || url.startsWith(\"https://\"))\n ? url\n : url\n ? `https://${url}`\n : \"\";\n\n let isValidUrl = false;\n if (normalizedUrl) {\n try {\n const parsed = new URL(normalizedUrl);\n isValidUrl =\n (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") &&\n (parsed.hostname.includes(\".\") || parsed.hostname === \"localhost\");\n } catch {\n // invalid URL\n }\n }\n\n if (!isValidUrl || !publicId) {\n return { normalizedUrl, isValidUrl, iframeSrc: normalizedUrl };\n }\n\n const urlObj = new URL(normalizedUrl);\n urlObj.searchParams.set(\"public_id\", publicId);\n return { normalizedUrl, isValidUrl, iframeSrc: urlObj.toString() };\n }, [url, publicId]);\n}\n\ntype UseEmbedPostMessageBridgeProps = {\n iframeRef: RefObject<HTMLIFrameElement | null>;\n normalizedUrl: string;\n isValidUrl: boolean;\n editMode: boolean;\n};\n\nfunction useEmbedPostMessageBridge({\n iframeRef,\n normalizedUrl,\n isValidUrl,\n editMode,\n}: UseEmbedPostMessageBridgeProps): void {\n useEffect(() => {\n if (!isValidUrl || editMode) return;\n\n const expectedOrigin = new URL(normalizedUrl).origin;\n\n function handleMessage(event: MessageEvent) {\n if (event.origin !== expectedOrigin) return;\n if (event.source !== iframeRef.current?.contentWindow) return;\n\n let data: unknown;\n if (typeof event.data === \"string\") {\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n } else {\n data = event.data;\n }\n\n if (\n typeof data === \"object\" &&\n data !== null &&\n \"type\" in data &&\n (data as EmbedWidgetMessage).type === \"OPEN_FULL_SCREEN_WEBVIEW\"\n ) {\n const messageUrl = (data as EmbedWidgetMessage).url;\n if (messageUrl && isValidHttpUrl(messageUrl)) {\n window.open(messageUrl, \"_blank\", \"noopener,noreferrer\");\n }\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [iframeRef, normalizedUrl, isValidUrl, editMode]);\n}\n\nfunction useModalBodyScrollLock(isOpen: boolean): void {\n useEffect(() => {\n if (!isOpen) return;\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previousOverflow;\n };\n }, [isOpen]);\n}\n\nfunction useModalEscapeClose(isOpen: boolean, onClose: () => void): void {\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose();\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, onClose]);\n}\n\nfunction useDialogFocusRestore(dialogRef: RefObject<HTMLElement | null>): void {\n useEffect(() => {\n const previouslyFocused =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n dialogRef.current?.focus();\n return () => {\n previouslyFocused?.focus();\n };\n }, [dialogRef]);\n}\n\n// ---------- header icon registry ----------\n\nconst HEADER_ICON_MAP: Record<string, LucideIcon> = {\n GraduationCap,\n Video,\n BookOpen,\n Globe,\n User,\n Star,\n Heart,\n Trophy,\n Sparkles,\n Zap,\n Gift,\n ShoppingBag,\n Bell,\n Calendar,\n Bookmark: BookmarkIcon,\n};\n\nconst HEADER_ICON_OPTIONS: Array<{ label: string; value: string }> = [\n { label: \"Graduation Cap\", value: \"GraduationCap\" },\n { label: \"Video\", value: \"Video\" },\n { label: \"Book\", value: \"BookOpen\" },\n { label: \"Globe\", value: \"Globe\" },\n { label: \"User\", value: \"User\" },\n { label: \"Star\", value: \"Star\" },\n { label: \"Heart\", value: \"Heart\" },\n { label: \"Trophy\", value: \"Trophy\" },\n { label: \"Sparkles\", value: \"Sparkles\" },\n { label: \"Zap / Lightning\", value: \"Zap\" },\n { label: \"Gift\", value: \"Gift\" },\n { label: \"Shopping Bag\", value: \"ShoppingBag\" },\n { label: \"Bell\", value: \"Bell\" },\n { label: \"Calendar\", value: \"Calendar\" },\n { label: \"Bookmark\", value: \"Bookmark\" },\n];\n\nconst getHeaderIcon = (name: string | undefined): LucideIcon => {\n if (!name) return GraduationCap;\n return HEADER_ICON_MAP[name] ?? GraduationCap;\n};\n\ntype EmbedWidgetProps = ComponentProps<\"div\"> & {\n url?: string;\n title?: string;\n height?: string;\n fullScreen?: boolean;\n allowFullscreen?: boolean;\n loading?: \"eager\" | \"lazy\";\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n editMode?: boolean;\n isSelected?: boolean;\n\n // Cover-mode additions (all optional — inline mode ignores these)\n displayMode?: DisplayMode;\n coverResource?: ShareableItem;\n coverUseCustomUrl?: boolean;\n coverImageUrl?: string;\n coverTitle?: string;\n coverMeta?: string;\n coverShowHeader?: boolean;\n coverHeaderIcon?: string;\n coverHeaderIconColor?: ColorOptions;\n coverHeight?: string;\n};\n\nexport function EmbedWidget({\n url = \"\",\n title = \"Embedded Content\",\n height = \"400px\",\n fullScreen = false,\n allowFullscreen = true,\n loading = \"lazy\",\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n editMode = false,\n isSelected = false,\n\n displayMode = \"inline\",\n coverResource,\n coverUseCustomUrl = false,\n coverImageUrl = \"\",\n coverTitle = \"\",\n coverMeta = \"\",\n coverShowHeader = true,\n coverHeaderIcon = \"GraduationCap\",\n coverHeaderIconColor = \"primary\",\n coverHeight = \"320px\",\n\n className,\n ...props\n}: EmbedWidgetProps): React.JSX.Element {\n const isFullScreen = fullScreen;\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const repUser = useRepUser();\n const publicId = repUser?.publicId;\n\n const [modalOpen, setModalOpen] = useState(false);\n const [coverReloadKey, setCoverReloadKey] = useState(0);\n const [iframeReloadKey, setIframeReloadKey] = useState(0);\n\n const closeModal = useCallback(() => setModalOpen(false), []);\n\n const { normalizedUrl, isValidUrl, iframeSrc } = useEmbedUrl(url, publicId);\n useEmbedPostMessageBridge({\n iframeRef,\n normalizedUrl,\n isValidUrl,\n editMode,\n });\n useModalBodyScrollLock(modalOpen);\n useModalEscapeClose(modalOpen, closeModal);\n\n // ----- Empty/invalid URL states -----\n\n if (!url || !isValidUrl) {\n return (\n <div\n className={`flex items-center justify-center rounded-${borderRadius} border-border bg-muted text-muted-foreground border-2 border-dashed ${className ?? \"\"}`}\n {...props}\n style={\n isFullScreen\n ? {\n height:\n \"var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))\",\n }\n : { height: displayMode === \"cover\" ? coverHeight : height }\n }\n >\n <div className=\"flex flex-col items-center gap-2 p-6 text-center\">\n <Globe className=\"size-12 opacity-50\" />\n <p className=\"text-sm font-medium\">\n Enter a URL to embed external content\n </p>\n <p className=\"text-xs opacity-75\">\n Configure the URL in the properties panel\n </p>\n </div>\n </div>\n );\n }\n\n // ----- Cover mode -----\n\n if (displayMode === \"cover\") {\n const resolvedCoverImage = coverUseCustomUrl\n ? coverImageUrl\n : coverResource?.imageUrl || coverResource?.image_url || coverImageUrl;\n\n const effectiveTitle = coverTitle || title;\n const HeaderIcon = getHeaderIcon(coverHeaderIcon);\n\n const handleOpenModal = () => {\n if (editMode) return;\n setModalOpen(true);\n };\n\n const handleReload = () => {\n if (editMode) return;\n setCoverReloadKey((key) => key + 1);\n };\n\n const handleOpenNewTab = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (editMode) return;\n window.open(iframeSrc, \"_blank\", \"noopener,noreferrer\");\n };\n\n return (\n <>\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-background ${className ?? \"\"}`}\n style={{\n boxShadow:\n \"0 1px 2px color-mix(in oklch, var(--color-foreground) 5%, transparent), 0 12px 32px -16px color-mix(in oklch, var(--color-foreground) 10%, transparent)\",\n }}\n {...props}\n >\n {/* Inset hairline ring */}\n <div\n aria-hidden=\"true\"\n className={`pointer-events-none absolute inset-0 z-[1] rounded-${borderRadius}`}\n style={{\n boxShadow:\n \"inset 0 0 0 1px color-mix(in oklch, var(--color-foreground) 8%, transparent)\",\n }}\n />\n {coverShowHeader && (\n <div className=\"relative z-[2] flex items-center gap-3 px-5 py-3\">\n <span\n aria-hidden=\"true\"\n className={`text-${coverHeaderIconColor}-foreground flex size-7 shrink-0 items-center justify-center rounded-${borderRadius}`}\n style={{\n background: `linear-gradient(135deg, color-mix(in oklch, var(--color-${coverHeaderIconColor}) 75%, white 25%) 0%, var(--color-${coverHeaderIconColor}) 100%)`,\n boxShadow: `\n inset 0 1px 0 rgba(255,255,255,0.25),\n inset 0 -1px 0 rgba(0,0,0,0.08),\n 0 1px 2px color-mix(in oklch, var(--color-${coverHeaderIconColor}) 25%, transparent)\n `,\n }}\n >\n <HeaderIcon className=\"size-3.5\" strokeWidth={2.25} />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n {effectiveTitle && (\n <h3 className=\"text-foreground truncate text-[15px] leading-tight font-semibold tracking-tight\">\n {effectiveTitle}\n </h3>\n )}\n {coverMeta && (\n <p className=\"text-foreground/40 mt-0.5 truncate text-[11px] font-medium tracking-[0.08em] uppercase\">\n {coverMeta}\n </p>\n )}\n </div>\n\n <div className=\"bg-foreground/5 flex shrink-0 items-center rounded-lg p-0.5\">\n <HeaderIconButton\n Icon={RotateCw}\n label=\"Reload\"\n onClick={(e) => {\n e.stopPropagation();\n handleReload();\n }}\n />\n <HeaderIconButton\n Icon={Maximize2}\n label=\"Open\"\n onClick={(e) => {\n e.stopPropagation();\n handleOpenModal();\n }}\n />\n <HeaderIconButton\n Icon={ExternalLink}\n label=\"Open in new tab\"\n onClick={handleOpenNewTab}\n />\n </div>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={handleOpenModal}\n disabled={editMode}\n className={`relative block w-full overflow-hidden ${editMode ? \"cursor-default\" : \"cursor-pointer\"}`}\n style={{ height: coverHeight }}\n aria-label={`Open ${effectiveTitle || title}`}\n >\n {resolvedCoverImage ? (\n <img\n key={`cover-${coverReloadKey}`}\n src={resolvedCoverImage}\n alt={effectiveTitle || title}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"bg-muted flex h-full w-full items-center justify-center\">\n <Globe className=\"text-muted-foreground/40 size-16\" />\n </div>\n )}\n </button>\n {editMode && !isSelected && <div className=\"absolute inset-0 z-10\" />}\n </div>\n\n {modalOpen && (\n <EmbedModal\n key={`modal-${iframeReloadKey}`}\n src={iframeSrc}\n title={effectiveTitle || title}\n allowFullscreen={allowFullscreen}\n iframeRef={iframeRef}\n onClose={closeModal}\n onReload={() => setIframeReloadKey((key) => key + 1)}\n />\n )}\n </>\n );\n }\n\n // ----- Inline mode (original behavior) -----\n\n return (\n <div\n className={`relative w-full rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n {...props}\n style={\n isFullScreen\n ? {\n height:\n \"var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))\",\n }\n : undefined\n }\n >\n <iframe\n ref={iframeRef}\n src={iframeSrc}\n title={title}\n width=\"100%\"\n style={isFullScreen ? { height: \"100%\" } : { height }}\n loading={loading}\n allowFullScreen={allowFullscreen}\n className={`rounded-${borderRadius} border-border border`}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\"\n />\n {editMode && !isSelected && <div className=\"absolute inset-0 z-10\" />}\n </div>\n );\n}\n\n// ----- Header icon button -----\n\ntype HeaderIconButtonProps = {\n Icon: LucideIcon;\n label: string;\n onClick: (e: React.MouseEvent) => void;\n};\n\nfunction HeaderIconButton({\n Icon,\n label,\n onClick,\n}: HeaderIconButtonProps): React.JSX.Element {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className=\"text-foreground/45 hover:text-foreground hover:bg-background flex size-7 items-center justify-center rounded-md transition-colors\"\n >\n <Icon className=\"size-3.5\" strokeWidth={2.25} />\n </button>\n );\n}\n\n// ----- Modal -----\n\ntype EmbedModalProps = {\n src: string;\n title: string;\n allowFullscreen: boolean;\n iframeRef: RefObject<HTMLIFrameElement | null>;\n onClose: () => void;\n onReload: () => void;\n};\n\nfunction EmbedModal({\n src,\n title,\n allowFullscreen,\n iframeRef,\n onClose,\n onReload,\n}: EmbedModalProps): React.JSX.Element {\n const dialogRef = useRef<HTMLDivElement>(null);\n\n useDialogFocusRestore(dialogRef);\n\n // Portal to document.body so the fixed-position dialog isn't clipped by\n // a transformed widget container on the live canvas (CSS transforms make\n // descendants the containing block for `position: fixed`).\n return createPortal(\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"fixed inset-0 z-[100] flex items-center justify-center p-4 focus:outline-none sm:p-8\"\n style={{\n background: \"color-mix(in oklch, var(--color-foreground) 80%, black)\",\n }}\n onClick={onClose}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n <div\n className=\"bg-background relative flex h-full max-h-[95vh] w-full max-w-[1400px] flex-col overflow-hidden rounded-2xl shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n >\n <div\n className=\"flex items-center justify-between gap-4 px-5 py-3\"\n style={{\n borderBottom:\n \"1px solid color-mix(in oklch, var(--color-foreground) 8%, transparent)\",\n }}\n >\n <h3 className=\"text-foreground truncate text-sm font-semibold tracking-tight\">\n {title}\n </h3>\n <div className=\"flex shrink-0 items-center gap-1\">\n <HeaderIconButton\n Icon={RotateCw}\n label=\"Reload\"\n onClick={(e) => {\n e.stopPropagation();\n onReload();\n }}\n />\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close\"\n className=\"text-foreground/60 hover:text-foreground hover:bg-foreground/5 flex size-9 shrink-0 items-center justify-center rounded-full transition-colors\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n </div>\n <iframe\n ref={iframeRef}\n src={src}\n title={title}\n className=\"flex-1 border-0\"\n allowFullScreen={allowFullscreen}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\"\n />\n </div>\n </div>,\n document.body,\n );\n}\n\n// ----- Schema -----\n\nexport const embedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"EmbedWidget\",\n displayName: \"Embed\",\n fields: [\n // Content\n {\n key: \"url\",\n label: \"URL\",\n type: \"text\",\n description: \"The URL of the external site to embed\",\n placeholder: \"https://example.com\",\n defaultValue: \"\",\n group: \"Content\",\n },\n {\n key: \"title\",\n label: \"Screen Reader Label\",\n type: \"text\",\n description:\n \"Describes the embed for screen readers and assistive tech. Not visible on the page.\",\n defaultValue: \"Embedded Content\",\n group: \"Content\",\n },\n\n // Display Mode\n {\n key: \"displayMode\",\n label: \"Display Mode\",\n type: \"buttonGroup\",\n description:\n \"Inline: iframe renders directly. Cover: shows a card that opens the embed in a full-screen modal.\",\n defaultValue: \"inline\",\n options: [\n { label: \"Inline\", value: \"inline\" },\n { label: \"Cover + Modal\", value: \"cover\" },\n ],\n group: \"Display Mode\",\n },\n\n // Cover fields — all gated behind displayMode=cover\n {\n key: \"coverResource\",\n label: \"Cover Image\",\n type: \"resource\",\n description: \"Select the image shown before the embed opens\",\n allowedTypes: [\"Medium\"],\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverUseCustomUrl\",\n label: \"Use Custom URL\",\n type: \"boolean\",\n description: \"Enter a custom image URL instead of selecting media\",\n defaultValue: false,\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverImageUrl\",\n label: \"Cover Image URL\",\n type: \"text\",\n description: \"Direct URL to the cover image\",\n placeholder: \"https://example.com/cover.jpg\",\n defaultValue: \"\",\n group: \"Cover\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverUseCustomUrl\", value: true },\n ],\n },\n getHeightField({\n key: \"coverHeight\",\n label: \"Cover Height\",\n description: \"Height of the cover image area\",\n defaultValue: \"320px\",\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n }),\n\n // Cover header (optional)\n {\n key: \"coverShowHeader\",\n label: \"Show Card Header\",\n type: \"boolean\",\n description: \"Show the header with icon, title, and action buttons\",\n defaultValue: true,\n group: \"Cover Header\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverHeaderIcon\",\n label: \"Header Icon\",\n type: \"select\",\n description: \"Icon displayed in the colored badge on the left\",\n options: HEADER_ICON_OPTIONS,\n defaultValue: \"GraduationCap\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n },\n getColorField({\n key: \"coverHeaderIconColor\",\n label: \"Icon Badge Color\",\n description: \"Background color of the icon badge\",\n defaultValue: \"primary\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n }),\n {\n key: \"coverTitle\",\n label: \"Header Title\",\n type: \"text\",\n description:\n \"Title shown in the card header and modal (falls back to the widget Title if empty). Available even when the card header is hidden so the modal still has a meaningful title.\",\n defaultValue: \"\",\n group: \"Cover Header\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverMeta\",\n label: \"Meta Text\",\n type: \"text\",\n description:\n \"Small uppercase meta line below the title (e.g. 'APR 16 · COACHING THE HOSTESS')\",\n defaultValue: \"\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n },\n\n // Design\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the embed container\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n {\n key: \"fullScreen\",\n label: \"Full Screen\",\n type: \"boolean\",\n description:\n \"Inline mode: fill the available space instead of a fixed height\",\n defaultValue: false,\n group: \"Design\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n getHeightField({\n key: \"height\",\n label: \"Height\",\n description: \"Height of the inline embed iframe\",\n defaultValue: \"400px\",\n group: \"Design\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"inline\" },\n { key: \"fullScreen\", value: false },\n ],\n }),\n\n // Settings\n {\n key: \"allowFullscreen\",\n label: \"Allow Fullscreen\",\n type: \"boolean\",\n description: \"Allow the embedded content to use fullscreen mode\",\n defaultValue: true,\n group: \"Settings\",\n },\n {\n key: \"loading\",\n label: \"Loading\",\n type: \"select\",\n description: \"When to load the embedded content (inline mode only)\",\n options: [\n { label: \"Lazy (on scroll)\", value: \"lazy\" },\n { label: \"Eager (immediately)\", value: \"eager\" },\n ],\n defaultValue: \"lazy\",\n group: \"Settings\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n ],\n};\n"],"mappings":"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"}