@fluid-app/portal-widgets 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ListWidget-C0RDtImi.cjs +2 -0
- package/dist/{ListWidget-RHQ2fQXa.cjs → ListWidget-DPVLRWoB.cjs} +37 -49
- package/dist/ListWidget-DPVLRWoB.cjs.map +1 -0
- package/dist/{ListWidget-C-jcsCb4.mjs → ListWidget-DdvuIQXy.mjs} +37 -39
- package/dist/ListWidget-DdvuIQXy.mjs.map +1 -0
- package/dist/{MySiteWidget-A_cYFgxJ.cjs → MySiteWidget-1xqN0Bcg.cjs} +1 -1
- package/dist/{MySiteWidget-A_cYFgxJ.cjs.map → MySiteWidget-1xqN0Bcg.cjs.map} +1 -1
- package/dist/{MySiteWidget-DariqlfU.mjs → MySiteWidget-CX_jY14-.mjs} +1 -1
- package/dist/{MySiteWidget-DariqlfU.mjs.map → MySiteWidget-CX_jY14-.mjs.map} +1 -1
- package/dist/NestedWidget-DjZYPLc7.cjs +2 -0
- package/dist/{NestedWidget-BaRb7Z5r.mjs → NestedWidget-DoevHJKG.mjs} +27 -3
- package/dist/NestedWidget-DoevHJKG.mjs.map +1 -0
- package/dist/{NestedWidget-Dbo3dXEi.cjs → NestedWidget-DszMmpt7.cjs} +28 -14
- package/dist/NestedWidget-DszMmpt7.cjs.map +1 -0
- package/dist/{QuickShareWidget-DXq5lcDn.mjs → QuickShareWidget-CdvP1eRx.mjs} +1 -1
- package/dist/{QuickShareWidget-DXq5lcDn.mjs.map → QuickShareWidget-CdvP1eRx.mjs.map} +1 -1
- package/dist/{QuickShareWidget-DWvgEy74.cjs → QuickShareWidget-Dg2OcMYg.cjs} +1 -1
- package/dist/{QuickShareWidget-DWvgEy74.cjs.map → QuickShareWidget-Dg2OcMYg.cjs.map} +1 -1
- package/dist/{RecentActivityWidget-BvncOdax.mjs → RecentActivityWidget-YD-2z7oN.mjs} +12 -2
- package/dist/RecentActivityWidget-YD-2z7oN.mjs.map +1 -0
- package/dist/{RecentActivityWidget-wODng8dt.cjs → RecentActivityWidget-_3h0KmQP.cjs} +13 -2
- package/dist/RecentActivityWidget-_3h0KmQP.cjs.map +1 -0
- package/dist/{SpacerWidget-BFboILmz.cjs → SpacerWidget-BdVf_Yqm.cjs} +1 -1
- package/dist/{SpacerWidget-BFboILmz.cjs.map → SpacerWidget-BdVf_Yqm.cjs.map} +1 -1
- package/dist/{SpacerWidget-Cc0IuKda.mjs → SpacerWidget-DxR5K3hp.mjs} +1 -1
- package/dist/{SpacerWidget-Cc0IuKda.mjs.map → SpacerWidget-DxR5K3hp.mjs.map} +1 -1
- package/dist/{TableWidget-iS_DwHOX.cjs → TableWidget-BQNVZUkg.cjs} +15 -13
- package/dist/TableWidget-BQNVZUkg.cjs.map +1 -0
- package/dist/TableWidget-amUotAZN.cjs +2 -0
- package/dist/{TableWidget-DqAN_2sf.mjs → TableWidget-bpvdvJHI.mjs} +14 -2
- package/dist/TableWidget-bpvdvJHI.mjs.map +1 -0
- package/dist/{ToDoWidget-D8YIsl7y.mjs → ToDoWidget-4EZIWq_Z.mjs} +1 -1
- package/dist/{ToDoWidget-D8YIsl7y.mjs.map → ToDoWidget-4EZIWq_Z.mjs.map} +1 -1
- package/dist/{ToDoWidget-Dvs0GDkx.cjs → ToDoWidget-D5BFKUrZ.cjs} +1 -1
- package/dist/{ToDoWidget-Dvs0GDkx.cjs.map → ToDoWidget-D5BFKUrZ.cjs.map} +1 -1
- package/dist/{VideoWidget-D_1kluGw.mjs → VideoWidget-CYSOjVec.mjs} +1 -1
- package/dist/{VideoWidget-D_1kluGw.mjs.map → VideoWidget-CYSOjVec.mjs.map} +1 -1
- package/dist/{VideoWidget-D3Fw1jZE.cjs → VideoWidget-CqRHfFnI.cjs} +1 -1
- package/dist/{VideoWidget-D3Fw1jZE.cjs.map → VideoWidget-CqRHfFnI.cjs.map} +1 -1
- package/dist/WidgetInteractionContext-DjlpWpTR.cjs +31 -0
- package/dist/WidgetInteractionContext-DjlpWpTR.cjs.map +1 -0
- package/dist/WidgetInteractionContext-awLrJeAK.mjs +18 -0
- package/dist/WidgetInteractionContext-awLrJeAK.mjs.map +1 -0
- package/dist/contexts/index.cjs +3 -0
- package/dist/contexts/index.d.cts +19 -1
- package/dist/contexts/index.d.cts.map +1 -1
- package/dist/contexts/index.d.mts +19 -1
- package/dist/contexts/index.d.mts.map +1 -1
- package/dist/contexts/index.mjs +2 -1
- package/dist/core/index.d.mts +1 -1
- package/dist/widgets/index.cjs +18 -18
- package/dist/widgets/index.cjs.map +1 -1
- package/dist/widgets/index.d.cts +1 -2
- package/dist/widgets/index.d.cts.map +1 -1
- package/dist/widgets/index.d.mts +2 -3
- package/dist/widgets/index.d.mts.map +1 -1
- package/dist/widgets/index.mjs +18 -18
- package/package.json +3 -3
- package/dist/ListWidget-C-jcsCb4.mjs.map +0 -1
- package/dist/ListWidget-RHQ2fQXa.cjs.map +0 -1
- package/dist/NestedWidget-BaRb7Z5r.mjs.map +0 -1
- package/dist/NestedWidget-Dbo3dXEi.cjs.map +0 -1
- package/dist/RecentActivityWidget-BvncOdax.mjs.map +0 -1
- package/dist/RecentActivityWidget-wODng8dt.cjs.map +0 -1
- package/dist/TableWidget-DqAN_2sf.mjs.map +0 -1
- package/dist/TableWidget-iS_DwHOX.cjs.map +0 -1
- /package/dist/{fields-4FC6JUNH.d.mts → fields-BGGlw1MW.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickShareWidget-DXq5lcDn.mjs","names":[],"sources":["../src/widgets/QuickShareWidget.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ShareableItem } from \"@fluid-app/portal-core/types\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport {\n faCopy,\n faCartShopping,\n faImage,\n} from \"@fortawesome/pro-regular-svg-icons\";\n\ntype QuickShareWidgetProps = ComponentProps<\"div\"> & {\n // Resource\n shareableResource?: ShareableItem;\n\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Actions\n showBuyButton?: boolean;\n};\n\nexport function QuickShareWidget({\n // Resource\n shareableResource,\n\n // Title defaults\n titleEnabled = true,\n titleText = \"\",\n titleFontSize = \"2xl\",\n titleColor = \"foreground\",\n\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n // Overlay defaults\n overlayEnabled = true,\n overlayType = \"solid\",\n overlayIntensity = 50,\n\n // Actions defaults\n showBuyButton = false,\n\n className,\n ...props\n}: QuickShareWidgetProps): React.JSX.Element {\n // Determine background styling\n const backgroundImageUrl =\n shareableResource?.image_url || shareableResource?.imageUrl;\n\n // Get share link from resource\n const shareLink = shareableResource?.share_link || \"\";\n const displayUrl = shareLink || \"Select a resource to generate link\";\n\n // Determine title - use provided title or fall back to resource title\n const displayTitle =\n titleText || shareableResource?.title || \"Select a resource to display!\";\n\n // Check if resource is a Product for buy button visibility\n const isProduct =\n shareableResource?.type === \"Product\" ||\n shareableResource?.shareableType === \"Product\";\n const shouldShowBuyButton = showBuyButton && isProduct;\n\n // Copy to clipboard handler\n const handleCopyToClipboard = async () => {\n if (shareLink) {\n try {\n await navigator.clipboard.writeText(shareLink);\n } catch (error) {\n console.error(\"Failed to copy to clipboard:\", error);\n }\n }\n };\n\n return (\n <div\n className={`relative overflow-hidden rounded-${borderRadius} bg-muted text-${textColor} ${className ?? \"\"}`}\n {...props}\n >\n {/* Background Image with Overlay */}\n {backgroundImageUrl ? (\n <div className=\"absolute inset-0\">\n <img\n src={backgroundImageUrl}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n />\n {overlayEnabled && (\n <div\n className={`absolute inset-0 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n ) : (\n <div\n className={`bg-muted absolute inset-0 flex items-center justify-center`}\n >\n <FontAwesomeIcon icon={faImage} className=\"h-16 w-16 opacity-20\" />\n </div>\n )}\n\n {/* Content Container */}\n <div className={`relative flex min-h-[400px] flex-col p-${padding}`}>\n {/* Title Overlay */}\n {titleEnabled && displayTitle && (\n <div className=\"flex flex-1 items-center justify-center\">\n <h2\n className={`text-center text-${titleFontSize} font-semibold text-${titleColor} drop-shadow-lg`}\n >\n {displayTitle}\n </h2>\n </div>\n )}\n\n {/* Bottom Section - QR Code, URL, and Buttons */}\n <div className=\"mt-auto flex flex-col gap-4\">\n <div className=\"flex items-end justify-between gap-4\">\n {/* QR Code */}\n <div className=\"shrink-0 rounded-lg bg-white p-2\">\n <QRCodeSVG\n value={shareLink || \"https://example.com\"}\n size={100}\n level=\"H\"\n />\n </div>\n\n {/* URL Display */}\n <div className=\"min-w-0 flex-1\">\n <p className=\"mb-2 text-sm font-semibold tracking-wide drop-shadow\">\n Your Shareable URL\n </p>\n <div className=\"flex items-center justify-between rounded-md border border-white/20 bg-black/50 p-2 text-sm text-white backdrop-blur\">\n <span className=\"truncate\">{displayUrl}</span>\n <button\n type=\"button\"\n onClick={handleCopyToClipboard}\n className={`ml-2 shrink-0 rounded p-1 transition-colors hover:bg-${accentColor}/20`}\n aria-label=\"Copy link\"\n >\n <FontAwesomeIcon icon={faCopy} className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n </div>\n\n {/* Action Buttons */}\n {/* TODO: Needs button link implmented, once it is uncomment the config for showBuyButton */}\n {shouldShowBuyButton && (\n <div className=\"flex\">\n <button\n type=\"button\"\n className={`flex w-full items-center justify-center gap-2 rounded-lg bg-${accentColor} p-3 font-medium text-${accentColor}-foreground transition-all hover:bg-${accentColor}-500`}\n >\n <FontAwesomeIcon icon={faCartShopping} className=\"h-4 w-4\" />\n <span>Buy</span>\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const quickShareWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickShareWidget\",\n displayName: \"Quick Share Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Resource\n {\n key: \"shareableResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select the content to generate a share link for\",\n allowedTypes: [\"Product\", \"Page\", \"EnrollmentPack\", \"Medium\", \"Library\"],\n tab: \"styling\",\n group: \"Content\",\n },\n\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Display a title overlay on the widget\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Custom title text (defaults to resource title if empty)\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title text\",\n defaultValue: \"2xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title text\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Actions Group\n // {\n // key: \"showBuyButton\",\n // label: \"Show Buy Button\",\n // type: \"boolean\",\n // description: \"Display the buy button (only visible for Product type)\",\n // defaultValue: false,\n // tab: \"styling\",\n // group: \"Actions\",\n // },\n\n // Styling Tab - Design Group\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for the widget\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color for accent elements and buy button\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add background overlay for text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay to add to the background\",\n defaultValue: \"solid\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay background (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget content\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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Ac;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
|
|
1
|
+
{"version":3,"file":"QuickShareWidget-CdvP1eRx.mjs","names":[],"sources":["../src/widgets/QuickShareWidget.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ShareableItem } from \"@fluid-app/portal-core/types\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport {\n faCopy,\n faCartShopping,\n faImage,\n} from \"@fortawesome/pro-regular-svg-icons\";\n\ntype QuickShareWidgetProps = ComponentProps<\"div\"> & {\n // Resource\n shareableResource?: ShareableItem;\n\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Actions\n showBuyButton?: boolean;\n};\n\nexport function QuickShareWidget({\n // Resource\n shareableResource,\n\n // Title defaults\n titleEnabled = true,\n titleText = \"\",\n titleFontSize = \"2xl\",\n titleColor = \"foreground\",\n\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n // Overlay defaults\n overlayEnabled = true,\n overlayType = \"solid\",\n overlayIntensity = 50,\n\n // Actions defaults\n showBuyButton = false,\n\n className,\n ...props\n}: QuickShareWidgetProps): React.JSX.Element {\n // Determine background styling\n const backgroundImageUrl =\n shareableResource?.image_url || shareableResource?.imageUrl;\n\n // Get share link from resource\n const shareLink = shareableResource?.share_link || \"\";\n const displayUrl = shareLink || \"Select a resource to generate link\";\n\n // Determine title - use provided title or fall back to resource title\n const displayTitle =\n titleText || shareableResource?.title || \"Select a resource to display!\";\n\n // Check if resource is a Product for buy button visibility\n const isProduct =\n shareableResource?.type === \"Product\" ||\n shareableResource?.shareableType === \"Product\";\n const shouldShowBuyButton = showBuyButton && isProduct;\n\n // Copy to clipboard handler\n const handleCopyToClipboard = async () => {\n if (shareLink) {\n try {\n await navigator.clipboard.writeText(shareLink);\n } catch (error) {\n console.error(\"Failed to copy to clipboard:\", error);\n }\n }\n };\n\n return (\n <div\n className={`relative overflow-hidden rounded-${borderRadius} bg-muted text-${textColor} ${className ?? \"\"}`}\n {...props}\n >\n {/* Background Image with Overlay */}\n {backgroundImageUrl ? (\n <div className=\"absolute inset-0\">\n <img\n src={backgroundImageUrl}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n />\n {overlayEnabled && (\n <div\n className={`absolute inset-0 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n ) : (\n <div\n className={`bg-muted absolute inset-0 flex items-center justify-center`}\n >\n <FontAwesomeIcon icon={faImage} className=\"h-16 w-16 opacity-20\" />\n </div>\n )}\n\n {/* Content Container */}\n <div className={`relative flex min-h-[400px] flex-col p-${padding}`}>\n {/* Title Overlay */}\n {titleEnabled && displayTitle && (\n <div className=\"flex flex-1 items-center justify-center\">\n <h2\n className={`text-center text-${titleFontSize} font-semibold text-${titleColor} drop-shadow-lg`}\n >\n {displayTitle}\n </h2>\n </div>\n )}\n\n {/* Bottom Section - QR Code, URL, and Buttons */}\n <div className=\"mt-auto flex flex-col gap-4\">\n <div className=\"flex items-end justify-between gap-4\">\n {/* QR Code */}\n <div className=\"shrink-0 rounded-lg bg-white p-2\">\n <QRCodeSVG\n value={shareLink || \"https://example.com\"}\n size={100}\n level=\"H\"\n />\n </div>\n\n {/* URL Display */}\n <div className=\"min-w-0 flex-1\">\n <p className=\"mb-2 text-sm font-semibold tracking-wide drop-shadow\">\n Your Shareable URL\n </p>\n <div className=\"flex items-center justify-between rounded-md border border-white/20 bg-black/50 p-2 text-sm text-white backdrop-blur\">\n <span className=\"truncate\">{displayUrl}</span>\n <button\n type=\"button\"\n onClick={handleCopyToClipboard}\n className={`ml-2 shrink-0 rounded p-1 transition-colors hover:bg-${accentColor}/20`}\n aria-label=\"Copy link\"\n >\n <FontAwesomeIcon icon={faCopy} className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n </div>\n\n {/* Action Buttons */}\n {/* TODO: Needs button link implmented, once it is uncomment the config for showBuyButton */}\n {shouldShowBuyButton && (\n <div className=\"flex\">\n <button\n type=\"button\"\n className={`flex w-full items-center justify-center gap-2 rounded-lg bg-${accentColor} p-3 font-medium text-${accentColor}-foreground transition-all hover:bg-${accentColor}-500`}\n >\n <FontAwesomeIcon icon={faCartShopping} className=\"h-4 w-4\" />\n <span>Buy</span>\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const quickShareWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickShareWidget\",\n displayName: \"Quick Share Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Resource\n {\n key: \"shareableResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select the content to generate a share link for\",\n allowedTypes: [\"Product\", \"Page\", \"EnrollmentPack\", \"Medium\", \"Library\"],\n tab: \"styling\",\n group: \"Content\",\n },\n\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Display a title overlay on the widget\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Custom title text (defaults to resource title if empty)\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title text\",\n defaultValue: \"2xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title text\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Actions Group\n // {\n // key: \"showBuyButton\",\n // label: \"Show Buy Button\",\n // type: \"boolean\",\n // description: \"Display the buy button (only visible for Product type)\",\n // defaultValue: false,\n // tab: \"styling\",\n // group: \"Actions\",\n // },\n\n // Styling Tab - Design Group\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for the widget\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color for accent elements and buy button\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add background overlay for text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay to add to the background\",\n defaultValue: \"solid\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay background (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget content\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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Ac;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickShareWidget-DWvgEy74.cjs","names":["FontAwesomeIcon","faImage","QRCodeSVG","faCopy","faCartShopping"],"sources":["../src/widgets/QuickShareWidget.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ShareableItem } from \"@fluid-app/portal-core/types\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport {\n faCopy,\n faCartShopping,\n faImage,\n} from \"@fortawesome/pro-regular-svg-icons\";\n\ntype QuickShareWidgetProps = ComponentProps<\"div\"> & {\n // Resource\n shareableResource?: ShareableItem;\n\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Actions\n showBuyButton?: boolean;\n};\n\nexport function QuickShareWidget({\n // Resource\n shareableResource,\n\n // Title defaults\n titleEnabled = true,\n titleText = \"\",\n titleFontSize = \"2xl\",\n titleColor = \"foreground\",\n\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n // Overlay defaults\n overlayEnabled = true,\n overlayType = \"solid\",\n overlayIntensity = 50,\n\n // Actions defaults\n showBuyButton = false,\n\n className,\n ...props\n}: QuickShareWidgetProps): React.JSX.Element {\n // Determine background styling\n const backgroundImageUrl =\n shareableResource?.image_url || shareableResource?.imageUrl;\n\n // Get share link from resource\n const shareLink = shareableResource?.share_link || \"\";\n const displayUrl = shareLink || \"Select a resource to generate link\";\n\n // Determine title - use provided title or fall back to resource title\n const displayTitle =\n titleText || shareableResource?.title || \"Select a resource to display!\";\n\n // Check if resource is a Product for buy button visibility\n const isProduct =\n shareableResource?.type === \"Product\" ||\n shareableResource?.shareableType === \"Product\";\n const shouldShowBuyButton = showBuyButton && isProduct;\n\n // Copy to clipboard handler\n const handleCopyToClipboard = async () => {\n if (shareLink) {\n try {\n await navigator.clipboard.writeText(shareLink);\n } catch (error) {\n console.error(\"Failed to copy to clipboard:\", error);\n }\n }\n };\n\n return (\n <div\n className={`relative overflow-hidden rounded-${borderRadius} bg-muted text-${textColor} ${className ?? \"\"}`}\n {...props}\n >\n {/* Background Image with Overlay */}\n {backgroundImageUrl ? (\n <div className=\"absolute inset-0\">\n <img\n src={backgroundImageUrl}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n />\n {overlayEnabled && (\n <div\n className={`absolute inset-0 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n ) : (\n <div\n className={`bg-muted absolute inset-0 flex items-center justify-center`}\n >\n <FontAwesomeIcon icon={faImage} className=\"h-16 w-16 opacity-20\" />\n </div>\n )}\n\n {/* Content Container */}\n <div className={`relative flex min-h-[400px] flex-col p-${padding}`}>\n {/* Title Overlay */}\n {titleEnabled && displayTitle && (\n <div className=\"flex flex-1 items-center justify-center\">\n <h2\n className={`text-center text-${titleFontSize} font-semibold text-${titleColor} drop-shadow-lg`}\n >\n {displayTitle}\n </h2>\n </div>\n )}\n\n {/* Bottom Section - QR Code, URL, and Buttons */}\n <div className=\"mt-auto flex flex-col gap-4\">\n <div className=\"flex items-end justify-between gap-4\">\n {/* QR Code */}\n <div className=\"shrink-0 rounded-lg bg-white p-2\">\n <QRCodeSVG\n value={shareLink || \"https://example.com\"}\n size={100}\n level=\"H\"\n />\n </div>\n\n {/* URL Display */}\n <div className=\"min-w-0 flex-1\">\n <p className=\"mb-2 text-sm font-semibold tracking-wide drop-shadow\">\n Your Shareable URL\n </p>\n <div className=\"flex items-center justify-between rounded-md border border-white/20 bg-black/50 p-2 text-sm text-white backdrop-blur\">\n <span className=\"truncate\">{displayUrl}</span>\n <button\n type=\"button\"\n onClick={handleCopyToClipboard}\n className={`ml-2 shrink-0 rounded p-1 transition-colors hover:bg-${accentColor}/20`}\n aria-label=\"Copy link\"\n >\n <FontAwesomeIcon icon={faCopy} className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n </div>\n\n {/* Action Buttons */}\n {/* TODO: Needs button link implmented, once it is uncomment the config for showBuyButton */}\n {shouldShowBuyButton && (\n <div className=\"flex\">\n <button\n type=\"button\"\n className={`flex w-full items-center justify-center gap-2 rounded-lg bg-${accentColor} p-3 font-medium text-${accentColor}-foreground transition-all hover:bg-${accentColor}-500`}\n >\n <FontAwesomeIcon icon={faCartShopping} className=\"h-4 w-4\" />\n <span>Buy</span>\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const quickShareWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickShareWidget\",\n displayName: \"Quick Share Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Resource\n {\n key: \"shareableResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select the content to generate a share link for\",\n allowedTypes: [\"Product\", \"Page\", \"EnrollmentPack\", \"Medium\", \"Library\"],\n tab: \"styling\",\n group: \"Content\",\n },\n\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Display a title overlay on the widget\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Custom title text (defaults to resource title if empty)\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title text\",\n defaultValue: \"2xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title text\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Actions Group\n // {\n // key: \"showBuyButton\",\n // label: \"Show Buy Button\",\n // type: \"boolean\",\n // description: \"Display the buy button (only visible for Product type)\",\n // defaultValue: false,\n // tab: \"styling\",\n // group: \"Actions\",\n // },\n\n // Styling Tab - Design Group\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for the widget\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color for accent elements and buy button\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add background overlay for text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay to add to the background\",\n defaultValue: \"solid\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay background (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget content\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;0DACgB;GACf,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;uDACY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;uDAcY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;uDACY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;yDACe;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;8DACmB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
|
|
1
|
+
{"version":3,"file":"QuickShareWidget-Dg2OcMYg.cjs","names":["FontAwesomeIcon","faImage","QRCodeSVG","faCopy","faCartShopping"],"sources":["../src/widgets/QuickShareWidget.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ShareableItem } from \"@fluid-app/portal-core/types\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport {\n faCopy,\n faCartShopping,\n faImage,\n} from \"@fortawesome/pro-regular-svg-icons\";\n\ntype QuickShareWidgetProps = ComponentProps<\"div\"> & {\n // Resource\n shareableResource?: ShareableItem;\n\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Actions\n showBuyButton?: boolean;\n};\n\nexport function QuickShareWidget({\n // Resource\n shareableResource,\n\n // Title defaults\n titleEnabled = true,\n titleText = \"\",\n titleFontSize = \"2xl\",\n titleColor = \"foreground\",\n\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n // Overlay defaults\n overlayEnabled = true,\n overlayType = \"solid\",\n overlayIntensity = 50,\n\n // Actions defaults\n showBuyButton = false,\n\n className,\n ...props\n}: QuickShareWidgetProps): React.JSX.Element {\n // Determine background styling\n const backgroundImageUrl =\n shareableResource?.image_url || shareableResource?.imageUrl;\n\n // Get share link from resource\n const shareLink = shareableResource?.share_link || \"\";\n const displayUrl = shareLink || \"Select a resource to generate link\";\n\n // Determine title - use provided title or fall back to resource title\n const displayTitle =\n titleText || shareableResource?.title || \"Select a resource to display!\";\n\n // Check if resource is a Product for buy button visibility\n const isProduct =\n shareableResource?.type === \"Product\" ||\n shareableResource?.shareableType === \"Product\";\n const shouldShowBuyButton = showBuyButton && isProduct;\n\n // Copy to clipboard handler\n const handleCopyToClipboard = async () => {\n if (shareLink) {\n try {\n await navigator.clipboard.writeText(shareLink);\n } catch (error) {\n console.error(\"Failed to copy to clipboard:\", error);\n }\n }\n };\n\n return (\n <div\n className={`relative overflow-hidden rounded-${borderRadius} bg-muted text-${textColor} ${className ?? \"\"}`}\n {...props}\n >\n {/* Background Image with Overlay */}\n {backgroundImageUrl ? (\n <div className=\"absolute inset-0\">\n <img\n src={backgroundImageUrl}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n />\n {overlayEnabled && (\n <div\n className={`absolute inset-0 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n ) : (\n <div\n className={`bg-muted absolute inset-0 flex items-center justify-center`}\n >\n <FontAwesomeIcon icon={faImage} className=\"h-16 w-16 opacity-20\" />\n </div>\n )}\n\n {/* Content Container */}\n <div className={`relative flex min-h-[400px] flex-col p-${padding}`}>\n {/* Title Overlay */}\n {titleEnabled && displayTitle && (\n <div className=\"flex flex-1 items-center justify-center\">\n <h2\n className={`text-center text-${titleFontSize} font-semibold text-${titleColor} drop-shadow-lg`}\n >\n {displayTitle}\n </h2>\n </div>\n )}\n\n {/* Bottom Section - QR Code, URL, and Buttons */}\n <div className=\"mt-auto flex flex-col gap-4\">\n <div className=\"flex items-end justify-between gap-4\">\n {/* QR Code */}\n <div className=\"shrink-0 rounded-lg bg-white p-2\">\n <QRCodeSVG\n value={shareLink || \"https://example.com\"}\n size={100}\n level=\"H\"\n />\n </div>\n\n {/* URL Display */}\n <div className=\"min-w-0 flex-1\">\n <p className=\"mb-2 text-sm font-semibold tracking-wide drop-shadow\">\n Your Shareable URL\n </p>\n <div className=\"flex items-center justify-between rounded-md border border-white/20 bg-black/50 p-2 text-sm text-white backdrop-blur\">\n <span className=\"truncate\">{displayUrl}</span>\n <button\n type=\"button\"\n onClick={handleCopyToClipboard}\n className={`ml-2 shrink-0 rounded p-1 transition-colors hover:bg-${accentColor}/20`}\n aria-label=\"Copy link\"\n >\n <FontAwesomeIcon icon={faCopy} className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n </div>\n\n {/* Action Buttons */}\n {/* TODO: Needs button link implmented, once it is uncomment the config for showBuyButton */}\n {shouldShowBuyButton && (\n <div className=\"flex\">\n <button\n type=\"button\"\n className={`flex w-full items-center justify-center gap-2 rounded-lg bg-${accentColor} p-3 font-medium text-${accentColor}-foreground transition-all hover:bg-${accentColor}-500`}\n >\n <FontAwesomeIcon icon={faCartShopping} className=\"h-4 w-4\" />\n <span>Buy</span>\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const quickShareWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickShareWidget\",\n displayName: \"Quick Share Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Resource\n {\n key: \"shareableResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select the content to generate a share link for\",\n allowedTypes: [\"Product\", \"Page\", \"EnrollmentPack\", \"Medium\", \"Library\"],\n tab: \"styling\",\n group: \"Content\",\n },\n\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Display a title overlay on the widget\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Custom title text (defaults to resource title if empty)\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title text\",\n defaultValue: \"2xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title text\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Actions Group\n // {\n // key: \"showBuyButton\",\n // label: \"Show Buy Button\",\n // type: \"boolean\",\n // description: \"Display the buy button (only visible for Product type)\",\n // defaultValue: false,\n // tab: \"styling\",\n // group: \"Actions\",\n // },\n\n // Styling Tab - Design Group\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for the widget\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color for accent elements and buy button\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add background overlay for text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay to add to the background\",\n defaultValue: \"solid\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay background (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget content\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;0DACgB;GACf,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;uDACY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;uDAcY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;uDACY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;yDACe;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;8DACmB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
|
|
@@ -8,6 +8,7 @@ import { useDataSourceConfig } from "@fluid-app/portal-core/data-sources/context
|
|
|
8
8
|
import { useWidgetPreviewContext } from "@fluid-app/portal-core/data-sources/preview-context";
|
|
9
9
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
10
10
|
import { faBell, faCalendar, faCartShopping, faComment, faEye, faPlay, faSquareCheck, faStar, faTrophy, faUser, faUserPlus } from "@fortawesome/pro-regular-svg-icons";
|
|
11
|
+
import DOMPurify from "dompurify";
|
|
11
12
|
//#region src/hooks/use-activities.preview.ts
|
|
12
13
|
const now = /* @__PURE__ */ new Date();
|
|
13
14
|
function minutesAgo(minutes) {
|
|
@@ -195,7 +196,16 @@ function ActivityFeedItem({ activity, accentColor, textColor }) {
|
|
|
195
196
|
children: activity.userName
|
|
196
197
|
}),
|
|
197
198
|
" ",
|
|
198
|
-
activity.targetName
|
|
199
|
+
/* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(activity.targetName, {
|
|
200
|
+
ALLOWED_TAGS: [
|
|
201
|
+
"br",
|
|
202
|
+
"strong",
|
|
203
|
+
"em",
|
|
204
|
+
"b",
|
|
205
|
+
"i"
|
|
206
|
+
],
|
|
207
|
+
ALLOWED_ATTR: []
|
|
208
|
+
}) } })
|
|
199
209
|
]
|
|
200
210
|
})]
|
|
201
211
|
})]
|
|
@@ -388,4 +398,4 @@ const recentActivityWidgetPropertySchema = {
|
|
|
388
398
|
//#endregion
|
|
389
399
|
export { RecentActivityWidget_exports as n, recentActivityWidgetPropertySchema as r, RecentActivityWidget as t };
|
|
390
400
|
|
|
391
|
-
//# sourceMappingURL=RecentActivityWidget-
|
|
401
|
+
//# sourceMappingURL=RecentActivityWidget-YD-2z7oN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecentActivityWidget-YD-2z7oN.mjs","names":[],"sources":["../src/hooks/use-activities.preview.ts","../src/hooks/use-activities.ts","../src/widgets/RecentActivityWidget.tsx"],"sourcesContent":["import type { Activity } from \"./use-activities.types\";\n\nconst now = new Date();\n\nfunction minutesAgo(minutes: number): string {\n return new Date(now.getTime() - minutes * 60_000).toISOString();\n}\n\nexport const PREVIEW_DATA: Activity[] = [\n {\n id: 1,\n userName: \"Sarah Johnson\",\n avatarUrl: null,\n activityType: \"Order Placed\",\n targetName: \"Wellness Starter Kit\",\n timestamp: minutesAgo(12),\n slug: \"order_placed\",\n },\n {\n id: 2,\n userName: \"Mike Chen\",\n avatarUrl: null,\n activityType: \"New Lead\",\n targetName: \"Signed up from Instagram link\",\n timestamp: minutesAgo(45),\n slug: \"new_lead\",\n },\n {\n id: 3,\n userName: \"Visitor from Austin, TX\",\n avatarUrl: null,\n activityType: \"Page Views\",\n targetName: \"Viewed product catalog (3 pages)\",\n timestamp: minutesAgo(90),\n slug: \"page_views\",\n },\n {\n id: 4,\n userName: \"Lisa Park\",\n avatarUrl: null,\n activityType: \"Video Complete\",\n targetName: \"Watched: Getting Started Guide\",\n timestamp: minutesAgo(180),\n slug: \"video_complete\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useDataSourceConfig } from \"@fluid-app/portal-core/data-sources/context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-core/data-sources/preview-context\";\nimport { PREVIEW_DATA } from \"./use-activities.preview\";\nimport type {\n Activity,\n ActivityContact,\n ActivityVisitor,\n ApiActivity,\n} from \"./use-activities.types\";\n\nexport type {\n ActivityContact,\n ActivityVisitor,\n ActivitySlug,\n ApiActivity,\n Activity,\n} from \"./use-activities.types\";\n\ntype PaginationInfo = {\n current: number;\n previous: number | null;\n next: number | null;\n per_page: number;\n pages: number;\n count: number;\n};\n\ntype ApiResponse = [{ pagination: PaginationInfo }, { items: ApiActivity[] }];\n\nexport function useActivities(): UseQueryResult<Activity[], Error> {\n const { baseUrl, getApiHeaders } = useDataSourceConfig();\n const { isPreview } = useWidgetPreviewContext();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"activities\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: async ({ signal }): Promise<Activity[]> => {\n const url = baseUrl\n ? `${baseUrl}/v1.1/activities.json`\n : \"/v1.1/activities.json\";\n const response = await fetch(url, {\n headers: {\n \"content-type\": \"application/json\",\n ...getApiHeaders?.(),\n },\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch activities: ${response.status}`);\n }\n\n const data: ApiResponse = await response.json();\n return transformActivities(data);\n },\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n\n// Transform and format helpers\nfunction getUserName(\n contact: ActivityContact | null,\n visitor: ActivityVisitor | null,\n): string {\n if (contact?.full_name) {\n return contact.full_name;\n }\n if (contact?.first_name && contact?.last_name) {\n return `${contact.first_name} ${contact.last_name}`;\n }\n if (visitor?.city && visitor?.state) {\n return `Visitor from ${visitor.city}, ${visitor.state}`;\n }\n return \"Unknown Visitor\";\n}\n\nfunction transformActivities(rawData: ApiResponse): Activity[] {\n const itemsObj = rawData[1];\n if (!itemsObj?.items) return [];\n\n return itemsObj.items\n .map((activity) => ({\n id: activity.id,\n userName: getUserName(activity.contact, activity.visitor),\n avatarUrl: activity.contact?.avatar_url ?? null,\n activityType: formatActivityType(activity.slug),\n targetName: activity.description || activity.title,\n timestamp: activity.created_at,\n slug: activity.slug,\n }))\n .sort(\n (a, b) =>\n new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n );\n}\n\nfunction formatActivityType(slug: string): string {\n return slug\n .split(\"_\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n","import DOMPurify from \"dompurify\";\nimport { useMemo, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport {\n useActivities,\n type Activity,\n type ActivitySlug,\n} from \"../hooks/use-activities\";\nimport { ErrorState } from \"../components/error-state\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport type { IconDefinition } from \"@fortawesome/fontawesome-svg-core\";\nimport {\n faBell,\n faCalendar,\n faSquareCheck,\n faEye,\n faComment,\n faPlay,\n faCartShopping,\n faStar,\n faTrophy,\n faUser,\n faUserPlus,\n} from \"@fortawesome/pro-regular-svg-icons\";\n\n// Format timestamp to time string\nconst formatTimestamp = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n });\n};\n\n// Format date for grouping header\nconst formatDateHeader = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toLocaleDateString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n });\n};\n\n// Get date string for grouping (without time)\nconst getDateKey = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toISOString().split(\"T\")[0] ?? timestamp;\n};\n\n// Group activities by date\nconst groupActivitiesByDate = (\n activities: Activity[],\n): Map<string, Activity[]> => {\n const grouped = new Map<string, Activity[]>();\n\n for (const activity of activities) {\n const dateKey = getDateKey(activity.timestamp);\n const existing = grouped.get(dateKey);\n if (existing) {\n existing.push(activity);\n } else {\n grouped.set(dateKey, [activity]);\n }\n }\n\n return grouped;\n};\n\n// Activity slug to icon mapping\nconst ACTIVITY_ICON_MAP: Record<ActivitySlug, IconDefinition> = {\n // Orders/Cart\n order_placed: faCartShopping,\n abandoned_cart: faCartShopping,\n cart_items_added: faCartShopping,\n new_cart_items_added: faCartShopping,\n // Messages\n direct_message: faComment,\n comment_reply: faComment,\n message_received: faComment,\n message_sent: faComment,\n // Video\n video: faPlay,\n video_complete: faPlay,\n video_contact: faPlay,\n video_complete_contact: faPlay,\n // Leads\n new_lead: faUserPlus,\n page_views_contact: faUserPlus,\n smart_link_clicked: faUserPlus,\n // Page Views\n page_views: faEye,\n // Events\n upcoming_event: faCalendar,\n // Reviews\n review_left: faStar,\n // Tasks\n tasks: faSquareCheck,\n // Announcements\n announcements: faBell,\n // Fantasy\n fantasy_point: faTrophy,\n};\n\nconst getActivityIcon = (slug: ActivitySlug) =>\n ACTIVITY_ICON_MAP[slug] ?? faUser;\n\n// Activity feed item component\ntype ActivityFeedItemProps = {\n activity: Activity;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n};\n\nfunction ActivityFeedItem({\n activity,\n accentColor,\n textColor,\n}: ActivityFeedItemProps) {\n const icon = getActivityIcon(activity.slug);\n\n return (\n <div className=\"flex w-full items-start gap-1.5\">\n {/* Avatar */}\n <div className=\"shrink-0\">\n {activity.avatarUrl ? (\n <div className=\"relative size-8 overflow-hidden rounded-full\">\n <img\n src={activity.avatarUrl}\n alt={activity.userName}\n className=\"size-full object-cover\"\n />\n <div className=\"border-foreground/[0.08] absolute inset-0 rounded-full border\" />\n </div>\n ) : (\n <div\n className={`bg-muted flex size-8 items-center justify-center rounded-full`}\n >\n <FontAwesomeIcon\n icon={icon}\n className={`size-3.5 text-${textColor} opacity-60`}\n />\n </div>\n )}\n </div>\n\n {/* Content */}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex w-full items-center gap-1.5\">\n <p\n className={`flex-1 text-base font-semibold text-${textColor} truncate`}\n >\n {activity.activityType}\n </p>\n <p className={`text-xs text-${textColor} shrink-0 opacity-50`}>\n {formatTimestamp(activity.timestamp)}\n </p>\n </div>\n <p className={`text-sm text-${textColor} opacity-80`}>\n <span className={`font-medium text-${accentColor}`}>\n {activity.userName}\n </span>{\" \"}\n <span\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(activity.targetName, {\n ALLOWED_TAGS: [\"br\", \"strong\", \"em\", \"b\", \"i\"],\n ALLOWED_ATTR: [],\n }),\n }}\n />\n </p>\n </div>\n </div>\n );\n}\n\ntype RecentActivityWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Activity settings\n maxItemsToShow?: number;\n};\n\nexport function RecentActivityWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"Recent Activity\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n // Activity defaults\n maxItemsToShow = 5,\n\n className,\n ...props\n}: RecentActivityWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n const { data: activities = [], isLoading, isError } = useActivities();\n\n const groupedActivities = useMemo(\n () => groupActivitiesByDate(activities),\n [activities],\n );\n\n const totalCount = Math.min(activities.length, maxItemsToShow);\n\n // Get activities to display (limited by maxItemsToShow)\n const activitiesToShow = useMemo(() => {\n const result: { date: string; items: Activity[] }[] = [];\n let count = 0;\n\n for (const [dateKey, items] of groupedActivities) {\n if (count >= maxItemsToShow) break;\n\n const remainingSlots = maxItemsToShow - count;\n const itemsToAdd = items.slice(0, remainingSlots);\n\n if (itemsToAdd.length > 0) {\n result.push({\n date: formatDateHeader(items[0]?.timestamp ?? dateKey),\n items: itemsToAdd,\n });\n count += itemsToAdd.length;\n }\n }\n\n return result;\n }, [groupedActivities, maxItemsToShow]);\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} border-muted border ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className={`p-${padding} flex flex-col gap-2`}>\n {/* Header */}\n {titleEnabled && titleText && (\n <div className=\"flex w-full items-start gap-2\">\n <h2\n className={`flex-1 text-${titleFontSize} font-bold text-${titleColor}`}\n >\n {titleText}\n </h2>\n {!isLoading && (\n <span\n className={`text-4xl font-bold text-${textColor} leading-none`}\n >\n {totalCount.toString().padStart(2, \"0\")}\n </span>\n )}\n </div>\n )}\n\n {/* Loading state */}\n {isLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n /* Error state */\n <ErrorState />\n ) : activities.length === 0 ? (\n /* Empty state */\n <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-2\">\n <FontAwesomeIcon\n icon={faUser}\n className={`size-12 text-${textColor} opacity-30`}\n />\n <p\n className={`text-base font-semibold text-${textColor} opacity-50`}\n >\n No Activity To Report\n </p>\n <p className={`text-sm text-${textColor} opacity-40`}>\n You'll Do Great!\n </p>\n </div>\n ) : (\n /* Activity list */\n <div className=\"flex flex-col gap-4\">\n {activitiesToShow.map((group, groupIndex) => (\n <div key={groupIndex} className=\"flex flex-col gap-4\">\n {/* Date header */}\n <p className={`text-base font-semibold text-${textColor}`}>\n {group.date}\n </p>\n\n {/* Activity items */}\n <div className=\"flex flex-col gap-4\">\n {group.items.map((activity) => (\n <ActivityFeedItem\n key={activity.id}\n activity={activity}\n accentColor={accentColor}\n textColor={textColor}\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport const recentActivityWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"RecentActivityWidget\",\n displayName: \"Recent Activity Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the activity feed\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the activity feed\",\n defaultValue: \"Recent Activity\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for activity content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color used for links and highlights\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n\n // Styling Tab - Display Group\n {\n key: \"maxItemsToShow\",\n label: \"Max Items\",\n type: \"number\",\n description: \"Maximum number of activity items to display\",\n defaultValue: 5,\n tab: \"styling\",\n group: \"Display\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@ let _fluid_app_portal_core_data_sources_context = require("@fluid-app/portal-cor
|
|
|
7
7
|
let _fluid_app_portal_core_data_sources_preview_context = require("@fluid-app/portal-core/data-sources/preview-context");
|
|
8
8
|
let _fortawesome_react_fontawesome = require("@fortawesome/react-fontawesome");
|
|
9
9
|
let _fortawesome_pro_regular_svg_icons = require("@fortawesome/pro-regular-svg-icons");
|
|
10
|
+
let dompurify = require("dompurify");
|
|
11
|
+
dompurify = require_chunk.__toESM(dompurify);
|
|
10
12
|
let _fluid_app_portal_core_registries = require("@fluid-app/portal-core/registries");
|
|
11
13
|
//#region src/hooks/use-activities.preview.ts
|
|
12
14
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -195,7 +197,16 @@ function ActivityFeedItem({ activity, accentColor, textColor }) {
|
|
|
195
197
|
children: activity.userName
|
|
196
198
|
}),
|
|
197
199
|
" ",
|
|
198
|
-
activity.targetName
|
|
200
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { dangerouslySetInnerHTML: { __html: dompurify.default.sanitize(activity.targetName, {
|
|
201
|
+
ALLOWED_TAGS: [
|
|
202
|
+
"br",
|
|
203
|
+
"strong",
|
|
204
|
+
"em",
|
|
205
|
+
"b",
|
|
206
|
+
"i"
|
|
207
|
+
],
|
|
208
|
+
ALLOWED_ATTR: []
|
|
209
|
+
}) } })
|
|
199
210
|
]
|
|
200
211
|
})]
|
|
201
212
|
})]
|
|
@@ -405,4 +416,4 @@ Object.defineProperty(exports, "recentActivityWidgetPropertySchema", {
|
|
|
405
416
|
}
|
|
406
417
|
});
|
|
407
418
|
|
|
408
|
-
//# sourceMappingURL=RecentActivityWidget-
|
|
419
|
+
//# sourceMappingURL=RecentActivityWidget-_3h0KmQP.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecentActivityWidget-_3h0KmQP.cjs","names":["faCartShopping","faComment","faPlay","faUserPlus","faEye","faCalendar","faStar","faSquareCheck","faBell","faTrophy","faUser","FontAwesomeIcon","DOMPurify","ErrorState"],"sources":["../src/hooks/use-activities.preview.ts","../src/hooks/use-activities.ts","../src/widgets/RecentActivityWidget.tsx"],"sourcesContent":["import type { Activity } from \"./use-activities.types\";\n\nconst now = new Date();\n\nfunction minutesAgo(minutes: number): string {\n return new Date(now.getTime() - minutes * 60_000).toISOString();\n}\n\nexport const PREVIEW_DATA: Activity[] = [\n {\n id: 1,\n userName: \"Sarah Johnson\",\n avatarUrl: null,\n activityType: \"Order Placed\",\n targetName: \"Wellness Starter Kit\",\n timestamp: minutesAgo(12),\n slug: \"order_placed\",\n },\n {\n id: 2,\n userName: \"Mike Chen\",\n avatarUrl: null,\n activityType: \"New Lead\",\n targetName: \"Signed up from Instagram link\",\n timestamp: minutesAgo(45),\n slug: \"new_lead\",\n },\n {\n id: 3,\n userName: \"Visitor from Austin, TX\",\n avatarUrl: null,\n activityType: \"Page Views\",\n targetName: \"Viewed product catalog (3 pages)\",\n timestamp: minutesAgo(90),\n slug: \"page_views\",\n },\n {\n id: 4,\n userName: \"Lisa Park\",\n avatarUrl: null,\n activityType: \"Video Complete\",\n targetName: \"Watched: Getting Started Guide\",\n timestamp: minutesAgo(180),\n slug: \"video_complete\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useDataSourceConfig } from \"@fluid-app/portal-core/data-sources/context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-core/data-sources/preview-context\";\nimport { PREVIEW_DATA } from \"./use-activities.preview\";\nimport type {\n Activity,\n ActivityContact,\n ActivityVisitor,\n ApiActivity,\n} from \"./use-activities.types\";\n\nexport type {\n ActivityContact,\n ActivityVisitor,\n ActivitySlug,\n ApiActivity,\n Activity,\n} from \"./use-activities.types\";\n\ntype PaginationInfo = {\n current: number;\n previous: number | null;\n next: number | null;\n per_page: number;\n pages: number;\n count: number;\n};\n\ntype ApiResponse = [{ pagination: PaginationInfo }, { items: ApiActivity[] }];\n\nexport function useActivities(): UseQueryResult<Activity[], Error> {\n const { baseUrl, getApiHeaders } = useDataSourceConfig();\n const { isPreview } = useWidgetPreviewContext();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"activities\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: async ({ signal }): Promise<Activity[]> => {\n const url = baseUrl\n ? `${baseUrl}/v1.1/activities.json`\n : \"/v1.1/activities.json\";\n const response = await fetch(url, {\n headers: {\n \"content-type\": \"application/json\",\n ...getApiHeaders?.(),\n },\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch activities: ${response.status}`);\n }\n\n const data: ApiResponse = await response.json();\n return transformActivities(data);\n },\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n\n// Transform and format helpers\nfunction getUserName(\n contact: ActivityContact | null,\n visitor: ActivityVisitor | null,\n): string {\n if (contact?.full_name) {\n return contact.full_name;\n }\n if (contact?.first_name && contact?.last_name) {\n return `${contact.first_name} ${contact.last_name}`;\n }\n if (visitor?.city && visitor?.state) {\n return `Visitor from ${visitor.city}, ${visitor.state}`;\n }\n return \"Unknown Visitor\";\n}\n\nfunction transformActivities(rawData: ApiResponse): Activity[] {\n const itemsObj = rawData[1];\n if (!itemsObj?.items) return [];\n\n return itemsObj.items\n .map((activity) => ({\n id: activity.id,\n userName: getUserName(activity.contact, activity.visitor),\n avatarUrl: activity.contact?.avatar_url ?? null,\n activityType: formatActivityType(activity.slug),\n targetName: activity.description || activity.title,\n timestamp: activity.created_at,\n slug: activity.slug,\n }))\n .sort(\n (a, b) =>\n new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n );\n}\n\nfunction formatActivityType(slug: string): string {\n return slug\n .split(\"_\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n","import DOMPurify from \"dompurify\";\nimport { useMemo, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport {\n useActivities,\n type Activity,\n type ActivitySlug,\n} from \"../hooks/use-activities\";\nimport { ErrorState } from \"../components/error-state\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport type { IconDefinition } from \"@fortawesome/fontawesome-svg-core\";\nimport {\n faBell,\n faCalendar,\n faSquareCheck,\n faEye,\n faComment,\n faPlay,\n faCartShopping,\n faStar,\n faTrophy,\n faUser,\n faUserPlus,\n} from \"@fortawesome/pro-regular-svg-icons\";\n\n// Format timestamp to time string\nconst formatTimestamp = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n });\n};\n\n// Format date for grouping header\nconst formatDateHeader = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toLocaleDateString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n });\n};\n\n// Get date string for grouping (without time)\nconst getDateKey = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toISOString().split(\"T\")[0] ?? timestamp;\n};\n\n// Group activities by date\nconst groupActivitiesByDate = (\n activities: Activity[],\n): Map<string, Activity[]> => {\n const grouped = new Map<string, Activity[]>();\n\n for (const activity of activities) {\n const dateKey = getDateKey(activity.timestamp);\n const existing = grouped.get(dateKey);\n if (existing) {\n existing.push(activity);\n } else {\n grouped.set(dateKey, [activity]);\n }\n }\n\n return grouped;\n};\n\n// Activity slug to icon mapping\nconst ACTIVITY_ICON_MAP: Record<ActivitySlug, IconDefinition> = {\n // Orders/Cart\n order_placed: faCartShopping,\n abandoned_cart: faCartShopping,\n cart_items_added: faCartShopping,\n new_cart_items_added: faCartShopping,\n // Messages\n direct_message: faComment,\n comment_reply: faComment,\n message_received: faComment,\n message_sent: faComment,\n // Video\n video: faPlay,\n video_complete: faPlay,\n video_contact: faPlay,\n video_complete_contact: faPlay,\n // Leads\n new_lead: faUserPlus,\n page_views_contact: faUserPlus,\n smart_link_clicked: faUserPlus,\n // Page Views\n page_views: faEye,\n // Events\n upcoming_event: faCalendar,\n // Reviews\n review_left: faStar,\n // Tasks\n tasks: faSquareCheck,\n // Announcements\n announcements: faBell,\n // Fantasy\n fantasy_point: faTrophy,\n};\n\nconst getActivityIcon = (slug: ActivitySlug) =>\n ACTIVITY_ICON_MAP[slug] ?? faUser;\n\n// Activity feed item component\ntype ActivityFeedItemProps = {\n activity: Activity;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n};\n\nfunction ActivityFeedItem({\n activity,\n accentColor,\n textColor,\n}: ActivityFeedItemProps) {\n const icon = getActivityIcon(activity.slug);\n\n return (\n <div className=\"flex w-full items-start gap-1.5\">\n {/* Avatar */}\n <div className=\"shrink-0\">\n {activity.avatarUrl ? (\n <div className=\"relative size-8 overflow-hidden rounded-full\">\n <img\n src={activity.avatarUrl}\n alt={activity.userName}\n className=\"size-full object-cover\"\n />\n <div className=\"border-foreground/[0.08] absolute inset-0 rounded-full border\" />\n </div>\n ) : (\n <div\n className={`bg-muted flex size-8 items-center justify-center rounded-full`}\n >\n <FontAwesomeIcon\n icon={icon}\n className={`size-3.5 text-${textColor} opacity-60`}\n />\n </div>\n )}\n </div>\n\n {/* Content */}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex w-full items-center gap-1.5\">\n <p\n className={`flex-1 text-base font-semibold text-${textColor} truncate`}\n >\n {activity.activityType}\n </p>\n <p className={`text-xs text-${textColor} shrink-0 opacity-50`}>\n {formatTimestamp(activity.timestamp)}\n </p>\n </div>\n <p className={`text-sm text-${textColor} opacity-80`}>\n <span className={`font-medium text-${accentColor}`}>\n {activity.userName}\n </span>{\" \"}\n <span\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(activity.targetName, {\n ALLOWED_TAGS: [\"br\", \"strong\", \"em\", \"b\", \"i\"],\n ALLOWED_ATTR: [],\n }),\n }}\n />\n </p>\n </div>\n </div>\n );\n}\n\ntype RecentActivityWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Activity settings\n maxItemsToShow?: number;\n};\n\nexport function RecentActivityWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"Recent Activity\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n // Activity defaults\n maxItemsToShow = 5,\n\n className,\n ...props\n}: RecentActivityWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n const { data: activities = [], isLoading, isError } = useActivities();\n\n const groupedActivities = useMemo(\n () => groupActivitiesByDate(activities),\n [activities],\n );\n\n const totalCount = Math.min(activities.length, maxItemsToShow);\n\n // Get activities to display (limited by maxItemsToShow)\n const activitiesToShow = useMemo(() => {\n const result: { date: string; items: Activity[] }[] = [];\n let count = 0;\n\n for (const [dateKey, items] of groupedActivities) {\n if (count >= maxItemsToShow) break;\n\n const remainingSlots = maxItemsToShow - count;\n const itemsToAdd = items.slice(0, remainingSlots);\n\n if (itemsToAdd.length > 0) {\n result.push({\n date: formatDateHeader(items[0]?.timestamp ?? dateKey),\n items: itemsToAdd,\n });\n count += itemsToAdd.length;\n }\n }\n\n return result;\n }, [groupedActivities, maxItemsToShow]);\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} border-muted border ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className={`p-${padding} flex flex-col gap-2`}>\n {/* Header */}\n {titleEnabled && titleText && (\n <div className=\"flex w-full items-start gap-2\">\n <h2\n className={`flex-1 text-${titleFontSize} font-bold text-${titleColor}`}\n >\n {titleText}\n </h2>\n {!isLoading && (\n <span\n className={`text-4xl font-bold text-${textColor} leading-none`}\n >\n {totalCount.toString().padStart(2, \"0\")}\n </span>\n )}\n </div>\n )}\n\n {/* Loading state */}\n {isLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n /* Error state */\n <ErrorState />\n ) : activities.length === 0 ? (\n /* Empty state */\n <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-2\">\n <FontAwesomeIcon\n icon={faUser}\n className={`size-12 text-${textColor} opacity-30`}\n />\n <p\n className={`text-base font-semibold text-${textColor} opacity-50`}\n >\n No Activity To Report\n </p>\n <p className={`text-sm text-${textColor} opacity-40`}>\n You'll Do Great!\n </p>\n </div>\n ) : (\n /* Activity list */\n <div className=\"flex flex-col gap-4\">\n {activitiesToShow.map((group, groupIndex) => (\n <div key={groupIndex} className=\"flex flex-col gap-4\">\n {/* Date header */}\n <p className={`text-base font-semibold text-${textColor}`}>\n {group.date}\n </p>\n\n {/* Activity items */}\n <div className=\"flex flex-col gap-4\">\n {group.items.map((activity) => (\n <ActivityFeedItem\n key={activity.id}\n activity={activity}\n accentColor={accentColor}\n textColor={textColor}\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport const recentActivityWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"RecentActivityWidget\",\n displayName: \"Recent Activity Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the activity feed\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the activity feed\",\n defaultValue: \"Recent Activity\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for activity content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color used for links and highlights\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n\n // Styling Tab - Display Group\n {\n key: \"maxItemsToShow\",\n label: \"Max Items\",\n type: \"number\",\n description: \"Maximum number of activity items to display\",\n defaultValue: 5,\n tab: \"styling\",\n group: \"Display\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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ACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;0DACgB;GACf,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;uDACY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,MAAM;GACN,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;uDACa;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;uDACY;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;yDACe;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;8DACmB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACF;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpacerWidget-
|
|
1
|
+
{"version":3,"file":"SpacerWidget-BdVf_Yqm.cjs","names":["FontAwesomeIcon","faArrowsUpDown"],"sources":["../src/widgets/SpacerWidget.tsx"],"sourcesContent":["import {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport { faArrowsUpDown } from \"@fortawesome/pro-regular-svg-icons\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport type { ComponentProps } from \"react\";\nimport type React from \"react\";\n\ntype SpacerWidgetProps = ComponentProps<\"div\"> & {\n /**\n * Custom height as a CSS value (e.g., \"128px\", \"8rem\", \"20vh\")\n */\n customHeight?: string;\n /**\n * Not customizable, determines if we should show a preview image in the container\n */\n previewMode?: boolean;\n};\n\nexport function SpacerWidget({\n customHeight = \"128px\",\n previewMode = false,\n className,\n style,\n ...props\n}: SpacerWidgetProps): React.JSX.Element {\n return (\n <div\n className={`w-full ${className ?? \"\"}`}\n style={{ height: customHeight, ...style }}\n aria-hidden=\"true\"\n {...props}\n >\n {previewMode && (\n <div className=\"border-muted-400 bg-muted text-muted-foreground flex h-full w-full items-center justify-center gap-1 border border-dashed\">\n <FontAwesomeIcon icon={faArrowsUpDown} />\n <span>SPACER</span>\n </div>\n )}\n </div>\n );\n}\n\nexport const spacerWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"SpacerWidget\",\n displayName: \"Spacer\",\n fields: [\n {\n key: \"customHeight\",\n label: \"Height\",\n type: \"cssUnit\",\n description: \"Height of the spacer\",\n defaultValue: \"128px\",\n allowedUnits: [\"px\", \"vh\", \"rem\"],\n minByUnit: { px: 1, vh: 1, rem: 0.25 },\n maxByUnit: { px: 2000, vh: 100, rem: 125 },\n stepByUnit: { px: 1, vh: 1, rem: 0.25 },\n group: \"Spacing\",\n },\n ],\n};\n"],"mappings":";;;;;;;;;;AAoBA,SAAgB,aAAa,EAC3B,eAAe,SACf,cAAc,OACd,WACA,OACA,GAAG,SACoC;AACvC,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,WAAW,UAAU,aAAa;EAClC,OAAO;GAAE,QAAQ;GAAc,GAAG;GAAO;EACzC,eAAY;EACZ,GAAI;YAEH,eACC,iBAAA,GAAA,kBAAA,MAAC,OAAD;GAAK,WAAU;aAAf,CACE,iBAAA,GAAA,kBAAA,KAACA,+BAAAA,iBAAD,EAAiB,MAAMC,mCAAAA,gBAAkB,CAAA,EACzC,iBAAA,GAAA,kBAAA,KAAC,QAAD,EAAA,UAAM,UAAa,CAAA,CACf;;EAEJ,CAAA;;AAIV,MAAa,6BAAmD;CAC9D,YAAY;CACZ,aAAa;CACb,QAAQ,CACN;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;EACb,cAAc;EACd,cAAc;GAAC;GAAM;GAAM;GAAM;EACjC,WAAW;GAAE,IAAI;GAAG,IAAI;GAAG,KAAK;GAAM;EACtC,WAAW;GAAE,IAAI;GAAM,IAAI;GAAK,KAAK;GAAK;EAC1C,YAAY;GAAE,IAAI;GAAG,IAAI;GAAG,KAAK;GAAM;EACvC,OAAO;EACR,CACF;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpacerWidget-
|
|
1
|
+
{"version":3,"file":"SpacerWidget-DxR5K3hp.mjs","names":[],"sources":["../src/widgets/SpacerWidget.tsx"],"sourcesContent":["import {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport { faArrowsUpDown } from \"@fortawesome/pro-regular-svg-icons\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport type { ComponentProps } from \"react\";\nimport type React from \"react\";\n\ntype SpacerWidgetProps = ComponentProps<\"div\"> & {\n /**\n * Custom height as a CSS value (e.g., \"128px\", \"8rem\", \"20vh\")\n */\n customHeight?: string;\n /**\n * Not customizable, determines if we should show a preview image in the container\n */\n previewMode?: boolean;\n};\n\nexport function SpacerWidget({\n customHeight = \"128px\",\n previewMode = false,\n className,\n style,\n ...props\n}: SpacerWidgetProps): React.JSX.Element {\n return (\n <div\n className={`w-full ${className ?? \"\"}`}\n style={{ height: customHeight, ...style }}\n aria-hidden=\"true\"\n {...props}\n >\n {previewMode && (\n <div className=\"border-muted-400 bg-muted text-muted-foreground flex h-full w-full items-center justify-center gap-1 border border-dashed\">\n <FontAwesomeIcon icon={faArrowsUpDown} />\n <span>SPACER</span>\n </div>\n )}\n </div>\n );\n}\n\nexport const spacerWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"SpacerWidget\",\n displayName: \"Spacer\",\n fields: [\n {\n key: \"customHeight\",\n label: \"Height\",\n type: \"cssUnit\",\n description: \"Height of the spacer\",\n defaultValue: \"128px\",\n allowedUnits: [\"px\", \"vh\", \"rem\"],\n minByUnit: { px: 1, vh: 1, rem: 0.25 },\n maxByUnit: { px: 2000, vh: 100, rem: 125 },\n stepByUnit: { px: 1, vh: 1, rem: 0.25 },\n group: \"Spacing\",\n },\n ],\n};\n"],"mappings":";;;;;;;;;;AAoBA,SAAgB,aAAa,EAC3B,eAAe,SACf,cAAc,OACd,WACA,OACA,GAAG,SACoC;AACvC,QACE,oBAAC,OAAD;EACE,WAAW,UAAU,aAAa;EAClC,OAAO;GAAE,QAAQ;GAAc,GAAG;GAAO;EACzC,eAAY;EACZ,GAAI;YAEH,eACC,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,iBAAD,EAAiB,MAAM,gBAAkB,CAAA,EACzC,oBAAC,QAAD,EAAA,UAAM,UAAa,CAAA,CACf;;EAEJ,CAAA;;AAIV,MAAa,6BAAmD;CAC9D,YAAY;CACZ,aAAa;CACb,QAAQ,CACN;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;EACb,cAAc;EACd,cAAc;GAAC;GAAM;GAAM;GAAM;EACjC,WAAW;GAAE,IAAI;GAAG,IAAI;GAAG,KAAK;GAAM;EACtC,WAAW;GAAE,IAAI;GAAM,IAAI;GAAK,KAAK;GAAK;EAC1C,YAAY;GAAE,IAAI;GAAG,IAAI;GAAG,KAAK;GAAM;EACvC,OAAO;EACR,CACF;CACF"}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
require("./chunk-CZWwpsFl.cjs");
|
|
2
2
|
const require_MediaRenderer = require("./MediaRenderer-CcJvyOJ1.cjs");
|
|
3
|
+
const require_WidgetInteractionContext = require("./WidgetInteractionContext-DjlpWpTR.cjs");
|
|
3
4
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
4
5
|
let react = require("react");
|
|
5
6
|
let _fluid_app_ui_primitives = require("@fluid-app/ui-primitives");
|
|
6
7
|
require("@fluid-app/portal-core/types");
|
|
7
8
|
let _fluid_app_portal_core_registries = require("@fluid-app/portal-core/registries");
|
|
8
9
|
//#region src/widgets/TableWidget.tsx
|
|
9
|
-
var TableWidget_exports = /* @__PURE__ */ require_chunk.__exportAll({
|
|
10
|
-
TableWidget: () => TableWidget,
|
|
11
|
-
tableWidgetPropertySchema: () => tableWidgetPropertySchema
|
|
12
|
-
});
|
|
13
10
|
const DEFAULT_DATA = [];
|
|
14
11
|
function ImageCellRenderer(_value, item) {
|
|
15
12
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -135,6 +132,7 @@ function TableWidget({ titleEnabled = true, titleText = "Products", titleFontSiz
|
|
|
135
132
|
if (sortConfig?.key !== key) return null;
|
|
136
133
|
return sortConfig.direction === "asc" ? " ↑" : " ↓";
|
|
137
134
|
};
|
|
135
|
+
const { onItemClick } = require_WidgetInteractionContext.useWidgetInteraction();
|
|
138
136
|
if (data.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
139
137
|
className: `@container rounded-${borderRadius} bg-${backgroundColor} bg-cover bg-center p-${padding} ${className}`,
|
|
140
138
|
style: { backgroundImage },
|
|
@@ -200,7 +198,17 @@ function TableWidget({ titleEnabled = true, titleText = "Products", titleFontSiz
|
|
|
200
198
|
})
|
|
201
199
|
}, col.key))
|
|
202
200
|
}) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tbody", { children: [paginatedData.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
|
|
203
|
-
className: `h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : ""}`,
|
|
201
|
+
className: `h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : ""} ${onItemClick ? "cursor-pointer hover:opacity-80" : ""}`,
|
|
202
|
+
...onItemClick ? {
|
|
203
|
+
tabIndex: 0,
|
|
204
|
+
onClick: () => onItemClick(item),
|
|
205
|
+
onKeyDown: (e) => {
|
|
206
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
207
|
+
e.preventDefault();
|
|
208
|
+
onItemClick(item);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
} : {},
|
|
204
212
|
children: columns.map((col) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
205
213
|
className: "px-4 py-3 text-sm",
|
|
206
214
|
children: col.render ? col.render(item[col.key], item) : String(item[col.key] ?? "-")
|
|
@@ -446,12 +454,6 @@ Object.defineProperty(exports, "TableWidget", {
|
|
|
446
454
|
return TableWidget;
|
|
447
455
|
}
|
|
448
456
|
});
|
|
449
|
-
Object.defineProperty(exports, "TableWidget_exports", {
|
|
450
|
-
enumerable: true,
|
|
451
|
-
get: function() {
|
|
452
|
-
return TableWidget_exports;
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
457
|
Object.defineProperty(exports, "tableWidgetPropertySchema", {
|
|
456
458
|
enumerable: true,
|
|
457
459
|
get: function() {
|
|
@@ -459,4 +461,4 @@ Object.defineProperty(exports, "tableWidgetPropertySchema", {
|
|
|
459
461
|
}
|
|
460
462
|
});
|
|
461
463
|
|
|
462
|
-
//# sourceMappingURL=TableWidget-
|
|
464
|
+
//# sourceMappingURL=TableWidget-BQNVZUkg.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableWidget-BQNVZUkg.cjs","names":["MediaRenderer","getMediaPropsFromShareable","useWidgetInteraction","Input"],"sources":["../src/widgets/TableWidget.tsx"],"sourcesContent":["import { useState, useMemo, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { Input } from \"@fluid-app/ui-primitives\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\n// Column definition for the table\ntype ColumnDef = {\n key: string;\n label: string;\n sortable: boolean;\n render?: (value: unknown, item: ShareableItem) => React.ReactNode;\n};\n\nconst DEFAULT_DATA: ShareableItem[] = [];\n\n// ---------------------------------------------------------------------------\n// Column cell renderers\n// ---------------------------------------------------------------------------\n\nfunction ImageCellRenderer(_value: unknown, item: ShareableItem) {\n return (\n <div className=\"h-10 w-10 rounded object-cover\">\n <MediaRenderer {...getMediaPropsFromShareable(item)} />\n </div>\n );\n}\n\nfunction PriceCellRenderer(_value: unknown, item: ShareableItem) {\n return ((item.display_price as string) ?? item.price) || \"-\";\n}\n\nfunction StatusCellRenderer(value: unknown) {\n const status = String(value || \"unknown\").toLowerCase();\n const statusStyles: Record<string, string> = {\n active: \"bg-primary text-primary-foreground\",\n inactive: \"bg-secondary text-secondary-foreground\",\n unknown: \"bg-muted text-muted-foreground\",\n };\n return (\n <span\n className={`inline-flex rounded-full px-2 py-1 text-xs font-medium ${statusStyles[status] || \"bg-muted text-foreground\"}`}\n >\n {String(value || \"Unknown\")}\n </span>\n );\n}\n\n// Default columns for product data\nconst defaultColumns: ColumnDef[] = [\n {\n key: \"imageUrl\",\n label: \"Image\",\n sortable: false,\n render: ImageCellRenderer,\n },\n {\n key: \"title\",\n label: \"Title\",\n sortable: true,\n },\n {\n key: \"price\",\n label: \"Price\",\n sortable: true,\n render: PriceCellRenderer,\n },\n {\n key: \"status\",\n label: \"Status\",\n sortable: true,\n render: StatusCellRenderer,\n },\n];\n\ntype TableWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n alternatingColorEnabled?: boolean;\n textColor?: ColorOptions;\n headerBackgroundColor?: ColorOptions;\n headerTextColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Data\n data?: ShareableItem[];\n\n // Features\n filterEnabled?: boolean;\n sortingEnabled?: boolean;\n paginationEnabled?: boolean;\n maxRowsPerPage?: number;\n};\n\nexport function TableWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"Products\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n alternatingColorEnabled = true,\n textColor = \"foreground\",\n headerBackgroundColor = \"muted\",\n headerTextColor = \"foreground\",\n padding = 4,\n borderRadius = \"md\",\n\n // Data\n data = DEFAULT_DATA,\n\n // Feature defaults\n filterEnabled = true,\n sortingEnabled = true,\n paginationEnabled = true,\n maxRowsPerPage = 5,\n\n className,\n ...props\n}: TableWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const isImageBackground = background.type === \"image\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n isImageBackground\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n const pageSize = maxRowsPerPage;\n\n // When using an image background, inner elements should be transparent\n // so the image shows through. Otherwise use the configured colors.\n const innerBg = isImageBackground\n ? \"bg-transparent\"\n : `bg-${backgroundColor}`;\n const innerBgAlt = isImageBackground\n ? \"bg-black/5\"\n : `bg-${backgroundColor}-400`;\n const innerBorder = isImageBackground\n ? \"border-white/20\"\n : `border-${backgroundColor}-600`;\n const headerBg = isImageBackground\n ? \"bg-black/10\"\n : `bg-${headerBackgroundColor}-400`;\n const headerBorder = isImageBackground\n ? \"border-white/20\"\n : `border-${headerBackgroundColor}-600`;\n const paginationBg = isImageBackground\n ? \"bg-black/10\"\n : `bg-${backgroundColor}-400`;\n\n // State for filtering, sorting, and pagination\n const [globalFilter, setGlobalFilter] = useState(\"\");\n const [sortConfig, setSortConfig] = useState<{\n key: string;\n direction: \"asc\" | \"desc\";\n } | null>(null);\n const [currentPage, setCurrentPage] = useState(1);\n\n const columns = defaultColumns;\n\n // Filter data\n const filteredData = useMemo(() => {\n let result = [...data];\n\n if (globalFilter) {\n const lowerFilter = globalFilter.toLowerCase();\n result = result.filter((item) =>\n columns.some((col) => {\n const value = item[col.key];\n return String(value ?? \"\")\n .toLowerCase()\n .includes(lowerFilter);\n }),\n );\n }\n\n return result;\n }, [data, globalFilter, columns]);\n\n // Sort data\n const sortedData = useMemo(() => {\n if (!sortConfig) return filteredData;\n\n return [...filteredData].sort((a, b) => {\n const aValue = a[sortConfig.key];\n const bValue = b[sortConfig.key];\n\n // Handle null/undefined\n if (aValue == null && bValue == null) return 0;\n if (aValue == null) return sortConfig.direction === \"asc\" ? 1 : -1;\n if (bValue == null) return sortConfig.direction === \"asc\" ? -1 : 1;\n\n // Compare values\n let comparison = 0;\n if (typeof aValue === \"number\" && typeof bValue === \"number\") {\n comparison = aValue - bValue;\n } else {\n comparison = String(aValue).localeCompare(String(bValue));\n }\n\n return sortConfig.direction === \"asc\" ? comparison : -comparison;\n });\n }, [filteredData, sortConfig]);\n\n // Paginate data\n const paginatedData = useMemo(() => {\n if (!paginationEnabled) return sortedData;\n\n const startIndex = (currentPage - 1) * pageSize;\n return sortedData.slice(startIndex, startIndex + pageSize);\n }, [sortedData, currentPage, pageSize, paginationEnabled]);\n\n const totalPages = Math.ceil(sortedData.length / pageSize);\n\n // Reset to page 1 when filters change\n const handleGlobalFilterChange = (value: string) => {\n setGlobalFilter(value);\n setCurrentPage(1);\n };\n\n // Handle sort\n const handleSort = (key: string) => {\n if (!sortingEnabled) return;\n\n setSortConfig((prev) => {\n if (prev?.key !== key) return { key, direction: \"asc\" };\n if (prev.direction === \"asc\") return { key, direction: \"desc\" };\n return null;\n });\n };\n\n // Get sort indicator\n const getSortIndicator = (key: string) => {\n if (sortConfig?.key !== key) return null;\n return sortConfig.direction === \"asc\" ? \" ↑\" : \" ↓\";\n };\n\n const { onItemClick } = useWidgetInteraction();\n\n // Empty state\n if (data.length === 0) {\n return (\n <div\n className={`@container rounded-${borderRadius} bg-${backgroundColor} bg-cover bg-center p-${padding} ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className=\"text-muted-foreground flex min-h-[200px] flex-col items-center justify-center gap-2\">\n <div className=\"text-4xl\">📋</div>\n <p className=\"text-sm\">No data available</p>\n <p className=\"text-muted-foreground/70 text-xs\">\n Connect a data source to display table data\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`@container overflow-hidden ${paginationEnabled ? \"\" : \"overflow-y-auto\"} rounded-${borderRadius} bg-${backgroundColor} bg-cover bg-center text-${textColor} ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div\n className={`flex items-center justify-between p-${padding} ${innerBg} space-x-2`}\n >\n {/* Title */}\n {titleEnabled && titleText && (\n <h2\n className={`text-${titleFontSize === \"md\" ? \"base\" : titleFontSize} font-bold text-${titleColor} min-w-0 truncate`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Global Search */}\n {filterEnabled && (\n <Input\n type=\"text\"\n placeholder=\"Search all columns...\"\n value={globalFilter}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n handleGlobalFilterChange(e.target.value)\n }\n className={`w-full rounded-md border ${headerBorder} ${headerBg} ring-offset-muted px-3 py-2 text-sm placeholder:text-${headerTextColor}-900 focus-visible:ring-primary focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none md:w-64`}\n />\n )}\n </div>\n\n {/* Table */}\n <div className=\"overflow-x-auto\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className={`${headerBg} ${headerBorder} border-y`}>\n {columns.map((col) => (\n <th\n key={col.key}\n className={`px-4 py-3 text-left text-sm font-semibold text-${headerTextColor} ${col.sortable && sortingEnabled ? \"cursor-pointer select-none hover:opacity-80\" : \"\"}`}\n {...(col.sortable && sortingEnabled\n ? {\n role: \"button\" as const,\n tabIndex: 0,\n onClick: () => handleSort(col.key),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleSort(col.key);\n }\n },\n }\n : {})}\n >\n <div className=\"flex flex-col gap-1\">\n <span>\n {col.label}\n {col.sortable &&\n sortingEnabled &&\n getSortIndicator(col.key)}\n </span>\n </div>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {paginatedData.map((item, index) => (\n <tr\n key={item.id ?? index}\n className={`h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : \"\"} ${onItemClick ? \"cursor-pointer hover:opacity-80\" : \"\"}`}\n {...(onItemClick\n ? {\n tabIndex: 0,\n onClick: () => onItemClick(item),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(item);\n }\n },\n }\n : {})}\n >\n {columns.map((col) => (\n <td key={col.key} className=\"px-4 py-3 text-sm\">\n {col.render\n ? col.render(item[col.key], item)\n : String(item[col.key] ?? \"-\")}\n </td>\n ))}\n </tr>\n ))}\n {/* Empty rows to fill the last page for consistent pagination position */}\n {paginationEnabled &&\n paginatedData.length < pageSize &&\n paginatedData.length > 0 &&\n Array.from({ length: pageSize - paginatedData.length }).map(\n (_, index) => (\n <tr\n key={`empty-${index}`}\n className={`h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : \"\"}`}\n >\n {columns.map((col) => (\n <td key={col.key} className=\"px-4 py-3 text-sm\">\n \n </td>\n ))}\n </tr>\n ),\n )}\n </tbody>\n </table>\n </div>\n\n {/* No results message */}\n {paginatedData.length === 0 && data.length > 0 && (\n <div className={`py-8 text-center ${innerBg}`}>\n <p className=\"text-sm\">No results found</p>\n <p className=\"text-xs\">Try adjusting your search</p>\n </div>\n )}\n\n {/* Pagination */}\n {paginationEnabled && totalPages > 1 && (\n <div\n className={`flex flex-col items-center justify-between gap-2 border-t ${innerBorder} p-${padding} @md:flex-row ${paginationBg} text-${textColor}`}\n >\n <p className=\"text-sm\">\n Showing {(currentPage - 1) * pageSize + 1}-\n {Math.min(currentPage * pageSize, sortedData.length)} of{\" \"}\n {sortedData.length} results\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}\n disabled={currentPage === 1}\n className={`rounded-md border border-${headerBackgroundColor}-600 bg-${headerBackgroundColor} ring-offset-muted placeholder:text-muted-foreground focus-visible:ring-primary px-3 py-1 text-sm transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50`}\n >\n Previous\n </button>\n <span className=\"text-sm\">\n Page {currentPage} of {totalPages}\n </span>\n <button\n onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}\n disabled={currentPage === totalPages}\n className={`rounded-md border border-${headerBackgroundColor}-600 bg-${headerBackgroundColor} ring-offset-muted placeholder:text-muted-foreground focus-visible:ring-primary px-3 py-1 text-sm transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50`}\n >\n Next\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const tableWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"TableWidget\",\n displayName: \"Table Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"data\"],\n fields: [\n // Content Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the table\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the table\",\n defaultValue: \"Products\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the table container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"alternatingColorEnabled\",\n label: \"Enable Alternating Colors\",\n type: \"boolean\",\n description: \"Enable alternating colors for table rows\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"headerBackgroundColor\",\n label: \"Header Background\",\n description: \"Background color for the table header\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for table content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"headerTextColor\",\n label: \"Header Text Color\",\n description: \"Text color for the table header\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the table container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the table container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n\n // Behavior Tab - Features Group\n {\n key: \"filterEnabled\",\n label: \"Enable Filters\",\n type: \"boolean\",\n description: \"Show global search and column filters\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"sortingEnabled\",\n label: \"Enable Sorting\",\n type: \"boolean\",\n description: \"Allow sorting by clicking column headers\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"paginationEnabled\",\n label: \"Enable Pagination\",\n type: \"boolean\",\n description: \"Split data into pages\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"maxRowsPerPage\",\n label: \"Max Rows Per Page\",\n type: \"number\",\n description: \"Maximum number of rows to display per page\",\n min: 1,\n max: 50,\n step: 1,\n defaultValue: 5,\n tab: \"behavior\",\n group: \"Features\",\n requiresKeyToBeTrue: \"paginationEnabled\",\n },\n\n // Data Tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure data source for the table\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs";
|
|
2
2
|
import { a as getFontSizeField, c as getPaddingField, i as getColorField, n as getBorderRadiusField } from "./fields-wPOk-SmZ.mjs";
|
|
3
3
|
import { n as getMediaPropsFromShareable, t as MediaRenderer } from "./MediaRenderer-Uq90PZcY.mjs";
|
|
4
|
+
import { n as useWidgetInteraction } from "./WidgetInteractionContext-awLrJeAK.mjs";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
import { useMemo, useState } from "react";
|
|
6
7
|
import { Input } from "@fluid-app/ui-primitives";
|
|
@@ -135,6 +136,7 @@ function TableWidget({ titleEnabled = true, titleText = "Products", titleFontSiz
|
|
|
135
136
|
if (sortConfig?.key !== key) return null;
|
|
136
137
|
return sortConfig.direction === "asc" ? " ↑" : " ↓";
|
|
137
138
|
};
|
|
139
|
+
const { onItemClick } = useWidgetInteraction();
|
|
138
140
|
if (data.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
139
141
|
className: `@container rounded-${borderRadius} bg-${backgroundColor} bg-cover bg-center p-${padding} ${className}`,
|
|
140
142
|
style: { backgroundImage },
|
|
@@ -200,7 +202,17 @@ function TableWidget({ titleEnabled = true, titleText = "Products", titleFontSiz
|
|
|
200
202
|
})
|
|
201
203
|
}, col.key))
|
|
202
204
|
}) }), /* @__PURE__ */ jsxs("tbody", { children: [paginatedData.map((item, index) => /* @__PURE__ */ jsx("tr", {
|
|
203
|
-
className: `h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : ""}`,
|
|
205
|
+
className: `h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : ""} ${onItemClick ? "cursor-pointer hover:opacity-80" : ""}`,
|
|
206
|
+
...onItemClick ? {
|
|
207
|
+
tabIndex: 0,
|
|
208
|
+
onClick: () => onItemClick(item),
|
|
209
|
+
onKeyDown: (e) => {
|
|
210
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
211
|
+
e.preventDefault();
|
|
212
|
+
onItemClick(item);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
} : {},
|
|
204
216
|
children: columns.map((col) => /* @__PURE__ */ jsx("td", {
|
|
205
217
|
className: "px-4 py-3 text-sm",
|
|
206
218
|
children: col.render ? col.render(item[col.key], item) : String(item[col.key] ?? "-")
|
|
@@ -442,4 +454,4 @@ const tableWidgetPropertySchema = {
|
|
|
442
454
|
//#endregion
|
|
443
455
|
export { TableWidget_exports as n, tableWidgetPropertySchema as r, TableWidget as t };
|
|
444
456
|
|
|
445
|
-
//# sourceMappingURL=TableWidget-
|
|
457
|
+
//# sourceMappingURL=TableWidget-bpvdvJHI.mjs.map
|