@planningcenter/topbar 11.2.4 → 11.2.5-qa-827.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3453,12 +3453,16 @@
3453
3453
 
3454
3454
  const pcoUrl = pcoUrl$1;
3455
3455
 
3456
+ // The route rides in the iframe URL fragment (`…/topbar#conversations/abc`),
3457
+ // not the path, so updating it is a same-document navigation that doesn't
3458
+ // reload the iframe, but also lets the route survive a forced reload (e.g.
3459
+ // Turbo re-parenting the topbar).
3456
3460
  function buildPicobotSrc(origin, path) {
3457
3461
  const [rawPath, queryPart] = path.replace(/^\/+/, "").split("?", 2);
3458
3462
  const safePath = rawPath.split("/").filter(segment => segment && segment !== "." && segment !== "..").join("/");
3459
- const pathWithPrefix = ["topbar", safePath].filter(Boolean).join("/");
3460
- const relativePath = queryPart !== undefined ? `${pathWithPrefix}?${queryPart}` : pathWithPrefix;
3461
- return new URL(relativePath, origin).toString();
3463
+ const fragment = queryPart !== undefined ? `${safePath}?${queryPart}` : safePath;
3464
+ const base = new URL("topbar", origin).toString();
3465
+ return fragment ? `${base}#${fragment}` : base;
3462
3466
  }
3463
3467
 
3464
3468
  const handleSearchSelect = (hit, indexName) => {
@@ -3610,6 +3614,11 @@
3610
3614
  LoadingIndicator: LoadingIndicator$1,
3611
3615
  StackView: StackView$1
3612
3616
  } = addOns.components;
3617
+ function CalendlyWidget(props) {
3618
+ return props.url ? /*#__PURE__*/React.createElement(reactCalendly.InlineWidget, {
3619
+ ...props
3620
+ }) : null;
3621
+ }
3613
3622
  function HelpdeskComponent({
3614
3623
  appName,
3615
3624
  closeDrawer,
@@ -3626,13 +3635,10 @@
3626
3635
  onMessage
3627
3636
  }) {
3628
3637
  const ref = React.useRef(null);
3629
- const initialPath = iframePath || "";
3630
- // Tracks the path picobot last reported via postMessage so an
3631
- // incoming currentPath that matches it doesn't trigger a reload.
3632
- // Picobot sends a bare relative path (e.g. "conversations/abc") with
3633
- // no leading slash or /topbar prefix—buildPicobotSrc adds those.
3634
- const lastReportedPathRef = React.useRef(initialPath);
3635
- const [loadedPath, setLoadedPath] = React.useState(initialPath);
3638
+ // Keep the fragment in sync in both directions—external opens (deeplink /
3639
+ // Contact support) and picobot's own NEW_ROUTE_RENDERED reports—so it
3640
+ // always reflects the live conversation. See buildPicobotSrc.
3641
+ const [loadedPath, setLoadedPath] = React.useState(iframePath || "");
3636
3642
  React.useEffect(() => {
3637
3643
  if (!onIframeChangePath && !onMessage) return undefined;
3638
3644
  const handler = e => {
@@ -3642,7 +3648,7 @@
3642
3648
  if (e.source !== ref.current.contentWindow) return;
3643
3649
  if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === "NEW_ROUTE_RENDERED" && onIframeChangePath) {
3644
3650
  const reportedPath = String((_b = e.data.payload) !== null && _b !== void 0 ? _b : "");
3645
- lastReportedPathRef.current = reportedPath;
3651
+ setLoadedPath(reportedPath);
3646
3652
  onIframeChangePath(reportedPath);
3647
3653
  }
3648
3654
  if (onMessage) onMessage(e.data);
@@ -3651,9 +3657,7 @@
3651
3657
  return () => window.removeEventListener("message", handler);
3652
3658
  }, [onIframeChangePath, onMessage]);
3653
3659
  React.useEffect(() => {
3654
- const incomingPath = iframePath || "";
3655
- if (lastReportedPathRef.current === incomingPath) return;
3656
- setLoadedPath(incomingPath);
3660
+ setLoadedPath(iframePath || "");
3657
3661
  }, [iframePath]);
3658
3662
  const iframeSrc = buildPicobotSrc(picobotOrigin, loadedPath);
3659
3663
  return /*#__PURE__*/React.createElement("iframe", {
@@ -3683,14 +3687,69 @@
3683
3687
  spacing: 1
3684
3688
  }, /*#__PURE__*/React.createElement(DrawerHeading, null, "Help and support"), /*#__PURE__*/React.createElement(LoadingIndicator$1, null)))),
3685
3689
  additionalComponents: {
3686
- // @ts-expect-error TODO: Relax type specification in add-ons-js to not require children
3687
- CalendlyWidget: reactCalendly.InlineWidget,
3688
- DocumentationSearch,
3689
- DrawerHeader,
3690
+ CalendlyWidget: {
3691
+ component: CalendlyWidget,
3692
+ properties: {
3693
+ pageSettings: {
3694
+ attribute: false
3695
+ },
3696
+ prefill: {
3697
+ attribute: false
3698
+ },
3699
+ styles: {
3700
+ attribute: false
3701
+ },
3702
+ url: {
3703
+ type: String
3704
+ }
3705
+ }
3706
+ },
3707
+ DocumentationSearch: {
3708
+ component: DocumentationSearch,
3709
+ properties: {
3710
+ currentAppName: {
3711
+ type: String
3712
+ },
3713
+ indexName: {
3714
+ type: String
3715
+ }
3716
+ }
3717
+ },
3718
+ DrawerHeader: {
3719
+ component: DrawerHeader,
3720
+ properties: {
3721
+ closeDrawer: {
3722
+ type: Function,
3723
+ event: false
3724
+ }
3725
+ }
3726
+ },
3690
3727
  DrawerHeading,
3691
- PicobotIframe,
3728
+ PicobotIframe: {
3729
+ component: PicobotIframe,
3730
+ properties: {
3731
+ currentPath: {
3732
+ attribute: false
3733
+ },
3734
+ onChangePath: {
3735
+ type: Function,
3736
+ event: false
3737
+ },
3738
+ onMessage: {
3739
+ type: Function,
3740
+ event: false
3741
+ }
3742
+ }
3743
+ },
3692
3744
  ScrollContainer,
3693
- SwitchView
3745
+ SwitchView: {
3746
+ component: SwitchView,
3747
+ properties: {
3748
+ activeIndex: {
3749
+ type: Number
3750
+ }
3751
+ }
3752
+ }
3694
3753
  },
3695
3754
  args: {
3696
3755
  appName,
@@ -3708,7 +3767,8 @@
3708
3767
  staticDotPath: "",
3709
3768
  staticPath: "M16 10C14.9391 10 13.9217 10.4214 13.1716 11.1716C12.4214 11.9217 12 12.9391 12 14H14C14 13.4696 14.2107 12.9609 14.5858 12.5858C14.9609 12.2107 15.4696 12 16 12C16.5304 12 17.0391 12.2107 17.4142 12.5858C17.7893 12.9609 18 13.4696 18 14C18 16 15 15.75 15 19H17C17 16.75 20 16.5 20 14C20 12.9391 19.5786 11.9217 18.8284 11.1716C18.0783 10.4214 17.0609 10 16 10ZM16 24C14.4178 24 12.871 23.5308 11.5554 22.6518C10.2399 21.7727 9.21447 20.5233 8.60897 19.0615C8.00347 17.5997 7.84504 15.9911 8.15372 14.4393C8.4624 12.8874 9.22433 11.462 10.3432 10.3431C11.462 9.22433 12.8874 8.4624 14.4393 8.15372C15.9911 7.84504 17.5997 8.00346 19.0615 8.60896C20.5233 9.21446 21.7727 10.2398 22.6518 11.5554C23.5308 12.871 24 14.4177 24 16C23.9974 18.1209 23.1537 20.1542 21.6539 21.6539C20.1542 23.1537 18.1209 23.9974 16 24ZM16 6C14.0222 6 12.0888 6.58649 10.4443 7.6853C8.79981 8.78412 7.51809 10.3459 6.76121 12.1732C6.00433 14.0004 5.8063 16.0111 6.19215 17.9509C6.578 19.8907 7.53041 21.6725 8.92894 23.0711C10.3275 24.4696 12.1093 25.422 14.0491 25.8079C15.9889 26.1937 17.9996 25.9957 19.8268 25.2388C21.6541 24.4819 23.2159 23.2002 24.3147 21.5557C25.4135 19.9112 26 17.9778 26 16C26 13.3478 24.9464 10.8043 23.0711 8.92893C21.1957 7.05357 18.6522 6 16 6V6ZM15 22H17V20H15V22Z"
3710
3769
  },
3711
- name: "Helpdesk"
3770
+ name: "Helpdesk",
3771
+ storageExemptPaths: ["email", "phone"]
3712
3772
  };
3713
3773
 
3714
3774
  const Eyebrow = ({
@@ -4293,8 +4353,13 @@
4293
4353
  function NavLinkWithBadge({
4294
4354
  children,
4295
4355
  badge,
4296
- onClick,
4297
- ...rest
4356
+ borderBottomColor,
4357
+ borderBottomStyle,
4358
+ borderBottomWidth,
4359
+ color,
4360
+ fontSize,
4361
+ fontWeight,
4362
+ onClick
4298
4363
  }) {
4299
4364
  return /*#__PURE__*/React.createElement(tapestryReact.StackView, {
4300
4365
  as: "button",
@@ -4304,7 +4369,14 @@
4304
4369
  paddingBottom: 0.75,
4305
4370
  onClick: () => onClick(),
4306
4371
  spacing: 1,
4307
- ...rest
4372
+ ...{
4373
+ borderBottomColor,
4374
+ borderBottomStyle,
4375
+ borderBottomWidth,
4376
+ color,
4377
+ fontSize,
4378
+ fontWeight
4379
+ }
4308
4380
  }, children, badge && /*#__PURE__*/React.createElement(tapestryReact.Badge, {
4309
4381
  size: "sm",
4310
4382
  fontWeight: "600",
@@ -4356,11 +4428,55 @@
4356
4428
  spacing: 1
4357
4429
  }, /*#__PURE__*/React.createElement(DrawerHeading, null, "To do"), /*#__PURE__*/React.createElement(LoadingIndicator, null)))),
4358
4430
  additionalComponents: {
4359
- DrawerHeader,
4431
+ DrawerHeader: {
4432
+ component: DrawerHeader,
4433
+ properties: {
4434
+ closeDrawer: {
4435
+ event: false,
4436
+ type: Function
4437
+ }
4438
+ }
4439
+ },
4360
4440
  DrawerHeading,
4361
- NavLinkWithBadge,
4441
+ NavLinkWithBadge: {
4442
+ component: NavLinkWithBadge,
4443
+ properties: {
4444
+ badge: {
4445
+ attribute: false
4446
+ },
4447
+ borderBottomColor: {
4448
+ type: String
4449
+ },
4450
+ borderBottomStyle: {
4451
+ type: String
4452
+ },
4453
+ borderBottomWidth: {
4454
+ type: String
4455
+ },
4456
+ color: {
4457
+ type: String
4458
+ },
4459
+ fontSize: {
4460
+ attribute: false
4461
+ },
4462
+ fontWeight: {
4463
+ attribute: false
4464
+ },
4465
+ onClick: {
4466
+ event: false,
4467
+ type: Function
4468
+ }
4469
+ }
4470
+ },
4362
4471
  ScrollContainer,
4363
- SwitchView
4472
+ SwitchView: {
4473
+ component: SwitchView,
4474
+ properties: {
4475
+ activeIndex: {
4476
+ type: Number
4477
+ }
4478
+ }
4479
+ }
4364
4480
  },
4365
4481
  args: {
4366
4482
  closeDrawer,
@@ -4639,6 +4755,13 @@
4639
4755
  const tool = toolsRouteMap[toolName];
4640
4756
  return (_b = (_a = tool === null || tool === void 0 ? void 0 : tool.storageExemptPaths) === null || _a === void 0 ? void 0 : _a.includes(path)) !== null && _b !== void 0 ? _b : false;
4641
4757
  }
4758
+ function scrollToolDrawerToTop(toolName) {
4759
+ var _a;
4760
+ (_a = document.getElementById(`toolbarDrawer${toolName}`)) === null || _a === void 0 ? void 0 : _a.scrollTo({
4761
+ behavior: "smooth",
4762
+ top: 0
4763
+ });
4764
+ }
4642
4765
  const TOOLS_MAP = {
4643
4766
  Chat,
4644
4767
  Helpdesk,
@@ -4708,17 +4831,21 @@
4708
4831
  unsubscribe();
4709
4832
  };
4710
4833
  }, [open, clearRoute]);
4834
+ const openHelpdeskAtRoot = React.useCallback(() => {
4835
+ onChangeToolbarFragmentRoute(Helpdesk.name.toLowerCase(), "");
4836
+ scrollToolDrawerToTop(Helpdesk.name);
4837
+ }, [onChangeToolbarFragmentRoute]);
4711
4838
  React.useEffect(() => {
4712
4839
  window.topbar = window.topbar || {};
4713
4840
  window.topbar.openProfile = () => handleToolOnClick(Profile);
4714
- window.topbar.openHelpdesk = () => handleToolOnClick(Helpdesk);
4841
+ window.topbar.openHelpdesk = openHelpdeskAtRoot;
4715
4842
  window.openHelpdesk = window.topbar.openHelpdesk; /* TODO: Remove when products have migrated to window.topbar.openHelpdesk */
4716
4843
  return () => {
4717
4844
  delete window.topbar.openProfile;
4718
4845
  delete window.topbar.openHelpdesk;
4719
4846
  delete window.openHelpdesk; /* TODO: Remove when products have migrated to window.topbar.openHelpdesk */
4720
4847
  };
4721
- }, [Helpdesk, Profile]);
4848
+ }, [Profile, openHelpdeskAtRoot]);
4722
4849
  const loginSettingsUrl = getLoginProfilePath({
4723
4850
  appName: appName.replace(/[\s-]/, ""),
4724
4851
  env: env,
@@ -4800,12 +4927,8 @@
4800
4927
  });
4801
4928
  const TOOLS = [Notifications, Tasks, displayChatIcon && Chat].filter(Boolean);
4802
4929
  const handleToolOnClick = tool => {
4803
- var _a;
4804
4930
  toggleDrawer(tool);
4805
- (_a = document.getElementById(`toolbarDrawer${tool.name}`)) === null || _a === void 0 ? void 0 : _a.scrollTo({
4806
- behavior: "smooth",
4807
- top: 0
4808
- });
4931
+ scrollToolDrawerToTop(tool.name);
4809
4932
  };
4810
4933
  const toolSpecificProps = {
4811
4934
  Profile: {