@behindthemusictree/app-kit-ui 32.0.2 → 33.0.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.
@@ -117,18 +117,21 @@ function AuthErrorPopup({ message, onClose, ...rest }) {
117
117
 
118
118
  // src/popup/NetworkErrorPopup.tsx
119
119
  import { AlertTriangle } from "lucide-react";
120
+ import { ErrorCode } from "@behindthemusictree/app-kit/transport";
120
121
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
121
- function NetworkErrorPopup(props) {
122
+ var OFFLINE_MESSAGE = "It seems that you are not connected to the internet. Please check your connection and try again.";
123
+ var UNREACHABLE_MESSAGE = "We couldn't reach the server. Please try again in a moment.";
124
+ function NetworkErrorPopup({ errorCode, ...rest }) {
122
125
  return /* @__PURE__ */ jsx3(
123
126
  BasePopup,
124
127
  {
125
- ...props,
128
+ ...rest,
126
129
  title: "Network Error",
127
130
  isDismissable: false,
128
131
  icon: AlertTriangle,
129
132
  children: /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center space-y-6 py-4", children: [
130
133
  /* @__PURE__ */ jsx3(AlertTriangle, { className: "h-16 w-16 text-[var(--color-neutral-600)]", strokeWidth: 1.5 }),
131
- /* @__PURE__ */ jsx3("p", { className: "text-center text-[var(--color-neutral-700)]", children: "It seems that you are not connected to the internet. Please check your connection and try again." })
134
+ /* @__PURE__ */ jsx3("p", { className: "text-center text-[var(--color-neutral-700)]", children: errorCode === ErrorCode.NETWORK_OFFLINE ? OFFLINE_MESSAGE : UNREACHABLE_MESSAGE })
132
135
  ] })
133
136
  }
134
137
  );
@@ -271,4 +274,4 @@ export {
271
274
  AuthPopup,
272
275
  SpotifyAuthErrorPopup
273
276
  };
274
- //# sourceMappingURL=chunk-XUC4UJDQ.js.map
277
+ //# sourceMappingURL=chunk-K4WMHUNM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/popup/TrackUploadPopup.tsx","../src/popup/AuthErrorPopup.tsx","../src/popup/NetworkErrorPopup.tsx","../src/popup/AuthPopup.tsx","../src/popup/SpotifyAuthErrorPopup.tsx"],"sourcesContent":["\"use client\";\n\nimport { MdError, MdCheckCircle, MdUpload } from \"react-icons/md\";\nimport { useTrackUpload, type UploadStatus, type UseTrackUploadOptions } from \"@behindthemusictree/app-kit/popup\";\nimport { BasePopup, BasePopupProps } from \"./BasePopup\";\nimport { capitalize, useTrackNoun } from \"@behindthemusictree/app-kit/track-noun\";\n\ntype TrackUploadPopupProps = Omit<BasePopupProps, \"title\" | \"children\" | \"icon\" | \"isDismissable\"> &\n UseTrackUploadOptions & {\n onClose?: () => void;\n };\n\nfunction getStatusIcon(status: UploadStatus) {\n switch (status) {\n case \"success\":\n return <MdCheckCircle className=\"text-[var(--color-green-500)]\" size={20} />;\n case \"error\":\n return <MdError className=\"text-[var(--color-red-500)]\" size={20} />;\n case \"uploading\":\n return <MdUpload className=\"text-[var(--color-blue-500)] animate-pulse\" size={20} />;\n default:\n return <div className=\"w-5 h-5 rounded-full border-2 border-[var(--color-neutral-300)]\" />;\n }\n}\n\nfunction getStatusText(status: UploadStatus) {\n switch (status) {\n case \"success\":\n return \"Uploaded\";\n case \"error\":\n return \"Failed\";\n case \"uploading\":\n return \"Uploading...\";\n default:\n return \"Pending\";\n }\n}\n\nexport default function TrackUploadPopup({\n files,\n genre,\n onProcessFile,\n onComplete,\n onClose,\n uploadTimeoutMs,\n ...rest\n}: TrackUploadPopupProps) {\n const { items, isUploading, allComplete, successfulCount, errorCount } = useTrackUpload({\n files,\n genre,\n onProcessFile,\n onComplete,\n uploadTimeoutMs,\n });\n\n const displayTotal = items.length > 0 ? items.length : files.length;\n const trackNoun = useTrackNoun();\n\n return (\n <BasePopup\n {...rest}\n onClose={onClose}\n title={`Upload ${capitalize(trackNoun.plural)} (${successfulCount}/${displayTotal})`}\n isDismissable\n showOkButton\n okButtonText=\"OK\"\n okButtonDisabled={isUploading || !allComplete}\n onOk={onClose}\n >\n <div className=\"space-y-4\">\n {items.map((item) => (\n <div key={item.id} className=\"border rounded-lg p-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center space-x-3\">\n {getStatusIcon(item.status)}\n <div>\n <div className=\"font-medium text-sm truncate max-w-xs\" title={item.file.name}>\n {item.file.name}\n </div>\n <div className=\"text-xs text-[var(--color-neutral-500)]\">{(item.file.size / 1024 / 1024).toFixed(1)} MB</div>\n </div>\n </div>\n <div className=\"text-sm text-[var(--color-neutral-600)]\">{getStatusText(item.status)}</div>\n </div>\n\n {item.status === \"uploading\" && (\n <div className=\"w-full bg-[var(--color-neutral-200)] rounded-full h-2\">\n <div\n className=\"bg-[var(--color-blue-500)] h-2 rounded-full transition-all duration-300\"\n style={{ width: `${item.progress}%` }}\n />\n </div>\n )}\n\n {item.status === \"error\" && item.error && (\n <div className=\"text-[var(--color-red-500)] text-sm mt-2\">\n {item.error.name === \"InvalidInputError\"\n ? \"Upload failed due to invalid file data. Please check your file and try again.\"\n : item.error.name === \"ZodError\"\n ? \"Upload failed due to a server error. Please try again later.\"\n : item.error.message}\n </div>\n )}\n </div>\n ))}\n\n {allComplete && (\n <div className=\"flex justify-between items-center\">\n <div className=\"text-sm text-[var(--color-neutral-600)]\">\n {successfulCount} successful, {errorCount} failed\n </div>\n </div>\n )}\n </div>\n </BasePopup>\n );\n}\n","\"use client\";\n\nimport { AlertCircle } from \"lucide-react\";\nimport { BasePopup, BasePopupProps } from \"./BasePopup\";\nimport { Button } from \"@behindthemusictree/ui\";\n\ntype AuthErrorPopupProps = Omit<BasePopupProps, \"title\" | \"children\" | \"icon\" | \"isDismissable\"> & {\n message: string;\n onClose: () => void;\n};\n\nexport default function AuthErrorPopup({ message, onClose, ...rest }: AuthErrorPopupProps) {\n return (\n <BasePopup\n {...rest}\n title=\"Sign-in error\"\n isDismissable\n icon={AlertCircle}\n children={\n <div className=\"flex flex-col items-center space-y-6 py-4\">\n <p className=\"text-center text-lg font-medium text-[var(--color-text)]\">{message}</p>\n <Button onClick={onClose} variant=\"secondary\" className=\"w-full max-w-xs\">\n Close\n </Button>\n </div>\n }\n />\n );\n}\n","\"use client\";\n\nimport { AlertTriangle } from \"lucide-react\";\nimport { BasePopup, BasePopupProps } from \"./BasePopup\";\nimport { ErrorCode } from \"@behindthemusictree/app-kit/transport\";\n\ntype NetworkErrorPopupProps = Omit<BasePopupProps, \"title\" | \"children\" | \"icon\" | \"isDismissable\"> & {\n errorCode: ErrorCode;\n};\n\nconst OFFLINE_MESSAGE = \"It seems that you are not connected to the internet. Please check your connection and try again.\";\nconst UNREACHABLE_MESSAGE = \"We couldn't reach the server. Please try again in a moment.\";\n\nexport default function NetworkErrorPopup({ errorCode, ...rest }: NetworkErrorPopupProps) {\n return (\n <BasePopup\n {...rest}\n title=\"Network Error\"\n isDismissable={false}\n icon={AlertTriangle}\n children={\n <div className=\"flex flex-col items-center space-y-6 py-4\">\n <AlertTriangle className=\"h-16 w-16 text-[var(--color-neutral-600)]\" strokeWidth={1.5} />\n <p className=\"text-center text-[var(--color-neutral-700)]\">\n {errorCode === ErrorCode.NETWORK_OFFLINE ? OFFLINE_MESSAGE : UNREACHABLE_MESSAGE}\n </p>\n </div>\n }\n />\n );\n}\n","\"use client\";\n\nimport { ReactNode } from \"react\";\nimport { User } from \"lucide-react\";\nimport { BasePopup, BasePopupProps } from \"./BasePopup\";\nimport { Button } from \"@behindthemusictree/ui\";\nimport { FaSpotify } from \"react-icons/fa\";\nimport { FcGoogle } from \"react-icons/fc\";\n\ntype AuthPopupProps = Omit<BasePopupProps, \"title\" | \"children\" | \"icon\" | \"isDismissable\"> & {\n handleSpotifyOAuth: (redirectAfterAuthPath?: string) => void;\n handleGoogleOAuth?: (redirectAfterAuthPath?: string) => void;\n redirectAfterAuthPath?: string;\n spotifyOnly?: boolean;\n message?: string;\n /**\n * Body copy shown when `spotifyOnly` is true. Wording (app name, feature description) is\n * app-specific, so each consuming app supplies its own instead of this package assuming one.\n */\n spotifyOnlyDescription: ReactNode;\n /** Body copy shown when `spotifyOnly` is false, for the same reason as `spotifyOnlyDescription`. */\n defaultDescription: ReactNode;\n};\n\nexport default function AuthPopup({\n handleSpotifyOAuth,\n handleGoogleOAuth,\n redirectAfterAuthPath,\n spotifyOnly,\n message,\n spotifyOnlyDescription,\n defaultDescription,\n ...rest\n}: AuthPopupProps) {\n const showGoogle = !spotifyOnly && handleGoogleOAuth;\n\n return (\n <BasePopup\n {...rest}\n title={spotifyOnly ? \"Connect with Spotify\" : \"Sign in\"}\n isDismissable={false}\n icon={User}\n type=\"auth\"\n children={\n <div className=\"flex flex-col items-center space-y-7\">\n <div className=\"px-2 text-center\">\n {message && <p className=\"mb-3 text-base font-medium leading-relaxed text-amber-200\">{message}</p>}\n <p className=\"text-lg font-medium leading-relaxed text-white\">\n {spotifyOnly ? spotifyOnlyDescription : defaultDescription}\n </p>\n </div>\n <div className=\"flex w-full flex-col items-center gap-3\">\n <Button\n onClick={() => handleSpotifyOAuth(redirectAfterAuthPath)}\n className=\"relative mb-2 w-fit transform bg-green-600 px-8 py-3 text-white shadow-lg transition-all duration-200 hover:scale-[1.02] hover:bg-green-700 hover:shadow-xl\"\n >\n <span className=\"flex items-center justify-center\">\n <FaSpotify className=\"absolute left-6 text-3xl\" />\n <span className=\"w-full pl-14 pr-8 text-center text-lg font-medium\">Sign in with Spotify</span>\n </span>\n </Button>\n {showGoogle && (\n <Button\n variant=\"outline\"\n onClick={() => handleGoogleOAuth!(redirectAfterAuthPath)}\n className=\"relative w-fit transform border-white bg-white px-8 py-3 text-black shadow-lg transition-all duration-200 hover:scale-[1.02] hover:bg-[var(--color-neutral-100)] hover:shadow-xl\"\n >\n <span className=\"flex items-center justify-center\">\n <FcGoogle className=\"absolute left-6 text-2xl\" />\n <span className=\"w-full pl-14 pr-8 text-center text-lg font-medium text-black\">\n Sign in with Google\n </span>\n </span>\n </Button>\n )}\n </div>\n </div>\n }\n />\n );\n}\n","\"use client\";\n\nimport { FaSpotify } from \"react-icons/fa\";\nimport { BasePopup, BasePopupProps } from \"./BasePopup\";\nimport { Button } from \"@behindthemusictree/ui\";\nimport { User } from \"lucide-react\";\nimport { getSpotifyAllowlistMailtoHref } from \"@behindthemusictree/app-kit/transport\";\n\ntype SpotifyAuthErrorPopupProps = Omit<BasePopupProps, \"title\" | \"children\" | \"icon\" | \"isDismissable\"> & {\n message: string;\n details?: string;\n onClose: () => void;\n /**\n * Support contact email used to build the allowlist-request mailto link. Passed by the\n * consuming app (from whatever env var / config it uses) so this package doesn't assume a\n * specific env var name.\n */\n contactEmail?: string | null;\n};\n\nexport default function SpotifyAuthErrorPopup({\n message,\n details,\n onClose,\n contactEmail = null,\n ...rest\n}: SpotifyAuthErrorPopupProps) {\n const requestAccessHref = getSpotifyAllowlistMailtoHref(contactEmail);\n\n return (\n <BasePopup\n {...rest}\n title=\"Authentication Failed\"\n isDismissable\n icon={User}\n children={\n <div className=\"flex flex-col items-center space-y-8 py-4\">\n <FaSpotify className=\"text-[#1DB954] text-7xl\" />\n <div className=\"space-y-3 text-center\">\n <p className=\"text-xl font-medium text-[var(--color-text)]\">{message}</p>\n {details && (\n <p className=\"text-sm text-[var(--color-neutral-500)] bg-[var(--color-neutral-100)] p-3 rounded-lg border border-[var(--color-neutral-100)]\">{details}</p>\n )}\n <div className=\"space-y-2 text-center\">\n <p className=\"text-base text-[var(--color-neutral-700)]\">\n The Spotify app is in development mode, so only allowlisted accounts can connect.\n </p>\n {requestAccessHref && contactEmail ? (\n <p className=\"text-base text-[var(--color-neutral-700)]\">\n Request access by emailing your{\" \"}\n <a\n href={requestAccessHref}\n className=\"text-[#1DB954] font-medium underline hover:no-underline focus:outline-none focus:ring-2 focus:ring-[#1DB954] focus:ring-offset-1 rounded\"\n >\n Spotify full name and Spotify email address\n </a>{\" \"}\n to{\" \"}\n <a\n href={requestAccessHref}\n className=\"text-[#1DB954] font-medium underline hover:no-underline focus:outline-none focus:ring-2 focus:ring-[#1DB954] focus:ring-offset-1 rounded\"\n >\n {contactEmail}\n </a>\n .\n </p>\n ) : (\n <p className=\"text-base text-[var(--color-neutral-700)]\">To request access, contact the app owner.</p>\n )}\n </div>\n </div>\n <Button\n onClick={onClose}\n className=\"bg-[#1DB954] hover:bg-[#1DB954]/90 text-white w-full max-w-xs transform transition-all duration-200 hover:scale-[1.02] shadow-lg hover:shadow-xl\"\n >\n <FaSpotify className=\"mr-2 text-lg\" />\n Try Again\n </Button>\n </div>\n }\n />\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","Button","jsx","jsxs","FaSpotify","Button","User","jsx","jsxs","FaSpotify"]}
@@ -2573,7 +2573,10 @@ function GenreTreeView({
2573
2573
  const ancestors = /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_genre_tree_view4.GenreNodeAncestors, { ancestorNodes: relation.ancestorNodes, onSelectNode: selectGenreFromPanel });
2574
2574
  const genrePlaylist = genrePlaylistByNodeId.get(node.id);
2575
2575
  const criteria = genrePlaylist?.criteria;
2576
- if (!genrePlaylist || !criteria) return { primary: family, aside: ancestors };
2576
+ if (!genrePlaylist || !criteria) return { primary: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
2577
+ family,
2578
+ ancestors
2579
+ ] }) };
2577
2580
  const genreUuid = criteria.uuid;
2578
2581
  const parentPlaylist = visibleGenrePlaylists.find(({ uuid }) => uuid === genrePlaylist.parent?.uuid);
2579
2582
  const canToggleSide = !readOnly && parentPlaylist !== void 0 && parentPlaylist.parent === null;
@@ -2594,7 +2597,10 @@ function GenreTreeView({
2594
2597
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2595
2598
  GenreInfoPanelBody,
2596
2599
  {
2597
- family,
2600
+ family: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
2601
+ family,
2602
+ ancestors
2603
+ ] }),
2598
2604
  genreUuid,
2599
2605
  genrePlaylist,
2600
2606
  wikidataId: criteria.wikidataId,
@@ -2641,8 +2647,7 @@ function GenreTreeView({
2641
2647
  }
2642
2648
  ),
2643
2649
  renderDangerZone?.(node)
2644
- ] }),
2645
- aside: ancestors
2650
+ ] })
2646
2651
  };
2647
2652
  };
2648
2653
  const isRotationControlled = controlledAllowWheelRotation !== void 0;
@@ -2659,11 +2664,10 @@ function GenreTreeView({
2659
2664
  compact: false
2660
2665
  };
2661
2666
  } else if (relations) {
2662
- const { primary, aside } = renderGenreBody(relations);
2667
+ const { primary } = renderGenreBody(relations);
2663
2668
  activePanel = {
2664
2669
  title: relations.node.name,
2665
2670
  content: primary,
2666
- aside,
2667
2671
  expanded: isExpanded,
2668
2672
  onExpandedChange: changeExpanded,
2669
2673
  onClose: clearSelection,
@@ -3040,12 +3044,14 @@ function GenreDetailPanel({
3040
3044
  expanded,
3041
3045
  onExpandedChange,
3042
3046
  edgeTab,
3043
- aside: ancestors,
3044
3047
  children: [
3045
3048
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3046
3049
  GenreInfoPanelBody,
3047
3050
  {
3048
- family,
3051
+ family: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
3052
+ family,
3053
+ ancestors
3054
+ ] }),
3049
3055
  genreUuid: detail.uuid,
3050
3056
  genrePlaylist: { ...detail.criteriaPlaylist, tracksCount: detail.tracksCount },
3051
3057
  wikidataId: detail.wikidataId,