@burdenoff/microfe-vibecontrols 2026.522.2 → 2026.522.4
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/node_modules/@apollo/client/errors/ServerError.js +17 -0
- package/dist/node_modules/@apollo/client/errors/ServerError.js.map +1 -0
- package/dist/node_modules/@apollo/client/errors/ServerParseError.js +17 -0
- package/dist/node_modules/@apollo/client/errors/ServerParseError.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/batch/batchLink.js +28 -0
- package/dist/node_modules/@apollo/client/link/batch/batchLink.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/batch/batching.js +70 -0
- package/dist/node_modules/@apollo/client/link/batch/batching.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/batch-http/BaseBatchHttpLink.js +74 -0
- package/dist/node_modules/@apollo/client/link/batch-http/BaseBatchHttpLink.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/batch-http/batchHttpLink.js +17 -0
- package/dist/node_modules/@apollo/client/link/batch-http/batchHttpLink.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/client-awareness/ClientAwarenessLink.js +32 -0
- package/dist/node_modules/@apollo/client/link/client-awareness/ClientAwarenessLink.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/core/ApolloLink.js +52 -0
- package/dist/node_modules/@apollo/client/link/core/ApolloLink.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/http/checkFetcher.js +9 -0
- package/dist/node_modules/@apollo/client/link/http/checkFetcher.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/http/parseAndCheckHttpResponse.js +45 -0
- package/dist/node_modules/@apollo/client/link/http/parseAndCheckHttpResponse.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/http/selectHttpOptionsAndBody.js +60 -0
- package/dist/node_modules/@apollo/client/link/http/selectHttpOptionsAndBody.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/http/selectURI.js +6 -0
- package/dist/node_modules/@apollo/client/link/http/selectURI.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/utils/createOperation.js +34 -0
- package/dist/node_modules/@apollo/client/link/utils/createOperation.js.map +1 -0
- package/dist/node_modules/@apollo/client/link/utils/filterOperationVariables.js +14 -0
- package/dist/node_modules/@apollo/client/link/utils/filterOperationVariables.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/caching/sizes.js +6 -0
- package/dist/node_modules/@apollo/client/utilities/caching/sizes.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/graphql/print.js +16 -0
- package/dist/node_modules/@apollo/client/utilities/graphql/print.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/caches.js +19 -0
- package/dist/node_modules/@apollo/client/utilities/internal/caches.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/checkDocument.js +21 -0
- package/dist/node_modules/@apollo/client/utilities/internal/checkDocument.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/compact.js +14 -0
- package/dist/node_modules/@apollo/client/utilities/internal/compact.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js +9 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getOperationDefinition.js +9 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getOperationDefinition.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getOperationName.js +8 -0
- package/dist/node_modules/@apollo/client/utilities/internal/getOperationName.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/globals/global.js +9 -0
- package/dist/node_modules/@apollo/client/utilities/internal/globals/global.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/globals/maybe.js +10 -0
- package/dist/node_modules/@apollo/client/utilities/internal/globals/maybe.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/makeUniqueId.js +10 -0
- package/dist/node_modules/@apollo/client/utilities/internal/makeUniqueId.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/memoize.js +23 -0
- package/dist/node_modules/@apollo/client/utilities/internal/memoize.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/internal/stringifyForDisplay.js +10 -0
- package/dist/node_modules/@apollo/client/utilities/internal/stringifyForDisplay.js.map +1 -0
- package/dist/node_modules/@apollo/client/utilities/invariant/index.js +57 -0
- package/dist/node_modules/@apollo/client/utilities/invariant/index.js.map +1 -0
- package/dist/node_modules/@apollo/client/version.js +6 -0
- package/dist/node_modules/@apollo/client/version.js.map +1 -0
- package/dist/node_modules/@wry/caches/lib/weak.js +67 -0
- package/dist/node_modules/@wry/caches/lib/weak.js.map +1 -0
- package/dist/node_modules/@wry/trie/lib/index.js +53 -0
- package/dist/node_modules/@wry/trie/lib/index.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/NotificationFactories.js +21 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/NotificationFactories.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Observable.js +78 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Observable.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Subscriber.js +117 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Subscriber.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Subscription.js +93 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/Subscription.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/config.js +12 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/config.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/observable/empty.js +9 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/observable/empty.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/observable/throwError.js +17 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/observable/throwError.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js +16 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/symbol/observable.js +8 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/symbol/observable.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js +13 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js +11 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js +11 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/errorContext.js +22 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/errorContext.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/identity.js +8 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/identity.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/isFunction.js +8 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/isFunction.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/noop.js +6 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/noop.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/pipe.js +13 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/pipe.js.map +1 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js +14 -0
- package/dist/node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js.map +1 -0
- package/dist/node_modules/rxjs/node_modules/tslib/tslib.es6.js +52 -0
- package/dist/node_modules/rxjs/node_modules/tslib/tslib.es6.js.map +1 -0
- package/dist/pages/AgentsPage.js +242 -239
- package/dist/pages/AgentsPage.js.map +1 -1
- package/dist/pages/CatalogPage.js +146 -98
- package/dist/pages/CatalogPage.js.map +1 -1
- package/dist/pages/ComponentsPage.js +163 -117
- package/dist/pages/ComponentsPage.js.map +1 -1
- package/dist/pages/TemplatesPage.js +74 -26
- package/dist/pages/TemplatesPage.js.map +1 -1
- package/dist/providers/VibeControlsProvider.js +35 -30
- package/dist/providers/VibeControlsProvider.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,51 +5,58 @@ import { ErrorState as i } from "../components/shared/ErrorState.js";
|
|
|
5
5
|
import { EntityTagPicker as a } from "../components/shared/EntityTagPicker.js";
|
|
6
6
|
import { useDraftEntityTags as o } from "../hooks/useDraftEntityTags.js";
|
|
7
7
|
import { EmptyState as s } from "../components/shared/EmptyState.js";
|
|
8
|
-
import { SearchInput as
|
|
9
|
-
import { FilterDropdown as
|
|
10
|
-
import { GetHelpButton as
|
|
8
|
+
import { SearchInput as ee } from "../components/shared/SearchInput.js";
|
|
9
|
+
import { FilterDropdown as c } from "../components/shared/FilterDropdown.js";
|
|
10
|
+
import { GetHelpButton as l } from "../components/shared/GetHelpButton.js";
|
|
11
11
|
import "../components/shared/index.js";
|
|
12
|
-
import { VIBE_PERMISSIONS as
|
|
13
|
-
import { PageSkeleton as
|
|
14
|
-
import { CatalogCard as
|
|
15
|
-
import { CatalogForm as
|
|
12
|
+
import { VIBE_PERMISSIONS as u } from "../constants/permissions.js";
|
|
13
|
+
import { PageSkeleton as d } from "../components/shared/PageSkeleton.js";
|
|
14
|
+
import { CatalogCard as f } from "../components/catalog/CatalogCard.js";
|
|
15
|
+
import { CatalogForm as p } from "../components/catalog/CatalogForm.js";
|
|
16
16
|
import "../components/catalog/index.js";
|
|
17
|
-
import { useCallback as
|
|
18
|
-
import { useI18n as
|
|
19
|
-
import { BookOpen as
|
|
20
|
-
import { usePermissions as
|
|
21
|
-
import { AnimatePresence as
|
|
22
|
-
import { jsx as
|
|
23
|
-
import { MotionItem as
|
|
17
|
+
import { useCallback as m, useEffect as h, useState as g } from "react";
|
|
18
|
+
import { useI18n as te } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
19
|
+
import { BookOpen as ne, Plus as _, RefreshCw as v } from "lucide-react";
|
|
20
|
+
import { usePermissions as y } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
21
|
+
import { AnimatePresence as b } from "framer-motion";
|
|
22
|
+
import { jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
23
|
+
import { MotionItem as C, MotionList as w, MotionPage as T } from "@burdenoff/fe-libs/shared/motion";
|
|
24
24
|
//#region src/pages/CatalogPage.tsx
|
|
25
|
-
function
|
|
26
|
-
let
|
|
27
|
-
let r =
|
|
25
|
+
function E() {
|
|
26
|
+
let E = n(), { t: D } = te(), { hasPermission: re, isLoading: ie } = y(), O = m((e, t, n) => {
|
|
27
|
+
let r = D(e, n), i = r === e ? t : r;
|
|
28
28
|
return n ? Object.entries(n).reduce((e, [t, n]) => e.replace(`{{${t}}}`, String(n)), i) : i;
|
|
29
|
-
}, [
|
|
29
|
+
}, [D]), k = [
|
|
30
30
|
{
|
|
31
31
|
value: "all",
|
|
32
|
-
label:
|
|
32
|
+
label: O("catalog.allVisibility", "All Visibility")
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
value: "PRIVATE",
|
|
36
|
-
label:
|
|
36
|
+
label: O("catalog.visibilityPrivate", "Private")
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
value: "INTERNAL",
|
|
40
|
-
label:
|
|
40
|
+
label: O("catalog.visibilityInternal", "Internal")
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
value: "PUBLIC",
|
|
44
|
-
label:
|
|
44
|
+
label: O("catalog.visibilityPublic", "Public")
|
|
45
45
|
}
|
|
46
|
-
], [
|
|
46
|
+
], [A, j] = g(""), [M, N] = g("all"), [P, F] = g(!1), [I, L] = g(null), [R, z] = g([]), [B, V] = g(!1), { data: H, loading: U, error: W, refetch: G, fetchMore: K } = t({
|
|
47
47
|
variables: {
|
|
48
|
-
filter: {
|
|
49
|
-
|
|
48
|
+
filter: {
|
|
49
|
+
visibility: M === "all" ? void 0 : M,
|
|
50
|
+
search: A || void 0
|
|
51
|
+
},
|
|
52
|
+
pagination: {
|
|
53
|
+
limit: 50,
|
|
54
|
+
offset: 0
|
|
55
|
+
}
|
|
50
56
|
},
|
|
51
|
-
fetchPolicy: "cache-and-network"
|
|
52
|
-
|
|
57
|
+
fetchPolicy: "cache-and-network",
|
|
58
|
+
notifyOnNetworkStatusChange: !0
|
|
59
|
+
}), [q] = e({ refetchQueries: ["ListCatalogs"] }), { setDraftTagIds: J, flushTags: ae } = o("VIBECONTROLS_CATALOG"), Y = m((e) => e.map((e) => ({
|
|
53
60
|
id: e.id,
|
|
54
61
|
name: e.name,
|
|
55
62
|
description: e.description || null,
|
|
@@ -59,119 +66,160 @@ function k() {
|
|
|
59
66
|
tags: e.tags || [],
|
|
60
67
|
createdAt: e.createdAt,
|
|
61
68
|
updatedAt: e.updatedAt
|
|
62
|
-
})), [
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
})), []);
|
|
70
|
+
h(() => {
|
|
71
|
+
z(Y(H?.vibecontrolsCatalogs?.items ?? []));
|
|
72
|
+
}, [H?.vibecontrolsCatalogs?.items, Y]);
|
|
73
|
+
let X = H?.vibecontrolsCatalogs?.total ?? 0, Z = R.length < X, Q = R, $ = R, oe = m(async () => {
|
|
74
|
+
if (!(B || !Z)) {
|
|
75
|
+
V(!0);
|
|
76
|
+
try {
|
|
77
|
+
await K({
|
|
78
|
+
variables: { pagination: {
|
|
79
|
+
limit: 50,
|
|
80
|
+
offset: R.length
|
|
81
|
+
} },
|
|
82
|
+
updateQuery: (e, { fetchMoreResult: t }) => {
|
|
83
|
+
if (!t?.vibecontrolsCatalogs) return e;
|
|
84
|
+
let n = e.vibecontrolsCatalogs, r = t.vibecontrolsCatalogs;
|
|
85
|
+
return {
|
|
86
|
+
...e,
|
|
87
|
+
vibecontrolsCatalogs: {
|
|
88
|
+
...r,
|
|
89
|
+
items: [...n?.items ?? [], ...r.items],
|
|
90
|
+
total: r.total,
|
|
91
|
+
hasMore: r.hasMore
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
} finally {
|
|
97
|
+
V(!1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}, [
|
|
101
|
+
K,
|
|
102
|
+
R.length,
|
|
103
|
+
B,
|
|
104
|
+
Z
|
|
105
|
+
]);
|
|
106
|
+
if (ie) return /* @__PURE__ */ x("div", {
|
|
68
107
|
className: "flex items-center justify-center min-h-[400px]",
|
|
69
|
-
children: /* @__PURE__ */
|
|
108
|
+
children: /* @__PURE__ */ x("p", {
|
|
70
109
|
className: "text-text-secondary",
|
|
71
110
|
children: "Loading permissions..."
|
|
72
111
|
})
|
|
73
112
|
});
|
|
74
|
-
if (!
|
|
113
|
+
if (!re(u.VIBE_LIST)) return /* @__PURE__ */ x("div", {
|
|
75
114
|
className: "flex items-center justify-center min-h-[400px]",
|
|
76
|
-
children: /* @__PURE__ */
|
|
115
|
+
children: /* @__PURE__ */ S("div", {
|
|
77
116
|
className: "text-center space-y-2",
|
|
78
|
-
children: [/* @__PURE__ */
|
|
117
|
+
children: [/* @__PURE__ */ x("h2", {
|
|
79
118
|
className: "text-lg font-semibold text-foreground",
|
|
80
119
|
children: "Access Denied"
|
|
81
|
-
}), /* @__PURE__ */
|
|
120
|
+
}), /* @__PURE__ */ x("p", {
|
|
82
121
|
className: "text-sm text-text-secondary",
|
|
83
122
|
children: "You don't have permission to access this page."
|
|
84
123
|
})]
|
|
85
124
|
})
|
|
86
125
|
});
|
|
87
|
-
let
|
|
88
|
-
|
|
126
|
+
let se = (e) => {
|
|
127
|
+
E(`/catalogs/${e.id}`);
|
|
89
128
|
};
|
|
90
|
-
return
|
|
129
|
+
return W && $.length === 0 ? /* @__PURE__ */ x(T, {
|
|
91
130
|
className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
|
|
92
|
-
children: /* @__PURE__ */
|
|
93
|
-
title:
|
|
94
|
-
message:
|
|
95
|
-
onRetry: () =>
|
|
131
|
+
children: /* @__PURE__ */ x(i, {
|
|
132
|
+
title: O("catalog.failedLoad", "Failed to load catalogs"),
|
|
133
|
+
message: W.message,
|
|
134
|
+
onRetry: () => G()
|
|
96
135
|
})
|
|
97
|
-
}) : /* @__PURE__ */ T
|
|
136
|
+
}) : /* @__PURE__ */ S(T, {
|
|
98
137
|
className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
|
|
99
138
|
children: [
|
|
100
|
-
/* @__PURE__ */
|
|
101
|
-
title:
|
|
102
|
-
description:
|
|
103
|
-
actions: /* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ x(r, {
|
|
140
|
+
title: O("catalog.title", "Catalogs"),
|
|
141
|
+
description: O("catalog.description", "{{total}} catalogs", { total: $.length }),
|
|
142
|
+
actions: /* @__PURE__ */ S("div", {
|
|
104
143
|
className: "flex items-center gap-2",
|
|
105
|
-
children: [/* @__PURE__ */
|
|
106
|
-
onClick: () =>
|
|
107
|
-
disabled:
|
|
144
|
+
children: [/* @__PURE__ */ x("button", {
|
|
145
|
+
onClick: () => G(),
|
|
146
|
+
disabled: U,
|
|
108
147
|
className: "flex items-center gap-2 px-3 py-2 text-text-secondary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50",
|
|
109
|
-
title:
|
|
110
|
-
children: /* @__PURE__ */
|
|
111
|
-
}), /* @__PURE__ */
|
|
112
|
-
onClick: () =>
|
|
148
|
+
title: O("common.refresh", "Refresh"),
|
|
149
|
+
children: /* @__PURE__ */ x(v, { className: `w-4 h-4 ${U ? "animate-spin" : ""}` })
|
|
150
|
+
}), /* @__PURE__ */ S("button", {
|
|
151
|
+
onClick: () => F(!0),
|
|
113
152
|
className: "flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors",
|
|
114
|
-
children: [/* @__PURE__ */
|
|
153
|
+
children: [/* @__PURE__ */ x(_, { className: "w-4 h-4" }), O("catalog.createCatalog", "Create Catalog")]
|
|
115
154
|
})]
|
|
116
155
|
})
|
|
117
156
|
}),
|
|
118
|
-
/* @__PURE__ */
|
|
157
|
+
/* @__PURE__ */ S("div", {
|
|
119
158
|
className: "flex items-center gap-2 sm:gap-3 flex-wrap",
|
|
120
|
-
children: [/* @__PURE__ */
|
|
121
|
-
value:
|
|
122
|
-
onChange:
|
|
123
|
-
placeholder:
|
|
159
|
+
children: [/* @__PURE__ */ x(ee, {
|
|
160
|
+
value: A,
|
|
161
|
+
onChange: j,
|
|
162
|
+
placeholder: O("catalog.searchPlaceholder", "Search catalogs..."),
|
|
124
163
|
className: "flex-1 sm:w-64 sm:flex-none"
|
|
125
|
-
}), /* @__PURE__ */
|
|
126
|
-
label:
|
|
127
|
-
value:
|
|
128
|
-
options:
|
|
129
|
-
onChange:
|
|
164
|
+
}), /* @__PURE__ */ x(c, {
|
|
165
|
+
label: O("catalog.filterVisibility", "Visibility"),
|
|
166
|
+
value: M,
|
|
167
|
+
options: k,
|
|
168
|
+
onChange: N
|
|
130
169
|
})]
|
|
131
170
|
}),
|
|
132
|
-
|
|
171
|
+
/* @__PURE__ */ S("p", {
|
|
133
172
|
className: "text-sm text-text-secondary",
|
|
134
|
-
children: [
|
|
135
|
-
filtered:
|
|
136
|
-
total: X
|
|
137
|
-
}),
|
|
173
|
+
children: [O("catalog.showingResults", "Showing {{filtered}} of {{total}} catalogs", {
|
|
174
|
+
filtered: Q.length,
|
|
175
|
+
total: X
|
|
176
|
+
}), U && /* @__PURE__ */ x("span", {
|
|
138
177
|
className: "ml-2 text-text-muted",
|
|
139
|
-
children:
|
|
178
|
+
children: O("common.refreshing", "(refreshing...)")
|
|
140
179
|
})]
|
|
141
180
|
}),
|
|
142
|
-
|
|
181
|
+
U && $.length === 0 ? /* @__PURE__ */ x(d, {
|
|
143
182
|
variant: "cards",
|
|
144
183
|
count: 6
|
|
145
|
-
}) :
|
|
184
|
+
}) : Q.length > 0 ? /* @__PURE__ */ x(b, {
|
|
146
185
|
mode: "wait",
|
|
147
|
-
children: /* @__PURE__ */ w
|
|
186
|
+
children: /* @__PURE__ */ x(w, {
|
|
148
187
|
stagger: .04,
|
|
149
188
|
className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
|
|
150
|
-
children:
|
|
189
|
+
children: Q.map((e) => /* @__PURE__ */ x(C, { children: /* @__PURE__ */ x(f, {
|
|
151
190
|
catalog: e,
|
|
152
|
-
onOpen:
|
|
191
|
+
onOpen: se
|
|
153
192
|
}) }, e.id))
|
|
154
193
|
}, "catalog-grid")
|
|
155
|
-
}) : /* @__PURE__ */
|
|
156
|
-
icon: /* @__PURE__ */
|
|
157
|
-
title:
|
|
158
|
-
description:
|
|
159
|
-
action: !
|
|
194
|
+
}) : /* @__PURE__ */ x(s, {
|
|
195
|
+
icon: /* @__PURE__ */ x(ne, { className: "w-8 h-8 text-text-secondary" }),
|
|
196
|
+
title: A || M !== "all" ? O("catalog.emptyNoResults", "No catalogs found") : O("catalog.emptyNoCatalogs", "No catalogs yet"),
|
|
197
|
+
description: A || M !== "all" ? O("catalog.emptyAdjustSearch", "Try adjusting your search or filters") : O("catalog.emptyCreate", "Create your first catalog to organize components"),
|
|
198
|
+
action: !A && M === "all" ? /* @__PURE__ */ S("div", {
|
|
160
199
|
className: "flex items-center gap-2",
|
|
161
|
-
children: [/* @__PURE__ */
|
|
162
|
-
onClick: () =>
|
|
200
|
+
children: [/* @__PURE__ */ S("button", {
|
|
201
|
+
onClick: () => F(!0),
|
|
163
202
|
className: "flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors",
|
|
164
|
-
children: [/* @__PURE__ */
|
|
165
|
-
}), /* @__PURE__ */
|
|
203
|
+
children: [/* @__PURE__ */ x(_, { className: "w-4 h-4" }), O("catalog.createCatalog", "Create Catalog")]
|
|
204
|
+
}), /* @__PURE__ */ x(l, { prompt: "What is a Catalog in VibeControls and how do I create one?" })]
|
|
166
205
|
}) : void 0
|
|
167
206
|
}),
|
|
168
|
-
|
|
207
|
+
Z && Q.length > 0 && /* @__PURE__ */ x("div", {
|
|
208
|
+
className: "flex justify-center pt-2",
|
|
209
|
+
children: /* @__PURE__ */ x("button", {
|
|
210
|
+
onClick: oe,
|
|
211
|
+
disabled: B,
|
|
212
|
+
className: "flex items-center gap-2 px-4 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken-hover transition-colors disabled:opacity-50",
|
|
213
|
+
children: B ? O("common.loading", "Loading...") : O("common.loadMore", "Load more")
|
|
214
|
+
})
|
|
215
|
+
}),
|
|
216
|
+
I && /* @__PURE__ */ x("div", {
|
|
169
217
|
className: "fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-success-bg text-status-success-text rounded-md shadow-lg text-sm",
|
|
170
|
-
children:
|
|
218
|
+
children: I
|
|
171
219
|
}),
|
|
172
|
-
/* @__PURE__ */
|
|
173
|
-
isOpen:
|
|
174
|
-
onClose: () =>
|
|
220
|
+
/* @__PURE__ */ x(p, {
|
|
221
|
+
isOpen: P,
|
|
222
|
+
onClose: () => F(!1),
|
|
175
223
|
onSubmit: async (e) => {
|
|
176
224
|
let t = (await q({ variables: { input: {
|
|
177
225
|
name: e.name,
|
|
@@ -180,12 +228,12 @@ function k() {
|
|
|
180
228
|
ownerName: e.owner || void 0,
|
|
181
229
|
tags: e.tags.length > 0 ? e.tags : void 0
|
|
182
230
|
} } })).data?.createVibecontrolsCatalog?.id;
|
|
183
|
-
t && await
|
|
231
|
+
t && await ae(t), L(O("catalog.createdSuccess", "Catalog created successfully")), setTimeout(() => L(null), 3e3);
|
|
184
232
|
},
|
|
185
|
-
extraSection: /* @__PURE__ */
|
|
233
|
+
extraSection: /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("h3", {
|
|
186
234
|
className: "text-sm font-medium text-text-secondary mb-2",
|
|
187
|
-
children:
|
|
188
|
-
}), /* @__PURE__ */
|
|
235
|
+
children: O("catalog.tags", "Tags")
|
|
236
|
+
}), /* @__PURE__ */ x(a, {
|
|
189
237
|
entityType: "VIBECONTROLS_CATALOG",
|
|
190
238
|
onDraftChange: J
|
|
191
239
|
})] })
|
|
@@ -194,6 +242,6 @@ function k() {
|
|
|
194
242
|
});
|
|
195
243
|
}
|
|
196
244
|
//#endregion
|
|
197
|
-
export {
|
|
245
|
+
export { E as CatalogPage };
|
|
198
246
|
|
|
199
247
|
//# sourceMappingURL=CatalogPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CatalogPage.js","names":[],"sources":["../../src/pages/CatalogPage.tsx"],"sourcesContent":["import { useState, useMemo, useCallback } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { Plus, BookOpen, RefreshCw } from 'lucide-react';\nimport { CatalogCard } from '@/components/catalog';\nimport type { CatalogCardData } from '@/components/catalog';\nimport { CatalogForm } from '@/components/catalog';\nimport type { CatalogFormData } from '@/components/catalog';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useDraftEntityTags } from '@/hooks/useDraftEntityTags';\nimport {\n PageHeader,\n SearchInput,\n FilterDropdown,\n EmptyState,\n ErrorState,\n GetHelpButton,\n} from '@/components/shared';\nimport { MotionPage, MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\nimport { AnimatePresence } from 'framer-motion';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useListCatalogsQuery, useCreateCatalogMutation } from '@/generated/wspace-operations';\n\nexport function CatalogPage() {\n const navigate = useVibeNavigate();\n const { t } = useI18n();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n if (!params) return template;\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n },\n [t]\n );\n\n const visibilityOptions = [\n { value: 'all', label: tr('catalog.allVisibility', 'All Visibility') },\n { value: 'PRIVATE', label: tr('catalog.visibilityPrivate', 'Private') },\n { value: 'INTERNAL', label: tr('catalog.visibilityInternal', 'Internal') },\n { value: 'PUBLIC', label: tr('catalog.visibilityPublic', 'Public') },\n ];\n\n const [searchQuery, setSearchQuery] = useState('');\n const [visibilityFilter, setVisibilityFilter] = useState('all');\n const [showCreateForm, setShowCreateForm] = useState(false);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n\n const { data, loading, error, refetch } = useListCatalogsQuery({\n variables: {\n filter: {\n visibility:\n visibilityFilter !== 'all'\n ? (visibilityFilter as 'PRIVATE' | 'INTERNAL' | 'PUBLIC')\n : undefined,\n },\n ...(searchQuery ? { pagination: { limit: 1000 } } : {}),\n },\n fetchPolicy: 'cache-and-network',\n });\n\n const [createCatalog] = useCreateCatalogMutation({ refetchQueries: ['ListCatalogs'] });\n const { setDraftTagIds, flushTags } = useDraftEntityTags('VIBECONTROLS_CATALOG');\n\n const catalogs: CatalogCardData[] = useMemo(() => {\n const items = data?.vibecontrolsCatalogs?.items ?? [];\n return items.map((item: Record<string, unknown>) => ({\n id: item.id as string,\n name: item.name as string,\n description: (item.description as string) || null,\n visibility: item.visibility as CatalogCardData['visibility'],\n componentCount: (item.componentCount as number) || 0,\n vibeCount: (item.vibeCount as number) || 0,\n tags: (item.tags as string[]) || [],\n createdAt: item.createdAt as string,\n updatedAt: item.updatedAt as string,\n }));\n }, [data?.vibecontrolsCatalogs?.items]);\n\n const filteredCatalogs = useMemo(() => {\n if (!searchQuery) return catalogs;\n const query = searchQuery.toLowerCase();\n return catalogs.filter(\n (c) =>\n c.name.toLowerCase().includes(query) ||\n c.description?.toLowerCase().includes(query) ||\n c.tags?.some((tag) => tag.toLowerCase().includes(query))\n );\n }, [catalogs, searchQuery]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions...</p>\n </div>\n );\n if (!hasPermission(VIBE_PERMISSIONS.VIBE_LIST))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const handleCatalogSelect = (catalog: CatalogCardData) => {\n navigate(`/catalogs/${catalog.id}`);\n };\n\n const handleCreateCatalog = async (formData: CatalogFormData) => {\n const res = await createCatalog({\n variables: {\n input: {\n name: formData.name,\n description: formData.description || undefined,\n visibility: formData.visibility,\n ownerName: formData.owner || undefined,\n tags: formData.tags.length > 0 ? formData.tags : undefined,\n },\n },\n });\n const newCatalogId = res.data?.createVibecontrolsCatalog?.id;\n if (newCatalogId) await flushTags(newCatalogId);\n setSuccessMessage(tr('catalog.createdSuccess', 'Catalog created successfully'));\n setTimeout(() => setSuccessMessage(null), 3000);\n };\n\n if (error && catalogs.length === 0) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <ErrorState\n title={tr('catalog.failedLoad', 'Failed to load catalogs')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <PageHeader\n title={tr('catalog.title', 'Catalogs')}\n description={tr('catalog.description', '{{total}} catalogs', {\n total: catalogs.length,\n })}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-2 text-text-secondary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n title={tr('common.refresh', 'Refresh')}\n >\n <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n <button\n onClick={() => setShowCreateForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('catalog.createCatalog', 'Create Catalog')}\n </button>\n </div>\n }\n />\n\n {/* Filters */}\n <div className=\"flex items-center gap-2 sm:gap-3 flex-wrap\">\n <SearchInput\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder={tr('catalog.searchPlaceholder', 'Search catalogs...')}\n className=\"flex-1 sm:w-64 sm:flex-none\"\n />\n <FilterDropdown\n label={tr('catalog.filterVisibility', 'Visibility')}\n value={visibilityFilter}\n options={visibilityOptions}\n onChange={setVisibilityFilter}\n />\n </div>\n\n {/* Results count */}\n {(searchQuery || visibilityFilter !== 'all') && (\n <p className=\"text-sm text-text-secondary\">\n {tr('catalog.showingResults', 'Showing {{filtered}} of {{total}} catalogs', {\n filtered: filteredCatalogs.length,\n total: catalogs.length,\n })}\n {loading && (\n <span className=\"ml-2 text-text-muted\">\n {tr('common.refreshing', '(refreshing...)')}\n </span>\n )}\n </p>\n )}\n\n {/* Grid */}\n {loading && catalogs.length === 0 ? (\n <PageSkeleton variant=\"cards\" count={6} />\n ) : filteredCatalogs.length > 0 ? (\n <AnimatePresence mode=\"wait\">\n <MotionList\n key=\"catalog-grid\"\n stagger={0.04}\n className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\"\n >\n {filteredCatalogs.map((catalog) => (\n <MotionItem key={catalog.id}>\n <CatalogCard catalog={catalog} onOpen={handleCatalogSelect} />\n </MotionItem>\n ))}\n </MotionList>\n </AnimatePresence>\n ) : (\n <EmptyState\n icon={<BookOpen className=\"w-8 h-8 text-text-secondary\" />}\n title={\n searchQuery || visibilityFilter !== 'all'\n ? tr('catalog.emptyNoResults', 'No catalogs found')\n : tr('catalog.emptyNoCatalogs', 'No catalogs yet')\n }\n description={\n searchQuery || visibilityFilter !== 'all'\n ? tr('catalog.emptyAdjustSearch', 'Try adjusting your search or filters')\n : tr('catalog.emptyCreate', 'Create your first catalog to organize components')\n }\n action={\n !searchQuery && visibilityFilter === 'all' ? (\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setShowCreateForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('catalog.createCatalog', 'Create Catalog')}\n </button>\n <GetHelpButton prompt=\"What is a Catalog in VibeControls and how do I create one?\" />\n </div>\n ) : undefined\n }\n />\n )}\n\n {/* Success Toast */}\n {successMessage && (\n <div className=\"fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-success-bg text-status-success-text rounded-md shadow-lg text-sm\">\n {successMessage}\n </div>\n )}\n\n {/* Create Form */}\n <CatalogForm\n isOpen={showCreateForm}\n onClose={() => setShowCreateForm(false)}\n onSubmit={handleCreateCatalog}\n extraSection={\n <div>\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">\n {tr('catalog.tags', 'Tags')}\n </h3>\n <EntityTagPicker entityType=\"VIBECONTROLS_CATALOG\" onDraftChange={setDraftTagIds} />\n </div>\n }\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CatalogPage.js","names":[],"sources":["../../src/pages/CatalogPage.tsx"],"sourcesContent":["import { useState, useCallback, useEffect } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { Plus, BookOpen, RefreshCw } from 'lucide-react';\nimport { CatalogCard } from '@/components/catalog';\nimport type { CatalogCardData } from '@/components/catalog';\nimport { CatalogForm } from '@/components/catalog';\nimport type { CatalogFormData } from '@/components/catalog';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useDraftEntityTags } from '@/hooks/useDraftEntityTags';\nimport {\n PageHeader,\n SearchInput,\n FilterDropdown,\n EmptyState,\n ErrorState,\n GetHelpButton,\n} from '@/components/shared';\nimport { MotionPage, MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\nimport { AnimatePresence } from 'framer-motion';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useListCatalogsQuery, useCreateCatalogMutation } from '@/generated/wspace-operations';\n\nexport function CatalogPage() {\n const navigate = useVibeNavigate();\n const { t } = useI18n();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n if (!params) return template;\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n },\n [t]\n );\n\n const visibilityOptions = [\n { value: 'all', label: tr('catalog.allVisibility', 'All Visibility') },\n { value: 'PRIVATE', label: tr('catalog.visibilityPrivate', 'Private') },\n { value: 'INTERNAL', label: tr('catalog.visibilityInternal', 'Internal') },\n { value: 'PUBLIC', label: tr('catalog.visibilityPublic', 'Public') },\n ];\n\n const PAGE_SIZE = 50;\n const [searchQuery, setSearchQuery] = useState('');\n const [visibilityFilter, setVisibilityFilter] = useState('all');\n const [showCreateForm, setShowCreateForm] = useState(false);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [accumulated, setAccumulated] = useState<CatalogCardData[]>([]);\n const [loadingMore, setLoadingMore] = useState(false);\n\n const { data, loading, error, refetch, fetchMore } = useListCatalogsQuery({\n variables: {\n filter: {\n visibility:\n visibilityFilter !== 'all'\n ? (visibilityFilter as 'PRIVATE' | 'INTERNAL' | 'PUBLIC')\n : undefined,\n search: searchQuery || undefined,\n },\n pagination: { limit: PAGE_SIZE, offset: 0 },\n },\n fetchPolicy: 'cache-and-network',\n notifyOnNetworkStatusChange: true,\n });\n\n const [createCatalog] = useCreateCatalogMutation({ refetchQueries: ['ListCatalogs'] });\n const { setDraftTagIds, flushTags } = useDraftEntityTags('VIBECONTROLS_CATALOG');\n\n const mapItems = useCallback(\n (items: ReadonlyArray<Record<string, unknown>>): CatalogCardData[] =>\n items.map((item) => ({\n id: item.id as string,\n name: item.name as string,\n description: (item.description as string) || null,\n visibility: item.visibility as CatalogCardData['visibility'],\n componentCount: (item.componentCount as number) || 0,\n vibeCount: (item.vibeCount as number) || 0,\n tags: (item.tags as string[]) || [],\n createdAt: item.createdAt as string,\n updatedAt: item.updatedAt as string,\n })),\n []\n );\n\n // Mirror the watched query's items into local state. fetchMore below uses\n // updateQuery to append new pages into the watched data, so this single\n // effect handles both the initial load and load-more cases.\n useEffect(() => {\n const items = data?.vibecontrolsCatalogs?.items ?? [];\n setAccumulated(mapItems(items as ReadonlyArray<Record<string, unknown>>));\n }, [data?.vibecontrolsCatalogs?.items, mapItems]);\n\n const total = data?.vibecontrolsCatalogs?.total ?? 0;\n const hasMore = accumulated.length < total;\n const filteredCatalogs = accumulated;\n const catalogs = accumulated;\n\n const handleLoadMore = useCallback(async () => {\n if (loadingMore || !hasMore) return;\n setLoadingMore(true);\n try {\n await fetchMore({\n variables: { pagination: { limit: PAGE_SIZE, offset: accumulated.length } },\n updateQuery: (prev, { fetchMoreResult }) => {\n if (!fetchMoreResult?.vibecontrolsCatalogs) return prev;\n const prevList = prev.vibecontrolsCatalogs;\n const nextList = fetchMoreResult.vibecontrolsCatalogs;\n return {\n ...prev,\n vibecontrolsCatalogs: {\n ...nextList,\n items: [...(prevList?.items ?? []), ...nextList.items],\n total: nextList.total,\n hasMore: nextList.hasMore,\n },\n };\n },\n });\n } finally {\n setLoadingMore(false);\n }\n }, [fetchMore, accumulated.length, loadingMore, hasMore]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions...</p>\n </div>\n );\n if (!hasPermission(VIBE_PERMISSIONS.VIBE_LIST))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const handleCatalogSelect = (catalog: CatalogCardData) => {\n navigate(`/catalogs/${catalog.id}`);\n };\n\n const handleCreateCatalog = async (formData: CatalogFormData) => {\n const res = await createCatalog({\n variables: {\n input: {\n name: formData.name,\n description: formData.description || undefined,\n visibility: formData.visibility,\n ownerName: formData.owner || undefined,\n tags: formData.tags.length > 0 ? formData.tags : undefined,\n },\n },\n });\n const newCatalogId = res.data?.createVibecontrolsCatalog?.id;\n if (newCatalogId) await flushTags(newCatalogId);\n setSuccessMessage(tr('catalog.createdSuccess', 'Catalog created successfully'));\n setTimeout(() => setSuccessMessage(null), 3000);\n };\n\n if (error && catalogs.length === 0) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <ErrorState\n title={tr('catalog.failedLoad', 'Failed to load catalogs')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <PageHeader\n title={tr('catalog.title', 'Catalogs')}\n description={tr('catalog.description', '{{total}} catalogs', {\n total: catalogs.length,\n })}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-2 text-text-secondary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n title={tr('common.refresh', 'Refresh')}\n >\n <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n <button\n onClick={() => setShowCreateForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('catalog.createCatalog', 'Create Catalog')}\n </button>\n </div>\n }\n />\n\n {/* Filters */}\n <div className=\"flex items-center gap-2 sm:gap-3 flex-wrap\">\n <SearchInput\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder={tr('catalog.searchPlaceholder', 'Search catalogs...')}\n className=\"flex-1 sm:w-64 sm:flex-none\"\n />\n <FilterDropdown\n label={tr('catalog.filterVisibility', 'Visibility')}\n value={visibilityFilter}\n options={visibilityOptions}\n onChange={setVisibilityFilter}\n />\n </div>\n\n {/* Results count */}\n <p className=\"text-sm text-text-secondary\">\n {tr('catalog.showingResults', 'Showing {{filtered}} of {{total}} catalogs', {\n filtered: filteredCatalogs.length,\n total,\n })}\n {loading && (\n <span className=\"ml-2 text-text-muted\">{tr('common.refreshing', '(refreshing...)')}</span>\n )}\n </p>\n\n {/* Grid */}\n {loading && catalogs.length === 0 ? (\n <PageSkeleton variant=\"cards\" count={6} />\n ) : filteredCatalogs.length > 0 ? (\n <AnimatePresence mode=\"wait\">\n <MotionList\n key=\"catalog-grid\"\n stagger={0.04}\n className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\"\n >\n {filteredCatalogs.map((catalog) => (\n <MotionItem key={catalog.id}>\n <CatalogCard catalog={catalog} onOpen={handleCatalogSelect} />\n </MotionItem>\n ))}\n </MotionList>\n </AnimatePresence>\n ) : (\n <EmptyState\n icon={<BookOpen className=\"w-8 h-8 text-text-secondary\" />}\n title={\n searchQuery || visibilityFilter !== 'all'\n ? tr('catalog.emptyNoResults', 'No catalogs found')\n : tr('catalog.emptyNoCatalogs', 'No catalogs yet')\n }\n description={\n searchQuery || visibilityFilter !== 'all'\n ? tr('catalog.emptyAdjustSearch', 'Try adjusting your search or filters')\n : tr('catalog.emptyCreate', 'Create your first catalog to organize components')\n }\n action={\n !searchQuery && visibilityFilter === 'all' ? (\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setShowCreateForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('catalog.createCatalog', 'Create Catalog')}\n </button>\n <GetHelpButton prompt=\"What is a Catalog in VibeControls and how do I create one?\" />\n </div>\n ) : undefined\n }\n />\n )}\n\n {/* Load more */}\n {hasMore && filteredCatalogs.length > 0 && (\n <div className=\"flex justify-center pt-2\">\n <button\n onClick={handleLoadMore}\n disabled={loadingMore}\n className=\"flex items-center gap-2 px-4 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken-hover transition-colors disabled:opacity-50\"\n >\n {loadingMore\n ? tr('common.loading', 'Loading...')\n : tr('common.loadMore', 'Load more')}\n </button>\n </div>\n )}\n\n {/* Success Toast */}\n {successMessage && (\n <div className=\"fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-success-bg text-status-success-text rounded-md shadow-lg text-sm\">\n {successMessage}\n </div>\n )}\n\n {/* Create Form */}\n <CatalogForm\n isOpen={showCreateForm}\n onClose={() => setShowCreateForm(false)}\n onSubmit={handleCreateCatalog}\n extraSection={\n <div>\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">\n {tr('catalog.tags', 'Tags')}\n </h3>\n <EntityTagPicker entityType=\"VIBECONTROLS_CATALOG\" onDraftChange={setDraftTagIds} />\n </div>\n }\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|