@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.
package/dist/topbar.js CHANGED
@@ -3466,12 +3466,16 @@ var styles = {"toolbar":"toolbar-KHJR5","toolbar-button":"toolbar-button-Ye4h5",
3466
3466
 
3467
3467
  const pcoUrl = pcoUrl$1;
3468
3468
 
3469
+ // The route rides in the iframe URL fragment (`…/topbar#conversations/abc`),
3470
+ // not the path, so updating it is a same-document navigation that doesn't
3471
+ // reload the iframe, but also lets the route survive a forced reload (e.g.
3472
+ // Turbo re-parenting the topbar).
3469
3473
  function buildPicobotSrc(origin, path) {
3470
3474
  const [rawPath, queryPart] = path.replace(/^\/+/, "").split("?", 2);
3471
3475
  const safePath = rawPath.split("/").filter(segment => segment && segment !== "." && segment !== "..").join("/");
3472
- const pathWithPrefix = ["topbar", safePath].filter(Boolean).join("/");
3473
- const relativePath = queryPart !== undefined ? `${pathWithPrefix}?${queryPart}` : pathWithPrefix;
3474
- return new URL(relativePath, origin).toString();
3476
+ const fragment = queryPart !== undefined ? `${safePath}?${queryPart}` : safePath;
3477
+ const base = new URL("topbar", origin).toString();
3478
+ return fragment ? `${base}#${fragment}` : base;
3475
3479
  }
3476
3480
 
3477
3481
  const handleSearchSelect = (hit, indexName) => {
@@ -3623,6 +3627,11 @@ const {
3623
3627
  LoadingIndicator: LoadingIndicator$1,
3624
3628
  StackView: StackView$1
3625
3629
  } = addOns.components;
3630
+ function CalendlyWidget(props) {
3631
+ return props.url ? /*#__PURE__*/React.createElement(reactCalendly.InlineWidget, {
3632
+ ...props
3633
+ }) : null;
3634
+ }
3626
3635
  function HelpdeskComponent({
3627
3636
  appName,
3628
3637
  closeDrawer,
@@ -3639,13 +3648,10 @@ function HelpdeskComponent({
3639
3648
  onMessage
3640
3649
  }) {
3641
3650
  const ref = React.useRef(null);
3642
- const initialPath = iframePath || "";
3643
- // Tracks the path picobot last reported via postMessage so an
3644
- // incoming currentPath that matches it doesn't trigger a reload.
3645
- // Picobot sends a bare relative path (e.g. "conversations/abc") with
3646
- // no leading slash or /topbar prefix—buildPicobotSrc adds those.
3647
- const lastReportedPathRef = React.useRef(initialPath);
3648
- const [loadedPath, setLoadedPath] = React.useState(initialPath);
3651
+ // Keep the fragment in sync in both directions—external opens (deeplink /
3652
+ // Contact support) and picobot's own NEW_ROUTE_RENDERED reports—so it
3653
+ // always reflects the live conversation. See buildPicobotSrc.
3654
+ const [loadedPath, setLoadedPath] = React.useState(iframePath || "");
3649
3655
  React.useEffect(() => {
3650
3656
  if (!onIframeChangePath && !onMessage) return undefined;
3651
3657
  const handler = e => {
@@ -3655,7 +3661,7 @@ function HelpdeskComponent({
3655
3661
  if (e.source !== ref.current.contentWindow) return;
3656
3662
  if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === "NEW_ROUTE_RENDERED" && onIframeChangePath) {
3657
3663
  const reportedPath = String((_b = e.data.payload) !== null && _b !== void 0 ? _b : "");
3658
- lastReportedPathRef.current = reportedPath;
3664
+ setLoadedPath(reportedPath);
3659
3665
  onIframeChangePath(reportedPath);
3660
3666
  }
3661
3667
  if (onMessage) onMessage(e.data);
@@ -3664,9 +3670,7 @@ function HelpdeskComponent({
3664
3670
  return () => window.removeEventListener("message", handler);
3665
3671
  }, [onIframeChangePath, onMessage]);
3666
3672
  React.useEffect(() => {
3667
- const incomingPath = iframePath || "";
3668
- if (lastReportedPathRef.current === incomingPath) return;
3669
- setLoadedPath(incomingPath);
3673
+ setLoadedPath(iframePath || "");
3670
3674
  }, [iframePath]);
3671
3675
  const iframeSrc = buildPicobotSrc(picobotOrigin, loadedPath);
3672
3676
  return /*#__PURE__*/React.createElement("iframe", {
@@ -3696,14 +3700,69 @@ function HelpdeskComponent({
3696
3700
  spacing: 1
3697
3701
  }, /*#__PURE__*/React.createElement(DrawerHeading, null, "Help and support"), /*#__PURE__*/React.createElement(LoadingIndicator$1, null)))),
3698
3702
  additionalComponents: {
3699
- // @ts-expect-error TODO: Relax type specification in add-ons-js to not require children
3700
- CalendlyWidget: reactCalendly.InlineWidget,
3701
- DocumentationSearch,
3702
- DrawerHeader,
3703
+ CalendlyWidget: {
3704
+ component: CalendlyWidget,
3705
+ properties: {
3706
+ pageSettings: {
3707
+ attribute: false
3708
+ },
3709
+ prefill: {
3710
+ attribute: false
3711
+ },
3712
+ styles: {
3713
+ attribute: false
3714
+ },
3715
+ url: {
3716
+ type: String
3717
+ }
3718
+ }
3719
+ },
3720
+ DocumentationSearch: {
3721
+ component: DocumentationSearch,
3722
+ properties: {
3723
+ currentAppName: {
3724
+ type: String
3725
+ },
3726
+ indexName: {
3727
+ type: String
3728
+ }
3729
+ }
3730
+ },
3731
+ DrawerHeader: {
3732
+ component: DrawerHeader,
3733
+ properties: {
3734
+ closeDrawer: {
3735
+ type: Function,
3736
+ event: false
3737
+ }
3738
+ }
3739
+ },
3703
3740
  DrawerHeading,
3704
- PicobotIframe,
3741
+ PicobotIframe: {
3742
+ component: PicobotIframe,
3743
+ properties: {
3744
+ currentPath: {
3745
+ attribute: false
3746
+ },
3747
+ onChangePath: {
3748
+ type: Function,
3749
+ event: false
3750
+ },
3751
+ onMessage: {
3752
+ type: Function,
3753
+ event: false
3754
+ }
3755
+ }
3756
+ },
3705
3757
  ScrollContainer,
3706
- SwitchView
3758
+ SwitchView: {
3759
+ component: SwitchView,
3760
+ properties: {
3761
+ activeIndex: {
3762
+ type: Number
3763
+ }
3764
+ }
3765
+ }
3707
3766
  },
3708
3767
  args: {
3709
3768
  appName,
@@ -3721,7 +3780,8 @@ const Helpdesk = {
3721
3780
  staticDotPath: "",
3722
3781
  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"
3723
3782
  },
3724
- name: "Helpdesk"
3783
+ name: "Helpdesk",
3784
+ storageExemptPaths: ["email", "phone"]
3725
3785
  };
3726
3786
 
3727
3787
  const Eyebrow = ({
@@ -4306,8 +4366,13 @@ const {
4306
4366
  function NavLinkWithBadge({
4307
4367
  children,
4308
4368
  badge,
4309
- onClick,
4310
- ...rest
4369
+ borderBottomColor,
4370
+ borderBottomStyle,
4371
+ borderBottomWidth,
4372
+ color,
4373
+ fontSize,
4374
+ fontWeight,
4375
+ onClick
4311
4376
  }) {
4312
4377
  return /*#__PURE__*/React.createElement(tapestryReact.StackView, {
4313
4378
  as: "button",
@@ -4317,7 +4382,14 @@ function NavLinkWithBadge({
4317
4382
  paddingBottom: 0.75,
4318
4383
  onClick: () => onClick(),
4319
4384
  spacing: 1,
4320
- ...rest
4385
+ ...{
4386
+ borderBottomColor,
4387
+ borderBottomStyle,
4388
+ borderBottomWidth,
4389
+ color,
4390
+ fontSize,
4391
+ fontWeight
4392
+ }
4321
4393
  }, children, badge && /*#__PURE__*/React.createElement(tapestryReact.Badge, {
4322
4394
  size: "sm",
4323
4395
  fontWeight: "600",
@@ -4369,11 +4441,55 @@ function TasksComponent({
4369
4441
  spacing: 1
4370
4442
  }, /*#__PURE__*/React.createElement(DrawerHeading, null, "To do"), /*#__PURE__*/React.createElement(LoadingIndicator, null)))),
4371
4443
  additionalComponents: {
4372
- DrawerHeader,
4444
+ DrawerHeader: {
4445
+ component: DrawerHeader,
4446
+ properties: {
4447
+ closeDrawer: {
4448
+ event: false,
4449
+ type: Function
4450
+ }
4451
+ }
4452
+ },
4373
4453
  DrawerHeading,
4374
- NavLinkWithBadge,
4454
+ NavLinkWithBadge: {
4455
+ component: NavLinkWithBadge,
4456
+ properties: {
4457
+ badge: {
4458
+ attribute: false
4459
+ },
4460
+ borderBottomColor: {
4461
+ type: String
4462
+ },
4463
+ borderBottomStyle: {
4464
+ type: String
4465
+ },
4466
+ borderBottomWidth: {
4467
+ type: String
4468
+ },
4469
+ color: {
4470
+ type: String
4471
+ },
4472
+ fontSize: {
4473
+ attribute: false
4474
+ },
4475
+ fontWeight: {
4476
+ attribute: false
4477
+ },
4478
+ onClick: {
4479
+ event: false,
4480
+ type: Function
4481
+ }
4482
+ }
4483
+ },
4375
4484
  ScrollContainer,
4376
- SwitchView
4485
+ SwitchView: {
4486
+ component: SwitchView,
4487
+ properties: {
4488
+ activeIndex: {
4489
+ type: Number
4490
+ }
4491
+ }
4492
+ }
4377
4493
  },
4378
4494
  args: {
4379
4495
  closeDrawer,
@@ -4652,6 +4768,13 @@ function isToolPathExemptFromStorage(toolName, path) {
4652
4768
  const tool = toolsRouteMap[toolName];
4653
4769
  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;
4654
4770
  }
4771
+ function scrollToolDrawerToTop(toolName) {
4772
+ var _a;
4773
+ (_a = document.getElementById(`toolbarDrawer${toolName}`)) === null || _a === void 0 ? void 0 : _a.scrollTo({
4774
+ behavior: "smooth",
4775
+ top: 0
4776
+ });
4777
+ }
4655
4778
  const TOOLS_MAP = {
4656
4779
  Chat,
4657
4780
  Helpdesk,
@@ -4721,17 +4844,21 @@ function Toolbar({
4721
4844
  unsubscribe();
4722
4845
  };
4723
4846
  }, [open, clearRoute]);
4847
+ const openHelpdeskAtRoot = React.useCallback(() => {
4848
+ onChangeToolbarFragmentRoute(Helpdesk.name.toLowerCase(), "");
4849
+ scrollToolDrawerToTop(Helpdesk.name);
4850
+ }, [onChangeToolbarFragmentRoute]);
4724
4851
  React.useEffect(() => {
4725
4852
  window.topbar = window.topbar || {};
4726
4853
  window.topbar.openProfile = () => handleToolOnClick(Profile);
4727
- window.topbar.openHelpdesk = () => handleToolOnClick(Helpdesk);
4854
+ window.topbar.openHelpdesk = openHelpdeskAtRoot;
4728
4855
  window.openHelpdesk = window.topbar.openHelpdesk; /* TODO: Remove when products have migrated to window.topbar.openHelpdesk */
4729
4856
  return () => {
4730
4857
  delete window.topbar.openProfile;
4731
4858
  delete window.topbar.openHelpdesk;
4732
4859
  delete window.openHelpdesk; /* TODO: Remove when products have migrated to window.topbar.openHelpdesk */
4733
4860
  };
4734
- }, [Helpdesk, Profile]);
4861
+ }, [Profile, openHelpdeskAtRoot]);
4735
4862
  const loginSettingsUrl = getLoginProfilePath({
4736
4863
  appName: appName.replace(/[\s-]/, ""),
4737
4864
  env: env,
@@ -4813,12 +4940,8 @@ function Toolbar({
4813
4940
  });
4814
4941
  const TOOLS = [Notifications, Tasks, displayChatIcon && Chat].filter(Boolean);
4815
4942
  const handleToolOnClick = tool => {
4816
- var _a;
4817
4943
  toggleDrawer(tool);
4818
- (_a = document.getElementById(`toolbarDrawer${tool.name}`)) === null || _a === void 0 ? void 0 : _a.scrollTo({
4819
- behavior: "smooth",
4820
- top: 0
4821
- });
4944
+ scrollToolDrawerToTop(tool.name);
4822
4945
  };
4823
4946
  const toolSpecificProps = {
4824
4947
  Profile: {