@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.
@@ -3442,12 +3442,16 @@ var styles = {"toolbar":"toolbar-KHJR5","toolbar-button":"toolbar-button-Ye4h5",
3442
3442
 
3443
3443
  const pcoUrl = pcoUrl$1;
3444
3444
 
3445
+ // The route rides in the iframe URL fragment (`…/topbar#conversations/abc`),
3446
+ // not the path, so updating it is a same-document navigation that doesn't
3447
+ // reload the iframe, but also lets the route survive a forced reload (e.g.
3448
+ // Turbo re-parenting the topbar).
3445
3449
  function buildPicobotSrc(origin, path) {
3446
3450
  const [rawPath, queryPart] = path.replace(/^\/+/, "").split("?", 2);
3447
3451
  const safePath = rawPath.split("/").filter(segment => segment && segment !== "." && segment !== "..").join("/");
3448
- const pathWithPrefix = ["topbar", safePath].filter(Boolean).join("/");
3449
- const relativePath = queryPart !== undefined ? `${pathWithPrefix}?${queryPart}` : pathWithPrefix;
3450
- return new URL(relativePath, origin).toString();
3452
+ const fragment = queryPart !== undefined ? `${safePath}?${queryPart}` : safePath;
3453
+ const base = new URL("topbar", origin).toString();
3454
+ return fragment ? `${base}#${fragment}` : base;
3451
3455
  }
3452
3456
 
3453
3457
  const handleSearchSelect = (hit, indexName) => {
@@ -3599,6 +3603,11 @@ const {
3599
3603
  LoadingIndicator: LoadingIndicator$1,
3600
3604
  StackView: StackView$1
3601
3605
  } = components;
3606
+ function CalendlyWidget(props) {
3607
+ return props.url ? /*#__PURE__*/React__default.createElement(InlineWidget, {
3608
+ ...props
3609
+ }) : null;
3610
+ }
3602
3611
  function HelpdeskComponent({
3603
3612
  appName,
3604
3613
  closeDrawer,
@@ -3615,13 +3624,10 @@ function HelpdeskComponent({
3615
3624
  onMessage
3616
3625
  }) {
3617
3626
  const ref = React__default.useRef(null);
3618
- const initialPath = iframePath || "";
3619
- // Tracks the path picobot last reported via postMessage so an
3620
- // incoming currentPath that matches it doesn't trigger a reload.
3621
- // Picobot sends a bare relative path (e.g. "conversations/abc") with
3622
- // no leading slash or /topbar prefix—buildPicobotSrc adds those.
3623
- const lastReportedPathRef = React__default.useRef(initialPath);
3624
- const [loadedPath, setLoadedPath] = React__default.useState(initialPath);
3627
+ // Keep the fragment in sync in both directions—external opens (deeplink /
3628
+ // Contact support) and picobot's own NEW_ROUTE_RENDERED reports—so it
3629
+ // always reflects the live conversation. See buildPicobotSrc.
3630
+ const [loadedPath, setLoadedPath] = React__default.useState(iframePath || "");
3625
3631
  React__default.useEffect(() => {
3626
3632
  if (!onIframeChangePath && !onMessage) return undefined;
3627
3633
  const handler = e => {
@@ -3631,7 +3637,7 @@ function HelpdeskComponent({
3631
3637
  if (e.source !== ref.current.contentWindow) return;
3632
3638
  if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === "NEW_ROUTE_RENDERED" && onIframeChangePath) {
3633
3639
  const reportedPath = String((_b = e.data.payload) !== null && _b !== void 0 ? _b : "");
3634
- lastReportedPathRef.current = reportedPath;
3640
+ setLoadedPath(reportedPath);
3635
3641
  onIframeChangePath(reportedPath);
3636
3642
  }
3637
3643
  if (onMessage) onMessage(e.data);
@@ -3640,9 +3646,7 @@ function HelpdeskComponent({
3640
3646
  return () => window.removeEventListener("message", handler);
3641
3647
  }, [onIframeChangePath, onMessage]);
3642
3648
  React__default.useEffect(() => {
3643
- const incomingPath = iframePath || "";
3644
- if (lastReportedPathRef.current === incomingPath) return;
3645
- setLoadedPath(incomingPath);
3649
+ setLoadedPath(iframePath || "");
3646
3650
  }, [iframePath]);
3647
3651
  const iframeSrc = buildPicobotSrc(picobotOrigin, loadedPath);
3648
3652
  return /*#__PURE__*/React__default.createElement("iframe", {
@@ -3672,14 +3676,69 @@ function HelpdeskComponent({
3672
3676
  spacing: 1
3673
3677
  }, /*#__PURE__*/React__default.createElement(DrawerHeading, null, "Help and support"), /*#__PURE__*/React__default.createElement(LoadingIndicator$1, null)))),
3674
3678
  additionalComponents: {
3675
- // @ts-expect-error TODO: Relax type specification in add-ons-js to not require children
3676
- CalendlyWidget: InlineWidget,
3677
- DocumentationSearch,
3678
- DrawerHeader,
3679
+ CalendlyWidget: {
3680
+ component: CalendlyWidget,
3681
+ properties: {
3682
+ pageSettings: {
3683
+ attribute: false
3684
+ },
3685
+ prefill: {
3686
+ attribute: false
3687
+ },
3688
+ styles: {
3689
+ attribute: false
3690
+ },
3691
+ url: {
3692
+ type: String
3693
+ }
3694
+ }
3695
+ },
3696
+ DocumentationSearch: {
3697
+ component: DocumentationSearch,
3698
+ properties: {
3699
+ currentAppName: {
3700
+ type: String
3701
+ },
3702
+ indexName: {
3703
+ type: String
3704
+ }
3705
+ }
3706
+ },
3707
+ DrawerHeader: {
3708
+ component: DrawerHeader,
3709
+ properties: {
3710
+ closeDrawer: {
3711
+ type: Function,
3712
+ event: false
3713
+ }
3714
+ }
3715
+ },
3679
3716
  DrawerHeading,
3680
- PicobotIframe,
3717
+ PicobotIframe: {
3718
+ component: PicobotIframe,
3719
+ properties: {
3720
+ currentPath: {
3721
+ attribute: false
3722
+ },
3723
+ onChangePath: {
3724
+ type: Function,
3725
+ event: false
3726
+ },
3727
+ onMessage: {
3728
+ type: Function,
3729
+ event: false
3730
+ }
3731
+ }
3732
+ },
3681
3733
  ScrollContainer,
3682
- SwitchView
3734
+ SwitchView: {
3735
+ component: SwitchView,
3736
+ properties: {
3737
+ activeIndex: {
3738
+ type: Number
3739
+ }
3740
+ }
3741
+ }
3683
3742
  },
3684
3743
  args: {
3685
3744
  appName,
@@ -3697,7 +3756,8 @@ const Helpdesk = {
3697
3756
  staticDotPath: "",
3698
3757
  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"
3699
3758
  },
3700
- name: "Helpdesk"
3759
+ name: "Helpdesk",
3760
+ storageExemptPaths: ["email", "phone"]
3701
3761
  };
3702
3762
 
3703
3763
  const Eyebrow = ({
@@ -4282,8 +4342,13 @@ const {
4282
4342
  function NavLinkWithBadge({
4283
4343
  children,
4284
4344
  badge,
4285
- onClick,
4286
- ...rest
4345
+ borderBottomColor,
4346
+ borderBottomStyle,
4347
+ borderBottomWidth,
4348
+ color,
4349
+ fontSize,
4350
+ fontWeight,
4351
+ onClick
4287
4352
  }) {
4288
4353
  return /*#__PURE__*/React__default.createElement(StackView$2, {
4289
4354
  as: "button",
@@ -4293,7 +4358,14 @@ function NavLinkWithBadge({
4293
4358
  paddingBottom: 0.75,
4294
4359
  onClick: () => onClick(),
4295
4360
  spacing: 1,
4296
- ...rest
4361
+ ...{
4362
+ borderBottomColor,
4363
+ borderBottomStyle,
4364
+ borderBottomWidth,
4365
+ color,
4366
+ fontSize,
4367
+ fontWeight
4368
+ }
4297
4369
  }, children, badge && /*#__PURE__*/React__default.createElement(Badge, {
4298
4370
  size: "sm",
4299
4371
  fontWeight: "600",
@@ -4345,11 +4417,55 @@ function TasksComponent({
4345
4417
  spacing: 1
4346
4418
  }, /*#__PURE__*/React__default.createElement(DrawerHeading, null, "To do"), /*#__PURE__*/React__default.createElement(LoadingIndicator, null)))),
4347
4419
  additionalComponents: {
4348
- DrawerHeader,
4420
+ DrawerHeader: {
4421
+ component: DrawerHeader,
4422
+ properties: {
4423
+ closeDrawer: {
4424
+ event: false,
4425
+ type: Function
4426
+ }
4427
+ }
4428
+ },
4349
4429
  DrawerHeading,
4350
- NavLinkWithBadge,
4430
+ NavLinkWithBadge: {
4431
+ component: NavLinkWithBadge,
4432
+ properties: {
4433
+ badge: {
4434
+ attribute: false
4435
+ },
4436
+ borderBottomColor: {
4437
+ type: String
4438
+ },
4439
+ borderBottomStyle: {
4440
+ type: String
4441
+ },
4442
+ borderBottomWidth: {
4443
+ type: String
4444
+ },
4445
+ color: {
4446
+ type: String
4447
+ },
4448
+ fontSize: {
4449
+ attribute: false
4450
+ },
4451
+ fontWeight: {
4452
+ attribute: false
4453
+ },
4454
+ onClick: {
4455
+ event: false,
4456
+ type: Function
4457
+ }
4458
+ }
4459
+ },
4351
4460
  ScrollContainer,
4352
- SwitchView
4461
+ SwitchView: {
4462
+ component: SwitchView,
4463
+ properties: {
4464
+ activeIndex: {
4465
+ type: Number
4466
+ }
4467
+ }
4468
+ }
4353
4469
  },
4354
4470
  args: {
4355
4471
  closeDrawer,
@@ -4628,6 +4744,13 @@ function isToolPathExemptFromStorage(toolName, path) {
4628
4744
  const tool = toolsRouteMap[toolName];
4629
4745
  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;
4630
4746
  }
4747
+ function scrollToolDrawerToTop(toolName) {
4748
+ var _a;
4749
+ (_a = document.getElementById(`toolbarDrawer${toolName}`)) === null || _a === void 0 ? void 0 : _a.scrollTo({
4750
+ behavior: "smooth",
4751
+ top: 0
4752
+ });
4753
+ }
4631
4754
  const TOOLS_MAP = {
4632
4755
  Chat,
4633
4756
  Helpdesk,
@@ -4697,17 +4820,21 @@ function Toolbar({
4697
4820
  unsubscribe();
4698
4821
  };
4699
4822
  }, [open, clearRoute]);
4823
+ const openHelpdeskAtRoot = useCallback(() => {
4824
+ onChangeToolbarFragmentRoute(Helpdesk.name.toLowerCase(), "");
4825
+ scrollToolDrawerToTop(Helpdesk.name);
4826
+ }, [onChangeToolbarFragmentRoute]);
4700
4827
  React__default.useEffect(() => {
4701
4828
  window.topbar = window.topbar || {};
4702
4829
  window.topbar.openProfile = () => handleToolOnClick(Profile);
4703
- window.topbar.openHelpdesk = () => handleToolOnClick(Helpdesk);
4830
+ window.topbar.openHelpdesk = openHelpdeskAtRoot;
4704
4831
  window.openHelpdesk = window.topbar.openHelpdesk; /* TODO: Remove when products have migrated to window.topbar.openHelpdesk */
4705
4832
  return () => {
4706
4833
  delete window.topbar.openProfile;
4707
4834
  delete window.topbar.openHelpdesk;
4708
4835
  delete window.openHelpdesk; /* TODO: Remove when products have migrated to window.topbar.openHelpdesk */
4709
4836
  };
4710
- }, [Helpdesk, Profile]);
4837
+ }, [Profile, openHelpdeskAtRoot]);
4711
4838
  const loginSettingsUrl = getLoginProfilePath({
4712
4839
  appName: appName.replace(/[\s-]/, ""),
4713
4840
  env: env,
@@ -4789,12 +4916,8 @@ function Toolbar({
4789
4916
  });
4790
4917
  const TOOLS = [Notifications, Tasks, displayChatIcon && Chat].filter(Boolean);
4791
4918
  const handleToolOnClick = tool => {
4792
- var _a;
4793
4919
  toggleDrawer(tool);
4794
- (_a = document.getElementById(`toolbarDrawer${tool.name}`)) === null || _a === void 0 ? void 0 : _a.scrollTo({
4795
- behavior: "smooth",
4796
- top: 0
4797
- });
4920
+ scrollToolDrawerToTop(tool.name);
4798
4921
  };
4799
4922
  const toolSpecificProps = {
4800
4923
  Profile: {