@behindthemusictree/app-kit-ui 0.0.0-stage → 26.1.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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026, Andreas Garcia
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,47 @@
1
- # Temporary Holding Version
1
+ # app-kit-ui
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `@behindthemusictree/app-kit-ui` — the styled BehindTheMusicTree components (popups, OAuth callback
4
+ screen, genre tree) built on the headless `@behindthemusictree/app-kit`. Install it to get the
5
+ BTMT look; skip it and compose your own UI on app-kit's hooks to get a different one.
6
+
7
+ ## Subpaths
8
+
9
+ ```tsx
10
+ import { BasePopup, AuthPopup, NetworkErrorPopup, TrackUploadPopup } from "@behindthemusictree/app-kit-ui/popup";
11
+ import { AuthCallbackHandler } from "@behindthemusictree/app-kit-ui/auth";
12
+ import { GenreTreeView, TrackListSidebar, TrackItem, Rating } from "@behindthemusictree/app-kit-ui/genre-tree";
13
+ import "@behindthemusictree/app-kit-ui/genre-tree/styles.css";
14
+ ```
15
+
16
+ ## Peers
17
+
18
+ `@behindthemusictree/app-kit` (one copy only, so the Session/Player/Popup contexts are shared),
19
+ `@behindthemusictree/ui`, `@tanstack/react-query`, `next`, `react`, `react-dom`. Tailwind must
20
+ scan `node_modules/@behindthemusictree/app-kit-ui/dist/**`.
21
+
22
+ ## Theme contract
23
+
24
+ Colors come from CSS variables, defined by `@behindthemusictree/brand` (`tokens/theme.css`) or by
25
+ your own stylesheet:
26
+
27
+ | Token | Used for |
28
+ | --- | --- |
29
+ | `--color-primary`, `--color-primary-hover` | Primary actions |
30
+ | `--color-text` | Body text |
31
+ | `--color-neutral-100` … `--color-neutral-700` (100, 200, 300, 500, 600, 700) | Surfaces, borders, muted text |
32
+ | `--color-red-500`, `--color-red-600`, `--color-red-700` | Errors |
33
+ | `--color-green-500` | Playing state |
34
+ | `--color-blue-500` | Links and highlights |
35
+
36
+ Third-party brand colors (Spotify, Google) stay literal.
37
+
38
+ `PlayerPanel` also reads the layout tokens `--layout-gutter`, `--layout-band-top`, `--layout-right-w` and `--layout-detail-panel-w` from the same stylesheet.
39
+
40
+ `GenreTreeView` with `placement="regions"` sets `--layout-left-w` to `0px` on the document while its info panel is hidden, so the stylesheet can widen the center column.
41
+
42
+ ## Extension points
43
+
44
+ - `GenreTreeView` takes `className` on its root (no outer margin by default) and
45
+ `showDisplayOptions` (default `true`) to hide the "Tree display options" group.
46
+ - Render props (`renderArtistLink`, `renderSummary`, `renderTracksToolbar`, …) replace pieces of
47
+ the genre detail panel.
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/auth/index.ts
21
+ var auth_exports = {};
22
+ __export(auth_exports, {
23
+ AuthCallbackHandler: () => AuthCallbackHandler
24
+ });
25
+ module.exports = __toCommonJS(auth_exports);
26
+
27
+ // src/auth/AuthCallbackHandler.tsx
28
+ var import_auth = require("@behindthemusictree/app-kit/auth");
29
+ var import_jsx_runtime = require("react/jsx-runtime");
30
+ function AuthCallbackHandler({ renderStatus, ...options }) {
31
+ const state = (0, import_auth.useAuthCallback)(options);
32
+ if (state.status === null) return null;
33
+ if (renderStatus) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderStatus(state) });
34
+ if (state.status === "error") {
35
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "fixed inset-0 z-[100] flex flex-col items-center justify-center bg-[var(--color-neutral-100)] p-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full max-w-md rounded-lg border border-[color-mix(in_srgb,var(--color-red-500)_20%,transparent)] bg-[color-mix(in_srgb,var(--color-red-500)_10%,transparent)] p-4", children: [
36
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "mb-2 font-semibold text-[var(--color-red-500)]", children: "Authentication Error" }),
37
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-[color-mix(in_srgb,var(--color-red-500)_80%,transparent)]", children: state.message }),
38
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
39
+ "button",
40
+ {
41
+ type: "button",
42
+ onClick: state.goHome,
43
+ className: "mt-4 rounded bg-[var(--color-red-600)] px-4 py-2 text-white hover:bg-[var(--color-red-700)]",
44
+ children: "Go to home"
45
+ }
46
+ )
47
+ ] }) });
48
+ }
49
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "fixed inset-0 z-[100] flex flex-col items-center justify-center bg-[var(--color-neutral-100)]", "data-page": "auth-callback-handler", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-center", children: [
50
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "mb-4 text-2xl font-bold", children: "Connecting\u2026" }),
51
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-[var(--color-neutral-600)]", children: "Completing sign-in." })
52
+ ] }) });
53
+ }
54
+ // Annotate the CommonJS export names for ESM import in node:
55
+ 0 && (module.exports = {
56
+ AuthCallbackHandler
57
+ });
58
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/auth/index.ts","../../src/auth/AuthCallbackHandler.tsx"],"sourcesContent":["export { default as AuthCallbackHandler } from \"./AuthCallbackHandler\";\nexport type { AuthCallbackHandlerProps } from \"./AuthCallbackHandler\";\n","\"use client\";\n\nimport { ReactNode } from \"react\";\nimport { useAuthCallback, type AuthCallbackState, type UseAuthCallbackOptions } from \"@behindthemusictree/app-kit/auth\";\n\nexport interface AuthCallbackHandlerProps extends UseAuthCallbackOptions {\n /** Optional custom \"connecting…\" / error UI; defaults to a minimal full-screen overlay. */\n renderStatus?: (state: Exclude<AuthCallbackState, { status: null }>) => ReactNode;\n}\n\n/** Handles OAuth callbacks at layout level. Rendered in the app shell so it runs on every load. */\nexport default function AuthCallbackHandler({ renderStatus, ...options }: AuthCallbackHandlerProps) {\n const state = useAuthCallback(options);\n\n if (state.status === null) return null;\n\n if (renderStatus) return <>{renderStatus(state)}</>;\n\n if (state.status === \"error\") {\n return (\n <div className=\"fixed inset-0 z-[100] flex flex-col items-center justify-center bg-[var(--color-neutral-100)] p-4\">\n <div className=\"w-full max-w-md rounded-lg border border-[color-mix(in_srgb,var(--color-red-500)_20%,transparent)] bg-[color-mix(in_srgb,var(--color-red-500)_10%,transparent)] p-4\">\n <h2 className=\"mb-2 font-semibold text-[var(--color-red-500)]\">Authentication Error</h2>\n <p className=\"text-[color-mix(in_srgb,var(--color-red-500)_80%,transparent)]\">{state.message}</p>\n <button\n type=\"button\"\n onClick={state.goHome}\n className=\"mt-4 rounded bg-[var(--color-red-600)] px-4 py-2 text-white hover:bg-[var(--color-red-700)]\"\n >\n Go to home\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"fixed inset-0 z-[100] flex flex-col items-center justify-center bg-[var(--color-neutral-100)]\" data-page=\"auth-callback-handler\">\n <div className=\"text-center\">\n <h1 className=\"mb-4 text-2xl font-bold\">Connecting…</h1>\n <p className=\"text-[var(--color-neutral-600)]\">Completing sign-in.</p>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGA,kBAAqF;AAa1D;AALZ,SAAR,oBAAqC,EAAE,cAAc,GAAG,QAAQ,GAA6B;AAClG,QAAM,YAAQ,6BAAgB,OAAO;AAErC,MAAI,MAAM,WAAW,KAAM,QAAO;AAElC,MAAI,aAAc,QAAO,2EAAG,uBAAa,KAAK,GAAE;AAEhD,MAAI,MAAM,WAAW,SAAS;AAC5B,WACE,4CAAC,SAAI,WAAU,qGACb,uDAAC,SAAI,WAAU,uKACb;AAAA,kDAAC,QAAG,WAAU,kDAAiD,kCAAoB;AAAA,MACnF,4CAAC,OAAE,WAAU,kEAAkE,gBAAM,SAAQ;AAAA,MAC7F;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM;AAAA,UACf,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,OACF,GACF;AAAA,EAEJ;AAEA,SACE,4CAAC,SAAI,WAAU,iGAAgG,aAAU,yBACvH,uDAAC,SAAI,WAAU,eACb;AAAA,gDAAC,QAAG,WAAU,2BAA0B,8BAAW;AAAA,IACnD,4CAAC,OAAE,WAAU,mCAAkC,iCAAmB;AAAA,KACpE,GACF;AAEJ;","names":[]}
@@ -0,0 +1,14 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { UseAuthCallbackOptions, AuthCallbackState } from '@behindthemusictree/app-kit/auth';
4
+
5
+ interface AuthCallbackHandlerProps extends UseAuthCallbackOptions {
6
+ /** Optional custom "connecting…" / error UI; defaults to a minimal full-screen overlay. */
7
+ renderStatus?: (state: Exclude<AuthCallbackState, {
8
+ status: null;
9
+ }>) => ReactNode;
10
+ }
11
+ /** Handles OAuth callbacks at layout level. Rendered in the app shell so it runs on every load. */
12
+ declare function AuthCallbackHandler({ renderStatus, ...options }: AuthCallbackHandlerProps): react.JSX.Element | null;
13
+
14
+ export { AuthCallbackHandler, type AuthCallbackHandlerProps };
@@ -0,0 +1,7 @@
1
+ import {
2
+ AuthCallbackHandler
3
+ } from "../chunk-MMJCB3CJ.js";
4
+ export {
5
+ AuthCallbackHandler
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}