@sudobility/entity_pages 0.0.11 → 0.0.13

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/index.d.ts CHANGED
@@ -20,4 +20,4 @@
20
20
  * }
21
21
  * ```
22
22
  */
23
- export { EntityListPage, type EntityListPageProps, MembersManagementPage, type MembersManagementPageProps, InvitationsPage, type InvitationsPageProps, EntitySubscriptionsPage, type EntitySubscriptionsPageProps, type SubscriptionProduct, type CurrentSubscription, type SubscriptionContextValue, type TranslationFunction, } from './pages';
23
+ export { EntityListPage, type EntityListPageProps, MembersManagementPage, type MembersManagementPageProps, InvitationsPage, type InvitationsPageProps, EntitySubscriptionsPage, type EntitySubscriptionsPageProps, type SubscriptionProduct, type CurrentSubscription, type SubscriptionContextValue, type SubscriptionPageLabels, type SubscriptionPageFormatters, } from './pages';
package/dist/index.esm.js CHANGED
@@ -1,79 +1,79 @@
1
- import { jsxs as a, jsx as i, Fragment as te } from "react/jsx-runtime";
2
- import { useState as w, useEffect as ie, useCallback as x } from "react";
3
- import { Plus as ne } from "lucide-react";
4
- import { EntityList as j, InvitationForm as re, InvitationList as B, MemberList as ae } from "@sudobility/entity-components";
5
- import { useEntities as se, useCreateEntity as le, useEntityMembers as oe, useUpdateMemberRole as ce, useRemoveMember as de, useEntityInvitations as ue, useCreateInvitation as me, useCancelInvitation as he, useMyInvitations as ye, useAcceptInvitation as ge, useDeclineInvitation as pe } from "@sudobility/entity_client";
6
- import { SubscriptionLayout as fe, SubscriptionTile as O, SegmentedControl as be } from "@sudobility/subscription-components";
1
+ import { jsxs as o, jsx as i, Fragment as ie } from "react/jsx-runtime";
2
+ import { useState as S, useEffect as ne, useCallback as P } from "react";
3
+ import { Plus as re } from "lucide-react";
4
+ import { EntityList as B, InvitationForm as ae, InvitationList as $, MemberList as oe } from "@sudobility/entity-components";
5
+ import { useEntities as se, useCreateEntity as le, useEntityMembers as ce, useUpdateMemberRole as de, useRemoveMember as ue, useEntityInvitations as me, useCreateInvitation as he, useCancelInvitation as ye, useMyInvitations as ge, useAcceptInvitation as fe, useDeclineInvitation as pe } from "@sudobility/entity_client";
6
+ import { SubscriptionLayout as ve, SubscriptionTile as O, SegmentedControl as be } from "@sudobility/subscription-components";
7
7
  function Ie({
8
- client: l,
8
+ client: c,
9
9
  onSelectEntity: r
10
10
  }) {
11
- const [e, h] = w(!1), [p, y] = w({
11
+ const [t, a] = S(!1), [h, f] = S({
12
12
  displayName: "",
13
13
  description: ""
14
- }), [N, o] = w(null), { data: s = [], isLoading: d } = se(l), c = le(l), I = s.filter((u) => u.entityType === "personal"), L = s.filter(
15
- (u) => u.entityType === "organization"
14
+ }), [y, p] = S(null), { data: d = [], isLoading: s } = se(c), m = le(c), x = d.filter((l) => l.entityType === "personal"), w = d.filter(
15
+ (l) => l.entityType === "organization"
16
16
  );
17
- return /* @__PURE__ */ a("div", { className: "space-y-8", children: [
18
- /* @__PURE__ */ a("div", { className: "flex items-center justify-between", children: [
19
- /* @__PURE__ */ a("div", { children: [
17
+ return /* @__PURE__ */ o("div", { className: "space-y-8", children: [
18
+ /* @__PURE__ */ o("div", { className: "flex items-center justify-between", children: [
19
+ /* @__PURE__ */ o("div", { children: [
20
20
  /* @__PURE__ */ i("h1", { className: "text-2xl font-bold text-foreground", children: "Workspaces" }),
21
21
  /* @__PURE__ */ i("p", { className: "text-muted-foreground", children: "Manage your personal and organization workspaces" })
22
22
  ] }),
23
- /* @__PURE__ */ a(
23
+ /* @__PURE__ */ o(
24
24
  "button",
25
25
  {
26
26
  type: "button",
27
- onClick: () => h(!0),
27
+ onClick: () => a(!0),
28
28
  className: "flex items-center gap-2 px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors",
29
29
  children: [
30
- /* @__PURE__ */ i(ne, { className: "h-4 w-4" }),
30
+ /* @__PURE__ */ i(re, { className: "h-4 w-4" }),
31
31
  /* @__PURE__ */ i("span", { children: "New Organization" })
32
32
  ]
33
33
  }
34
34
  )
35
35
  ] }),
36
- e && /* @__PURE__ */ i("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ a("div", { className: "w-full max-w-md rounded-lg bg-background p-6 shadow-lg", children: [
36
+ t && /* @__PURE__ */ i("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ o("div", { className: "w-full max-w-md rounded-lg bg-background p-6 shadow-lg", children: [
37
37
  /* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-4", children: "Create Organization" }),
38
- /* @__PURE__ */ a("form", { onSubmit: async (u) => {
39
- if (u.preventDefault(), o(null), !p.displayName.trim()) {
40
- o("Display name is required");
38
+ /* @__PURE__ */ o("form", { onSubmit: async (l) => {
39
+ if (l.preventDefault(), p(null), !h.displayName.trim()) {
40
+ p("Display name is required");
41
41
  return;
42
42
  }
43
43
  try {
44
- await c.mutateAsync({
45
- displayName: p.displayName.trim(),
46
- description: p.description.trim() || void 0
47
- }), h(!1), y({ displayName: "", description: "" });
44
+ await m.mutateAsync({
45
+ displayName: h.displayName.trim(),
46
+ description: h.description.trim() || void 0
47
+ }), a(!1), f({ displayName: "", description: "" });
48
48
  } catch (v) {
49
- o(v.message || "Failed to create organization");
49
+ p(v.message || "Failed to create organization");
50
50
  }
51
51
  }, className: "space-y-4", children: [
52
- /* @__PURE__ */ a("div", { children: [
52
+ /* @__PURE__ */ o("div", { children: [
53
53
  /* @__PURE__ */ i("label", { className: "block text-sm font-medium mb-1", children: "Display Name" }),
54
54
  /* @__PURE__ */ i(
55
55
  "input",
56
56
  {
57
57
  type: "text",
58
- value: p.displayName,
59
- onChange: (u) => y((v) => ({
58
+ value: h.displayName,
59
+ onChange: (l) => f((v) => ({
60
60
  ...v,
61
- displayName: u.target.value
61
+ displayName: l.target.value
62
62
  })),
63
63
  placeholder: "My Organization",
64
64
  className: "w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary"
65
65
  }
66
66
  )
67
67
  ] }),
68
- /* @__PURE__ */ a("div", { children: [
68
+ /* @__PURE__ */ o("div", { children: [
69
69
  /* @__PURE__ */ i("label", { className: "block text-sm font-medium mb-1", children: "Description (optional)" }),
70
70
  /* @__PURE__ */ i(
71
71
  "textarea",
72
72
  {
73
- value: p.description,
74
- onChange: (u) => y((v) => ({
73
+ value: h.description,
74
+ onChange: (l) => f((v) => ({
75
75
  ...v,
76
- description: u.target.value
76
+ description: l.target.value
77
77
  })),
78
78
  placeholder: "What is this organization for?",
79
79
  rows: 3,
@@ -81,14 +81,14 @@ function Ie({
81
81
  }
82
82
  )
83
83
  ] }),
84
- N && /* @__PURE__ */ i("p", { className: "text-sm text-destructive", children: N }),
85
- /* @__PURE__ */ a("div", { className: "flex justify-end gap-2", children: [
84
+ y && /* @__PURE__ */ i("p", { className: "text-sm text-destructive", children: y }),
85
+ /* @__PURE__ */ o("div", { className: "flex justify-end gap-2", children: [
86
86
  /* @__PURE__ */ i(
87
87
  "button",
88
88
  {
89
89
  type: "button",
90
90
  onClick: () => {
91
- h(!1), y({ displayName: "", description: "" }), o(null);
91
+ a(!1), f({ displayName: "", description: "" }), p(null);
92
92
  },
93
93
  className: "px-4 py-2 rounded-lg border hover:bg-muted transition-colors",
94
94
  children: "Cancel"
@@ -98,182 +98,182 @@ function Ie({
98
98
  "button",
99
99
  {
100
100
  type: "submit",
101
- disabled: c.isPending,
101
+ disabled: m.isPending,
102
102
  className: "px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50",
103
- children: c.isPending ? "Creating..." : "Create"
103
+ children: m.isPending ? "Creating..." : "Create"
104
104
  }
105
105
  )
106
106
  ] })
107
107
  ] })
108
108
  ] }) }),
109
- I.length > 0 && /* @__PURE__ */ a("div", { children: [
109
+ x.length > 0 && /* @__PURE__ */ o("div", { children: [
110
110
  /* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-3", children: "Personal Workspace" }),
111
111
  /* @__PURE__ */ i(
112
- j,
112
+ B,
113
113
  {
114
- entities: I,
114
+ entities: x,
115
115
  onSelect: r,
116
- isLoading: d
116
+ isLoading: s
117
117
  }
118
118
  )
119
119
  ] }),
120
- /* @__PURE__ */ a("div", { children: [
120
+ /* @__PURE__ */ o("div", { children: [
121
121
  /* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-3", children: "Organizations" }),
122
- L.length === 0 && !d ? /* @__PURE__ */ a("div", { className: "text-center py-8 text-muted-foreground border border-dashed rounded-lg", children: [
122
+ w.length === 0 && !s ? /* @__PURE__ */ o("div", { className: "text-center py-8 text-muted-foreground border border-dashed rounded-lg", children: [
123
123
  /* @__PURE__ */ i("p", { children: "No organizations yet" }),
124
124
  /* @__PURE__ */ i(
125
125
  "button",
126
126
  {
127
127
  type: "button",
128
- onClick: () => h(!0),
128
+ onClick: () => a(!0),
129
129
  className: "mt-2 text-primary hover:underline",
130
130
  children: "Create your first organization"
131
131
  }
132
132
  )
133
133
  ] }) : /* @__PURE__ */ i(
134
- j,
134
+ B,
135
135
  {
136
- entities: L,
136
+ entities: w,
137
137
  onSelect: r,
138
- isLoading: d
138
+ isLoading: s
139
139
  }
140
140
  )
141
141
  ] })
142
142
  ] });
143
143
  }
144
- function Le({
145
- client: l,
144
+ function Te({
145
+ client: c,
146
146
  entity: r,
147
- currentUserId: e
147
+ currentUserId: t
148
148
  }) {
149
- const h = r.userRole === "admin", { data: p = [], isLoading: y } = oe(
150
- l,
149
+ const a = r.userRole === "admin", { data: h = [], isLoading: f } = ce(
150
+ c,
151
151
  r.entitySlug
152
- ), N = ce(l), o = de(l), { data: s = [], isLoading: d } = ue(l, h ? r.entitySlug : null), c = me(l), I = he(l), L = async (g, f) => {
152
+ ), y = de(c), p = ue(c), { data: d = [], isLoading: s } = me(c, a ? r.entitySlug : null), m = he(c), x = ye(c), w = async (N, g) => {
153
153
  try {
154
- await N.mutateAsync({
154
+ await y.mutateAsync({
155
155
  entitySlug: r.entitySlug,
156
- memberId: g,
157
- role: f
156
+ memberId: N,
157
+ role: g
158
158
  });
159
- } catch (S) {
160
- console.error("Failed to update role:", S);
159
+ } catch (M) {
160
+ console.error("Failed to update role:", M);
161
161
  }
162
- }, P = async (g) => {
162
+ }, C = async (N) => {
163
163
  if (confirm("Are you sure you want to remove this member?"))
164
164
  try {
165
- await o.mutateAsync({
165
+ await p.mutateAsync({
166
166
  entitySlug: r.entitySlug,
167
- memberId: g
167
+ memberId: N
168
168
  });
169
- } catch (f) {
170
- console.error("Failed to remove member:", f);
169
+ } catch (g) {
170
+ console.error("Failed to remove member:", g);
171
171
  }
172
- }, u = async (g) => {
173
- await c.mutateAsync({
172
+ }, l = async (N) => {
173
+ await m.mutateAsync({
174
174
  entitySlug: r.entitySlug,
175
- request: g
175
+ request: N
176
176
  });
177
- }, v = async (g) => {
177
+ }, v = async (N) => {
178
178
  try {
179
- await I.mutateAsync({
179
+ await x.mutateAsync({
180
180
  entitySlug: r.entitySlug,
181
- invitationId: g
181
+ invitationId: N
182
182
  });
183
- } catch (f) {
184
- console.error("Failed to cancel invitation:", f);
183
+ } catch (g) {
184
+ console.error("Failed to cancel invitation:", g);
185
185
  }
186
186
  };
187
- return r.entityType === "personal" ? /* @__PURE__ */ a("div", { className: "text-center py-12 text-muted-foreground", children: [
187
+ return r.entityType === "personal" ? /* @__PURE__ */ o("div", { className: "text-center py-12 text-muted-foreground", children: [
188
188
  /* @__PURE__ */ i("p", { children: "Personal workspaces cannot have additional members." }),
189
189
  /* @__PURE__ */ i("p", { className: "mt-2", children: "Create an organization to collaborate with others." })
190
- ] }) : /* @__PURE__ */ a("div", { className: "space-y-8", children: [
191
- /* @__PURE__ */ a("div", { children: [
190
+ ] }) : /* @__PURE__ */ o("div", { className: "space-y-8", children: [
191
+ /* @__PURE__ */ o("div", { children: [
192
192
  /* @__PURE__ */ i("h1", { className: "text-2xl font-bold text-foreground", children: "Members" }),
193
- /* @__PURE__ */ a("p", { className: "text-muted-foreground", children: [
193
+ /* @__PURE__ */ o("p", { className: "text-muted-foreground", children: [
194
194
  "Manage members and invitations for ",
195
195
  r.displayName
196
196
  ] })
197
197
  ] }),
198
- h && /* @__PURE__ */ a("div", { className: "rounded-lg border p-4", children: [
198
+ a && /* @__PURE__ */ o("div", { className: "rounded-lg border p-4", children: [
199
199
  /* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-4", children: "Invite Members" }),
200
200
  /* @__PURE__ */ i(
201
- re,
201
+ ae,
202
202
  {
203
- onSubmit: u,
204
- isSubmitting: c.isPending
203
+ onSubmit: l,
204
+ isSubmitting: m.isPending
205
205
  }
206
206
  )
207
207
  ] }),
208
- h && /* @__PURE__ */ a("div", { children: [
208
+ a && /* @__PURE__ */ o("div", { children: [
209
209
  /* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-3", children: "Pending Invitations" }),
210
210
  /* @__PURE__ */ i(
211
- B,
211
+ $,
212
212
  {
213
- invitations: s,
213
+ invitations: d,
214
214
  mode: "admin",
215
215
  onCancel: v,
216
- isLoading: d,
216
+ isLoading: s,
217
217
  emptyMessage: "No pending invitations"
218
218
  }
219
219
  )
220
220
  ] }),
221
- /* @__PURE__ */ a("div", { children: [
222
- /* @__PURE__ */ a("h2", { className: "text-lg font-semibold mb-3", children: [
221
+ /* @__PURE__ */ o("div", { children: [
222
+ /* @__PURE__ */ o("h2", { className: "text-lg font-semibold mb-3", children: [
223
223
  "Current Members (",
224
- p.length,
224
+ h.length,
225
225
  ")"
226
226
  ] }),
227
227
  /* @__PURE__ */ i(
228
- ae,
228
+ oe,
229
229
  {
230
- members: p,
231
- currentUserId: e,
232
- canManage: h,
233
- onRoleChange: L,
234
- onRemove: P,
235
- isLoading: y
230
+ members: h,
231
+ currentUserId: t,
232
+ canManage: a,
233
+ onRoleChange: w,
234
+ onRemove: C,
235
+ isLoading: f
236
236
  }
237
237
  )
238
238
  ] })
239
239
  ] });
240
240
  }
241
- function Me({
242
- client: l,
241
+ function Fe({
242
+ client: c,
243
243
  onInvitationAccepted: r
244
244
  }) {
245
- const { data: e = [], isLoading: h } = ye(l), p = ge(l), y = pe(l), N = async (d) => {
245
+ const { data: t = [], isLoading: a } = ge(c), h = fe(c), f = pe(c), y = async (s) => {
246
246
  try {
247
- await p.mutateAsync(d), r?.();
248
- } catch (c) {
249
- console.error("Failed to accept invitation:", c);
247
+ await h.mutateAsync(s), r?.();
248
+ } catch (m) {
249
+ console.error("Failed to accept invitation:", m);
250
250
  }
251
- }, o = async (d) => {
251
+ }, p = async (s) => {
252
252
  try {
253
- await y.mutateAsync(d);
254
- } catch (c) {
255
- console.error("Failed to decline invitation:", c);
253
+ await f.mutateAsync(s);
254
+ } catch (m) {
255
+ console.error("Failed to decline invitation:", m);
256
256
  }
257
- }, s = e.filter((d) => d.status === "pending").length;
258
- return /* @__PURE__ */ a("div", { className: "space-y-6", children: [
259
- /* @__PURE__ */ a("div", { children: [
257
+ }, d = t.filter((s) => s.status === "pending").length;
258
+ return /* @__PURE__ */ o("div", { className: "space-y-6", children: [
259
+ /* @__PURE__ */ o("div", { children: [
260
260
  /* @__PURE__ */ i("h1", { className: "text-2xl font-bold text-foreground", children: "Invitations" }),
261
- /* @__PURE__ */ i("p", { className: "text-muted-foreground", children: s > 0 ? `You have ${s} pending invitation${s > 1 ? "s" : ""}` : "No pending invitations" })
261
+ /* @__PURE__ */ i("p", { className: "text-muted-foreground", children: d > 0 ? `You have ${d} pending invitation${d > 1 ? "s" : ""}` : "No pending invitations" })
262
262
  ] }),
263
263
  /* @__PURE__ */ i(
264
- B,
264
+ $,
265
265
  {
266
- invitations: e,
266
+ invitations: t,
267
267
  mode: "user",
268
- onAccept: N,
269
- onDecline: o,
270
- isLoading: h,
268
+ onAccept: y,
269
+ onDecline: p,
270
+ isLoading: a,
271
271
  emptyMessage: "You don't have any pending invitations"
272
272
  }
273
273
  )
274
274
  ] });
275
275
  }
276
- const C = {
276
+ const L = {
277
277
  ultra_yearly: "bandwidth_ultra",
278
278
  ultra_monthly: "bandwidth_ultra",
279
279
  pro_yearly: "bandwidth_pro",
@@ -281,273 +281,250 @@ const C = {
281
281
  dev_yearly: "bandwidth_dev",
282
282
  dev_monthly: "bandwidth_dev"
283
283
  };
284
- function Ae({
285
- subscription: l,
284
+ function Ce({
285
+ subscription: c,
286
286
  rateLimitsConfig: r,
287
- t: e,
287
+ labels: t,
288
+ formatters: a,
288
289
  onPurchaseSuccess: h,
289
- onRestoreSuccess: p,
290
+ onRestoreSuccess: f,
290
291
  onError: y,
291
- onWarning: N
292
+ onWarning: p
292
293
  }) {
293
294
  const {
294
- products: o,
295
+ products: d,
295
296
  currentSubscription: s,
296
- isLoading: d,
297
- error: c,
298
- purchase: I,
299
- restore: L,
300
- clearError: P
301
- } = l, [u, v] = w("monthly"), [g, f] = w(null), [S, F] = w(!1), [M, T] = w(!1);
302
- ie(() => {
303
- c && (y?.(e("common.error"), c), P());
304
- }, [c, P, e, y]);
305
- const k = o.filter((t) => {
306
- if (!t.period) return !1;
307
- const n = t.period.includes("Y") || t.period.includes("year");
308
- return u === "yearly" ? n : !n;
309
- }).sort((t, n) => parseFloat(t.price) - parseFloat(n.price)), Y = (t) => {
310
- v(t), f(null);
311
- }, $ = async () => {
297
+ isLoading: m,
298
+ error: x,
299
+ purchase: w,
300
+ restore: C,
301
+ clearError: l
302
+ } = c, [v, N] = S("monthly"), [g, M] = S(null), [I, A] = S(!1), [T, E] = S(!1);
303
+ ne(() => {
304
+ x && (y?.(t.errorTitle, x), l());
305
+ }, [x, l, t.errorTitle, y]);
306
+ const R = d.filter((e) => {
307
+ if (!e.period) return !1;
308
+ const n = e.period.includes("Y") || e.period.includes("year");
309
+ return v === "yearly" ? n : !n;
310
+ }).sort((e, n) => parseFloat(e.price) - parseFloat(n.price)), U = (e) => {
311
+ N(e), M(null);
312
+ }, q = async () => {
312
313
  if (g) {
313
- F(!0), P();
314
+ A(!0), l();
314
315
  try {
315
- await I(g) && (h?.(), f(null));
316
- } catch (t) {
316
+ await w(g) && (h?.(), M(null));
317
+ } catch (e) {
317
318
  y?.(
318
- e("common.error"),
319
- t instanceof Error ? t.message : e("purchase.error")
319
+ t.errorTitle,
320
+ e instanceof Error ? e.message : t.purchaseError
320
321
  );
321
322
  } finally {
322
- F(!1);
323
+ A(!1);
323
324
  }
324
325
  }
325
- }, W = async () => {
326
- T(!0), P();
326
+ }, H = async () => {
327
+ E(!0), l();
327
328
  try {
328
- await L() ? p?.() : N?.(e("common.error"), e("restore.noPurchases"));
329
- } catch (t) {
329
+ await C() ? f?.() : p?.(t.errorTitle, t.restoreNoPurchases);
330
+ } catch (e) {
330
331
  y?.(
331
- e("common.error"),
332
- t instanceof Error ? t.message : e("restore.error")
332
+ t.errorTitle,
333
+ e instanceof Error ? e.message : t.restoreError
333
334
  );
334
335
  } finally {
335
- T(!1);
336
+ E(!1);
336
337
  }
337
- }, V = x((t) => t ? new Intl.DateTimeFormat(void 0, {
338
+ }, V = P((e) => e ? new Intl.DateTimeFormat(void 0, {
338
339
  year: "numeric",
339
340
  month: "long",
340
341
  day: "numeric"
341
- }).format(t) : "", []), G = x(
342
- (t) => t ? t.includes("Y") || t.includes("year") ? e("periods.year") : t.includes("M") || t.includes("month") ? e("periods.month") : t.includes("W") || t.includes("week") ? e("periods.week") : "" : "",
343
- [e]
344
- ), J = x(
345
- (t) => {
346
- if (!t) return;
347
- const n = t.replace(/\D/g, "") || "1";
348
- return t.includes("W") ? e("trial.weeks", { count: parseInt(n, 10) }) : t.includes("M") ? e("trial.months", { count: parseInt(n, 10) }) : e("trial.days", { count: parseInt(n, 10) });
342
+ }).format(e) : "", []), G = P(
343
+ (e) => e ? e.includes("Y") || e.includes("year") ? t.periodYear : e.includes("M") || e.includes("month") ? t.periodMonth : e.includes("W") || e.includes("week") ? t.periodWeek : "" : "",
344
+ [t]
345
+ ), K = P(
346
+ (e) => {
347
+ if (!e) return;
348
+ const n = parseInt(e.replace(/\D/g, "") || "1", 10);
349
+ return e.includes("W") ? a.formatTrialWeeks(n) : e.includes("M") ? a.formatTrialMonths(n) : a.formatTrialDays(n);
349
350
  },
350
- [e]
351
- ), E = x(
352
- (t) => {
351
+ [a]
352
+ ), k = P(
353
+ (e) => {
353
354
  if (!r?.tiers) return;
354
- const n = C[t];
355
+ const n = L[e];
355
356
  return n ? r.tiers.find(
356
- (m) => m.entitlement === n
357
- ) : r.tiers.find((m) => m.entitlement === "none");
357
+ (u) => u.entitlement === n
358
+ ) : r.tiers.find((u) => u.entitlement === "none");
358
359
  },
359
360
  [r]
360
- ), b = x(
361
- (t) => t === null ? e("rateLimits.unlimited", "Unlimited") : t.toLocaleString(),
362
- [e]
363
- ), R = x(
364
- (t) => {
365
- const n = E(t);
361
+ ), b = P(
362
+ (e) => e === null ? t.unlimited : e.toLocaleString(),
363
+ [t.unlimited]
364
+ ), D = P(
365
+ (e) => {
366
+ const n = k(e);
366
367
  if (!n) return [];
367
- const m = [];
368
- return n.limits.hourly !== null && m.push(
369
- e("rateLimits.hourly", "{{limit}} requests/hour", {
370
- limit: b(n.limits.hourly)
371
- })
372
- ), n.limits.daily !== null && m.push(
373
- e("rateLimits.daily", "{{limit}} requests/day", {
374
- limit: b(n.limits.daily)
375
- })
376
- ), n.limits.monthly !== null && m.push(
377
- e("rateLimits.monthly", "{{limit}} requests/month", {
378
- limit: b(n.limits.monthly)
379
- })
380
- ), n.limits.hourly === null && n.limits.daily === null && n.limits.monthly === null && m.push(
381
- e("rateLimits.unlimitedRequests", "Unlimited API requests")
382
- ), m;
368
+ const u = [];
369
+ return n.limits.hourly !== null && u.push(
370
+ a.formatHourlyLimit(b(n.limits.hourly))
371
+ ), n.limits.daily !== null && u.push(
372
+ a.formatDailyLimit(b(n.limits.daily))
373
+ ), n.limits.monthly !== null && u.push(
374
+ a.formatMonthlyLimit(b(n.limits.monthly))
375
+ ), n.limits.hourly === null && n.limits.daily === null && n.limits.monthly === null && u.push(t.unlimitedRequests), u;
383
376
  },
384
- [E, b, e]
385
- ), K = x(
386
- (t) => R(t),
387
- [R]
388
- ), H = x(() => {
389
- const t = [
390
- e("freeTier.schemaValidation", "JSON Schema-validated outputs"),
391
- e(
392
- "freeTier.allProviders",
393
- "All LLM providers (OpenAI, Anthropic, Google)"
394
- ),
395
- e("freeTier.endpointTesting", "Built-in endpoint testing"),
396
- e("freeTier.analytics", "Basic usage analytics")
397
- ];
377
+ [k, b, a, t.unlimitedRequests]
378
+ ), J = P(
379
+ (e) => D(e),
380
+ [D]
381
+ ), Q = P(() => {
382
+ const e = [...t.freeTierFeatures];
398
383
  if (r?.tiers) {
399
384
  const n = r.tiers.find(
400
- (m) => m.entitlement === "none"
385
+ (u) => u.entitlement === "none"
401
386
  );
402
- n && (n.limits.hourly !== null && t.push(
403
- e("rateLimits.hourly", "{{limit}} requests/hour", {
404
- limit: b(n.limits.hourly)
405
- })
406
- ), n.limits.daily !== null && t.push(
407
- e("rateLimits.daily", "{{limit}} requests/day", {
408
- limit: b(n.limits.daily)
409
- })
410
- ), n.limits.monthly !== null && t.push(
411
- e("rateLimits.monthly", "{{limit}} requests/month", {
412
- limit: b(n.limits.monthly)
413
- })
387
+ n && (n.limits.hourly !== null && e.push(
388
+ a.formatHourlyLimit(b(n.limits.hourly))
389
+ ), n.limits.daily !== null && e.push(
390
+ a.formatDailyLimit(b(n.limits.daily))
391
+ ), n.limits.monthly !== null && e.push(
392
+ a.formatMonthlyLimit(b(n.limits.monthly))
414
393
  ));
415
394
  }
416
- return t;
417
- }, [r, b, e]), Q = x(
418
- (t) => {
419
- const n = C[t];
395
+ return e;
396
+ }, [r, b, a, t.freeTierFeatures]), X = P(
397
+ (e) => {
398
+ const n = L[e];
420
399
  if (!n) return;
421
- const m = o.find(
422
- (A) => A.identifier === t
400
+ const u = d.find(
401
+ (F) => F.identifier === e
423
402
  );
424
- if (!m) return;
425
- const z = Object.entries(C).find(
426
- ([A, ee]) => ee === n && A.includes("monthly")
403
+ if (!u) return;
404
+ const z = Object.entries(L).find(
405
+ ([F, te]) => te === n && F.includes("monthly")
427
406
  )?.[0];
428
407
  if (!z) return;
429
- const D = o.find(
430
- (A) => A.identifier === z
408
+ const _ = d.find(
409
+ (F) => F.identifier === z
431
410
  );
432
- if (!D) return;
433
- const _ = parseFloat(m.price), q = parseFloat(D.price);
434
- if (q <= 0 || _ <= 0) return;
435
- const U = q * 12, Z = (U - _) / U * 100;
436
- return Math.round(Z);
411
+ if (!_) return;
412
+ const Y = parseFloat(u.price), j = parseFloat(_.price);
413
+ if (j <= 0 || Y <= 0) return;
414
+ const W = j * 12, ee = (W - Y) / W * 100;
415
+ return Math.round(ee);
437
416
  },
438
- [o]
439
- ), X = [
440
- { value: "monthly", label: e("billingPeriod.monthly") },
441
- { value: "yearly", label: e("billingPeriod.yearly") }
417
+ [d]
418
+ ), Z = [
419
+ { value: "monthly", label: t.billingMonthly },
420
+ { value: "yearly", label: t.billingYearly }
442
421
  ];
443
422
  return /* @__PURE__ */ i(
444
- fe,
423
+ ve,
445
424
  {
446
- title: e("title"),
447
- error: c,
448
- currentStatusLabel: e("currentStatus.label"),
425
+ title: t.title,
426
+ error: x,
427
+ currentStatusLabel: t.currentStatusLabel,
449
428
  currentStatus: {
450
429
  isActive: s?.isActive ?? !1,
451
430
  activeContent: s?.isActive ? {
452
- title: e("currentStatus.active"),
431
+ title: t.statusActive,
453
432
  fields: [
454
433
  {
455
- label: e("currentStatus.plan"),
456
- value: s.productIdentifier || e("currentStatus.premium")
434
+ label: t.labelPlan,
435
+ value: s.productIdentifier || t.labelPremium
457
436
  },
458
437
  {
459
- label: e("currentStatus.expires"),
438
+ label: t.labelExpires,
460
439
  value: V(
461
440
  s.expirationDate
462
441
  )
463
442
  },
464
443
  {
465
- label: e("currentStatus.willRenew"),
466
- value: s.willRenew ? e("common.yes") : e("common.no")
444
+ label: t.labelWillRenew,
445
+ value: s.willRenew ? t.yes : t.no
467
446
  },
468
447
  ...r ? [
469
448
  {
470
- label: e("currentStatus.monthlyUsage", "Monthly Usage"),
449
+ label: t.labelMonthlyUsage,
471
450
  value: `${r.currentUsage.monthly.toLocaleString()} / ${b(r.currentLimits.monthly)}`
472
451
  },
473
452
  {
474
- label: e("currentStatus.dailyUsage", "Daily Usage"),
453
+ label: t.labelDailyUsage,
475
454
  value: `${r.currentUsage.daily.toLocaleString()} / ${b(r.currentLimits.daily)}`
476
455
  }
477
456
  ] : []
478
457
  ]
479
458
  } : void 0,
480
459
  inactiveContent: s?.isActive ? void 0 : {
481
- title: e("currentStatus.inactive"),
482
- message: e("currentStatus.inactiveMessage")
460
+ title: t.statusInactive,
461
+ message: t.statusInactiveMessage
483
462
  }
484
463
  },
485
- aboveProducts: !d && o.length > 0 ? /* @__PURE__ */ i("div", { className: "flex justify-center mb-6", children: /* @__PURE__ */ i(
464
+ aboveProducts: !m && d.length > 0 ? /* @__PURE__ */ i("div", { className: "flex justify-center mb-6", children: /* @__PURE__ */ i(
486
465
  be,
487
466
  {
488
- options: X,
489
- value: u,
490
- onChange: Y
467
+ options: Z,
468
+ value: v,
469
+ onChange: U
491
470
  }
492
471
  ) }) : null,
493
472
  primaryAction: {
494
- label: e(S ? "buttons.purchasing" : "buttons.subscribe"),
495
- onClick: $,
496
- disabled: !g || S || M,
497
- loading: S
473
+ label: I ? t.buttonPurchasing : t.buttonSubscribe,
474
+ onClick: q,
475
+ disabled: !g || I || T,
476
+ loading: I
498
477
  },
499
478
  secondaryAction: {
500
- label: e(M ? "buttons.restoring" : "buttons.restore"),
501
- onClick: W,
502
- disabled: S || M,
503
- loading: M
479
+ label: T ? t.buttonRestoring : t.buttonRestore,
480
+ onClick: H,
481
+ disabled: I || T,
482
+ loading: T
504
483
  },
505
- children: d ? /* @__PURE__ */ i("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ i("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }) }) : o.length === 0 ? /* @__PURE__ */ i("div", { className: "text-center py-12 text-theme-text-secondary", children: e("noProducts") }) : k.length === 0 ? /* @__PURE__ */ i("div", { className: "text-center py-12 text-theme-text-secondary", children: e("noProductsForPeriod") }) : /* @__PURE__ */ a(te, { children: [
484
+ children: m ? /* @__PURE__ */ i("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ i("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }) }) : d.length === 0 ? /* @__PURE__ */ i("div", { className: "text-center py-12 text-theme-text-secondary", children: t.noProducts }) : R.length === 0 ? /* @__PURE__ */ i("div", { className: "text-center py-12 text-theme-text-secondary", children: t.noProductsForPeriod }) : /* @__PURE__ */ o(ie, { children: [
506
485
  /* @__PURE__ */ i(
507
486
  O,
508
487
  {
509
488
  id: "free",
510
- title: e("freeTier.title"),
511
- price: e("freeTier.price"),
512
- periodLabel: e("periods.month"),
513
- features: H(),
489
+ title: t.freeTierTitle,
490
+ price: t.freeTierPrice,
491
+ periodLabel: t.periodMonth,
492
+ features: Q(),
514
493
  isSelected: !s?.isActive && g === null,
515
- onSelect: () => f(null),
494
+ onSelect: () => M(null),
516
495
  topBadge: s?.isActive ? void 0 : {
517
- text: e("badges.currentPlan", "Current Plan"),
496
+ text: t.currentPlanBadge,
518
497
  color: "green"
519
498
  },
520
- disabled: S || M,
499
+ disabled: I || T,
521
500
  hideSelectionIndicator: !0
522
501
  },
523
502
  "free"
524
503
  ),
525
- k.map((t) => /* @__PURE__ */ i(
504
+ R.map((e) => /* @__PURE__ */ i(
526
505
  O,
527
506
  {
528
- id: t.identifier,
529
- title: t.title,
530
- price: t.priceString,
531
- periodLabel: G(t.period),
532
- features: K(t.identifier),
533
- isSelected: g === t.identifier,
534
- onSelect: () => f(t.identifier),
535
- isBestValue: t.identifier.includes("pro"),
536
- discountBadge: t.period?.includes("Y") ? (() => {
537
- const n = Q(
538
- t.identifier
507
+ id: e.identifier,
508
+ title: e.title,
509
+ price: e.priceString,
510
+ periodLabel: G(e.period),
511
+ features: J(e.identifier),
512
+ isSelected: g === e.identifier,
513
+ onSelect: () => M(e.identifier),
514
+ isBestValue: e.identifier.includes("pro"),
515
+ discountBadge: e.period?.includes("Y") ? (() => {
516
+ const n = X(
517
+ e.identifier
539
518
  );
540
519
  return n && n > 0 ? {
541
- text: e("badges.savePercent", "Save {{percent}}%", {
542
- percent: n
543
- }),
520
+ text: a.formatSavePercent(n),
544
521
  isBestValue: !0
545
522
  } : void 0;
546
523
  })() : void 0,
547
- introPriceNote: t.freeTrialPeriod ? J(t.freeTrialPeriod) : t.introPrice ? e("intro.note", { price: t.introPrice }) : void 0,
548
- disabled: S || M
524
+ introPriceNote: e.freeTrialPeriod ? K(e.freeTrialPeriod) : e.introPrice ? a.formatIntroNote(e.introPrice) : void 0,
525
+ disabled: I || T
549
526
  },
550
- t.identifier
527
+ e.identifier
551
528
  ))
552
529
  ] })
553
530
  }
@@ -555,7 +532,7 @@ function Ae({
555
532
  }
556
533
  export {
557
534
  Ie as EntityListPage,
558
- Ae as EntitySubscriptionsPage,
559
- Me as InvitationsPage,
560
- Le as MembersManagementPage
535
+ Ce as EntitySubscriptionsPage,
536
+ Fe as InvitationsPage,
537
+ Te as MembersManagementPage
561
538
  };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(l,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("react/jsx-runtime"),require("react"),require("lucide-react"),require("@sudobility/entity-components"),require("@sudobility/entity_client"),require("@sudobility/subscription-components")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","lucide-react","@sudobility/entity-components","@sudobility/entity_client","@sudobility/subscription-components"],e):(l=typeof globalThis<"u"?globalThis:l||self,e(l.EntityPages={},l.jsxRuntime,l.React,l.LucideReact,l.SudobilityEntityComponents,l.SudobilityEntityClient,l.SudobilitySubscriptionComponents))})(this,(function(l,e,s,_,I,b,A){"use strict";function $({client:o,onSelectEntity:r}){const[t,y]=s.useState(!1),[f,g]=s.useState({displayName:"",description:""}),[N,c]=s.useState(null),{data:a=[],isLoading:u}=b.useEntities(o),d=b.useCreateEntity(o),L=a.filter(m=>m.entityType==="personal"),M=a.filter(m=>m.entityType==="organization"),P=async m=>{if(m.preventDefault(),c(null),!f.displayName.trim()){c("Display name is required");return}try{await d.mutateAsync({displayName:f.displayName.trim(),description:f.description.trim()||void 0}),y(!1),g({displayName:"",description:""})}catch(x){c(x.message||"Failed to create organization")}};return e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Workspaces"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage your personal and organization workspaces"})]}),e.jsxs("button",{type:"button",onClick:()=>y(!0),className:"flex items-center gap-2 px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors",children:[e.jsx(_.Plus,{className:"h-4 w-4"}),e.jsx("span",{children:"New Organization"})]})]}),t&&e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:e.jsxs("div",{className:"w-full max-w-md rounded-lg bg-background p-6 shadow-lg",children:[e.jsx("h2",{className:"text-lg font-semibold mb-4",children:"Create Organization"}),e.jsxs("form",{onSubmit:P,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Display Name"}),e.jsx("input",{type:"text",value:f.displayName,onChange:m=>g(x=>({...x,displayName:m.target.value})),placeholder:"My Organization",className:"w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Description (optional)"}),e.jsx("textarea",{value:f.description,onChange:m=>g(x=>({...x,description:m.target.value})),placeholder:"What is this organization for?",rows:3,className:"w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary resize-none"})]}),N&&e.jsx("p",{className:"text-sm text-destructive",children:N}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:()=>{y(!1),g({displayName:"",description:""}),c(null)},className:"px-4 py-2 rounded-lg border hover:bg-muted transition-colors",children:"Cancel"}),e.jsx("button",{type:"submit",disabled:d.isPending,className:"px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50",children:d.isPending?"Creating...":"Create"})]})]})]})}),L.length>0&&e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Personal Workspace"}),e.jsx(I.EntityList,{entities:L,onSelect:r,isLoading:u})]}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Organizations"}),M.length===0&&!u?e.jsxs("div",{className:"text-center py-8 text-muted-foreground border border-dashed rounded-lg",children:[e.jsx("p",{children:"No organizations yet"}),e.jsx("button",{type:"button",onClick:()=>y(!0),className:"mt-2 text-primary hover:underline",children:"Create your first organization"})]}):e.jsx(I.EntityList,{entities:M,onSelect:r,isLoading:u})]})]})}function W({client:o,entity:r,currentUserId:t}){const y=r.userRole==="admin",{data:f=[],isLoading:g}=b.useEntityMembers(o,r.entitySlug),N=b.useUpdateMemberRole(o),c=b.useRemoveMember(o),{data:a=[],isLoading:u}=b.useEntityInvitations(o,y?r.entitySlug:null),d=b.useCreateInvitation(o),L=b.useCancelInvitation(o),M=async(p,v)=>{try{await N.mutateAsync({entitySlug:r.entitySlug,memberId:p,role:v})}catch(w){console.error("Failed to update role:",w)}},P=async p=>{if(confirm("Are you sure you want to remove this member?"))try{await c.mutateAsync({entitySlug:r.entitySlug,memberId:p})}catch(v){console.error("Failed to remove member:",v)}},m=async p=>{await d.mutateAsync({entitySlug:r.entitySlug,request:p})},x=async p=>{try{await L.mutateAsync({entitySlug:r.entitySlug,invitationId:p})}catch(v){console.error("Failed to cancel invitation:",v)}};return r.entityType==="personal"?e.jsxs("div",{className:"text-center py-12 text-muted-foreground",children:[e.jsx("p",{children:"Personal workspaces cannot have additional members."}),e.jsx("p",{className:"mt-2",children:"Create an organization to collaborate with others."})]}):e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Members"}),e.jsxs("p",{className:"text-muted-foreground",children:["Manage members and invitations for ",r.displayName]})]}),y&&e.jsxs("div",{className:"rounded-lg border p-4",children:[e.jsx("h2",{className:"text-lg font-semibold mb-4",children:"Invite Members"}),e.jsx(I.InvitationForm,{onSubmit:m,isSubmitting:d.isPending})]}),y&&e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Pending Invitations"}),e.jsx(I.InvitationList,{invitations:a,mode:"admin",onCancel:x,isLoading:u,emptyMessage:"No pending invitations"})]}),e.jsxs("div",{children:[e.jsxs("h2",{className:"text-lg font-semibold mb-3",children:["Current Members (",f.length,")"]}),e.jsx(I.MemberList,{members:f,currentUserId:t,canManage:y,onRoleChange:M,onRemove:P,isLoading:g})]})]})}function V({client:o,onInvitationAccepted:r}){const{data:t=[],isLoading:y}=b.useMyInvitations(o),f=b.useAcceptInvitation(o),g=b.useDeclineInvitation(o),N=async u=>{try{await f.mutateAsync(u),r?.()}catch(d){console.error("Failed to accept invitation:",d)}},c=async u=>{try{await g.mutateAsync(u)}catch(d){console.error("Failed to decline invitation:",d)}},a=t.filter(u=>u.status==="pending").length;return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Invitations"}),e.jsx("p",{className:"text-muted-foreground",children:a>0?`You have ${a} pending invitation${a>1?"s":""}`:"No pending invitations"})]}),e.jsx(I.InvitationList,{invitations:t,mode:"user",onAccept:N,onDecline:c,isLoading:y,emptyMessage:"You don't have any pending invitations"})]})}const T={ultra_yearly:"bandwidth_ultra",ultra_monthly:"bandwidth_ultra",pro_yearly:"bandwidth_pro",pro_monthly:"bandwidth_pro",dev_yearly:"bandwidth_dev",dev_monthly:"bandwidth_dev"};function G({subscription:o,rateLimitsConfig:r,t,onPurchaseSuccess:y,onRestoreSuccess:f,onError:g,onWarning:N}){const{products:c,currentSubscription:a,isLoading:u,error:d,purchase:L,restore:M,clearError:P}=o,[m,x]=s.useState("monthly"),[p,v]=s.useState(null),[w,E]=s.useState(!1),[k,F]=s.useState(!1);s.useEffect(()=>{d&&(g?.(t("common.error"),d),P())},[d,P,t,g]);const q=c.filter(i=>{if(!i.period)return!1;const n=i.period.includes("Y")||i.period.includes("year");return m==="yearly"?n:!n}).sort((i,n)=>parseFloat(i.price)-parseFloat(n.price)),J=i=>{x(i),v(null)},K=async()=>{if(p){E(!0),P();try{await L(p)&&(y?.(),v(null))}catch(i){g?.(t("common.error"),i instanceof Error?i.message:t("purchase.error"))}finally{E(!1)}}},H=async()=>{F(!0),P();try{await M()?f?.():N?.(t("common.error"),t("restore.noPurchases"))}catch(i){g?.(t("common.error"),i instanceof Error?i.message:t("restore.error"))}finally{F(!1)}},Q=s.useCallback(i=>i?new Intl.DateTimeFormat(void 0,{year:"numeric",month:"long",day:"numeric"}).format(i):"",[]),X=s.useCallback(i=>i?i.includes("Y")||i.includes("year")?t("periods.year"):i.includes("M")||i.includes("month")?t("periods.month"):i.includes("W")||i.includes("week")?t("periods.week"):"":"",[t]),Z=s.useCallback(i=>{if(!i)return;const n=i.replace(/\D/g,"")||"1";return i.includes("W")?t("trial.weeks",{count:parseInt(n,10)}):i.includes("M")?t("trial.months",{count:parseInt(n,10)}):t("trial.days",{count:parseInt(n,10)})},[t]),z=s.useCallback(i=>{if(!r?.tiers)return;const n=T[i];return n?r.tiers.find(h=>h.entitlement===n):r.tiers.find(h=>h.entitlement==="none")},[r]),S=s.useCallback(i=>i===null?t("rateLimits.unlimited","Unlimited"):i.toLocaleString(),[t]),D=s.useCallback(i=>{const n=z(i);if(!n)return[];const h=[];return n.limits.hourly!==null&&h.push(t("rateLimits.hourly","{{limit}} requests/hour",{limit:S(n.limits.hourly)})),n.limits.daily!==null&&h.push(t("rateLimits.daily","{{limit}} requests/day",{limit:S(n.limits.daily)})),n.limits.monthly!==null&&h.push(t("rateLimits.monthly","{{limit}} requests/month",{limit:S(n.limits.monthly)})),n.limits.hourly===null&&n.limits.daily===null&&n.limits.monthly===null&&h.push(t("rateLimits.unlimitedRequests","Unlimited API requests")),h},[z,S,t]),R=s.useCallback(i=>D(i),[D]),ee=s.useCallback(()=>{const i=[t("freeTier.schemaValidation","JSON Schema-validated outputs"),t("freeTier.allProviders","All LLM providers (OpenAI, Anthropic, Google)"),t("freeTier.endpointTesting","Built-in endpoint testing"),t("freeTier.analytics","Basic usage analytics")];if(r?.tiers){const n=r.tiers.find(h=>h.entitlement==="none");n&&(n.limits.hourly!==null&&i.push(t("rateLimits.hourly","{{limit}} requests/hour",{limit:S(n.limits.hourly)})),n.limits.daily!==null&&i.push(t("rateLimits.daily","{{limit}} requests/day",{limit:S(n.limits.daily)})),n.limits.monthly!==null&&i.push(t("rateLimits.monthly","{{limit}} requests/month",{limit:S(n.limits.monthly)})))}return i},[r,S,t]),te=s.useCallback(i=>{const n=T[i];if(!n)return;const h=c.find(C=>C.identifier===i);if(!h)return;const j=Object.entries(T).find(([C,re])=>re===n&&C.includes("monthly"))?.[0];if(!j)return;const O=c.find(C=>C.identifier===j);if(!O)return;const U=parseFloat(h.price),B=parseFloat(O.price);if(B<=0||U<=0)return;const Y=B*12,ne=(Y-U)/Y*100;return Math.round(ne)},[c]),ie=[{value:"monthly",label:t("billingPeriod.monthly")},{value:"yearly",label:t("billingPeriod.yearly")}];return e.jsx(A.SubscriptionLayout,{title:t("title"),error:d,currentStatusLabel:t("currentStatus.label"),currentStatus:{isActive:a?.isActive??!1,activeContent:a?.isActive?{title:t("currentStatus.active"),fields:[{label:t("currentStatus.plan"),value:a.productIdentifier||t("currentStatus.premium")},{label:t("currentStatus.expires"),value:Q(a.expirationDate)},{label:t("currentStatus.willRenew"),value:a.willRenew?t("common.yes"):t("common.no")},...r?[{label:t("currentStatus.monthlyUsage","Monthly Usage"),value:`${r.currentUsage.monthly.toLocaleString()} / ${S(r.currentLimits.monthly)}`},{label:t("currentStatus.dailyUsage","Daily Usage"),value:`${r.currentUsage.daily.toLocaleString()} / ${S(r.currentLimits.daily)}`}]:[]]}:void 0,inactiveContent:a?.isActive?void 0:{title:t("currentStatus.inactive"),message:t("currentStatus.inactiveMessage")}},aboveProducts:!u&&c.length>0?e.jsx("div",{className:"flex justify-center mb-6",children:e.jsx(A.SegmentedControl,{options:ie,value:m,onChange:J})}):null,primaryAction:{label:t(w?"buttons.purchasing":"buttons.subscribe"),onClick:K,disabled:!p||w||k,loading:w},secondaryAction:{label:t(k?"buttons.restoring":"buttons.restore"),onClick:H,disabled:w||k,loading:k},children:u?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"})}):c.length===0?e.jsx("div",{className:"text-center py-12 text-theme-text-secondary",children:t("noProducts")}):q.length===0?e.jsx("div",{className:"text-center py-12 text-theme-text-secondary",children:t("noProductsForPeriod")}):e.jsxs(e.Fragment,{children:[e.jsx(A.SubscriptionTile,{id:"free",title:t("freeTier.title"),price:t("freeTier.price"),periodLabel:t("periods.month"),features:ee(),isSelected:!a?.isActive&&p===null,onSelect:()=>v(null),topBadge:a?.isActive?void 0:{text:t("badges.currentPlan","Current Plan"),color:"green"},disabled:w||k,hideSelectionIndicator:!0},"free"),q.map(i=>e.jsx(A.SubscriptionTile,{id:i.identifier,title:i.title,price:i.priceString,periodLabel:X(i.period),features:R(i.identifier),isSelected:p===i.identifier,onSelect:()=>v(i.identifier),isBestValue:i.identifier.includes("pro"),discountBadge:i.period?.includes("Y")?(()=>{const n=te(i.identifier);return n&&n>0?{text:t("badges.savePercent","Save {{percent}}%",{percent:n}),isBestValue:!0}:void 0})():void 0,introPriceNote:i.freeTrialPeriod?Z(i.freeTrialPeriod):i.introPrice?t("intro.note",{price:i.introPrice}):void 0,disabled:w||k},i.identifier))]})})}l.EntityListPage=$,l.EntitySubscriptionsPage=G,l.InvitationsPage=V,l.MembersManagementPage=W,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(c,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("react/jsx-runtime"),require("react"),require("lucide-react"),require("@sudobility/entity-components"),require("@sudobility/entity_client"),require("@sudobility/subscription-components")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","lucide-react","@sudobility/entity-components","@sudobility/entity_client","@sudobility/subscription-components"],e):(c=typeof globalThis<"u"?globalThis:c||self,e(c.EntityPages={},c.jsxRuntime,c.React,c.LucideReact,c.SudobilityEntityComponents,c.SudobilityEntityClient,c.SudobilitySubscriptionComponents))})(this,(function(c,e,o,$,w,g,C){"use strict";function U({client:d,onSelectEntity:r}){const[i,a]=o.useState(!1),[m,v]=o.useState({displayName:"",description:""}),[f,b]=o.useState(null),{data:u=[],isLoading:s}=g.useEntities(d),h=g.useCreateEntity(d),S=u.filter(l=>l.entityType==="personal"),M=u.filter(l=>l.entityType==="organization"),k=async l=>{if(l.preventDefault(),b(null),!m.displayName.trim()){b("Display name is required");return}try{await h.mutateAsync({displayName:m.displayName.trim(),description:m.description.trim()||void 0}),a(!1),v({displayName:"",description:""})}catch(N){b(N.message||"Failed to create organization")}};return e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Workspaces"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage your personal and organization workspaces"})]}),e.jsxs("button",{type:"button",onClick:()=>a(!0),className:"flex items-center gap-2 px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors",children:[e.jsx($.Plus,{className:"h-4 w-4"}),e.jsx("span",{children:"New Organization"})]})]}),i&&e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:e.jsxs("div",{className:"w-full max-w-md rounded-lg bg-background p-6 shadow-lg",children:[e.jsx("h2",{className:"text-lg font-semibold mb-4",children:"Create Organization"}),e.jsxs("form",{onSubmit:k,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Display Name"}),e.jsx("input",{type:"text",value:m.displayName,onChange:l=>v(N=>({...N,displayName:l.target.value})),placeholder:"My Organization",className:"w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Description (optional)"}),e.jsx("textarea",{value:m.description,onChange:l=>v(N=>({...N,description:l.target.value})),placeholder:"What is this organization for?",rows:3,className:"w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary resize-none"})]}),f&&e.jsx("p",{className:"text-sm text-destructive",children:f}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:()=>{a(!1),v({displayName:"",description:""}),b(null)},className:"px-4 py-2 rounded-lg border hover:bg-muted transition-colors",children:"Cancel"}),e.jsx("button",{type:"submit",disabled:h.isPending,className:"px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50",children:h.isPending?"Creating...":"Create"})]})]})]})}),S.length>0&&e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Personal Workspace"}),e.jsx(w.EntityList,{entities:S,onSelect:r,isLoading:s})]}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Organizations"}),M.length===0&&!s?e.jsxs("div",{className:"text-center py-8 text-muted-foreground border border-dashed rounded-lg",children:[e.jsx("p",{children:"No organizations yet"}),e.jsx("button",{type:"button",onClick:()=>a(!0),className:"mt-2 text-primary hover:underline",children:"Create your first organization"})]}):e.jsx(w.EntityList,{entities:M,onSelect:r,isLoading:s})]})]})}function H({client:d,entity:r,currentUserId:i}){const a=r.userRole==="admin",{data:m=[],isLoading:v}=g.useEntityMembers(d,r.entitySlug),f=g.useUpdateMemberRole(d),b=g.useRemoveMember(d),{data:u=[],isLoading:s}=g.useEntityInvitations(d,a?r.entitySlug:null),h=g.useCreateInvitation(d),S=g.useCancelInvitation(d),M=async(P,p)=>{try{await f.mutateAsync({entitySlug:r.entitySlug,memberId:P,role:p})}catch(T){console.error("Failed to update role:",T)}},k=async P=>{if(confirm("Are you sure you want to remove this member?"))try{await b.mutateAsync({entitySlug:r.entitySlug,memberId:P})}catch(p){console.error("Failed to remove member:",p)}},l=async P=>{await h.mutateAsync({entitySlug:r.entitySlug,request:P})},N=async P=>{try{await S.mutateAsync({entitySlug:r.entitySlug,invitationId:P})}catch(p){console.error("Failed to cancel invitation:",p)}};return r.entityType==="personal"?e.jsxs("div",{className:"text-center py-12 text-muted-foreground",children:[e.jsx("p",{children:"Personal workspaces cannot have additional members."}),e.jsx("p",{className:"mt-2",children:"Create an organization to collaborate with others."})]}):e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Members"}),e.jsxs("p",{className:"text-muted-foreground",children:["Manage members and invitations for ",r.displayName]})]}),a&&e.jsxs("div",{className:"rounded-lg border p-4",children:[e.jsx("h2",{className:"text-lg font-semibold mb-4",children:"Invite Members"}),e.jsx(w.InvitationForm,{onSubmit:l,isSubmitting:h.isPending})]}),a&&e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Pending Invitations"}),e.jsx(w.InvitationList,{invitations:u,mode:"admin",onCancel:N,isLoading:s,emptyMessage:"No pending invitations"})]}),e.jsxs("div",{children:[e.jsxs("h2",{className:"text-lg font-semibold mb-3",children:["Current Members (",m.length,")"]}),e.jsx(w.MemberList,{members:m,currentUserId:i,canManage:a,onRoleChange:M,onRemove:k,isLoading:v})]})]})}function V({client:d,onInvitationAccepted:r}){const{data:i=[],isLoading:a}=g.useMyInvitations(d),m=g.useAcceptInvitation(d),v=g.useDeclineInvitation(d),f=async s=>{try{await m.mutateAsync(s),r?.()}catch(h){console.error("Failed to accept invitation:",h)}},b=async s=>{try{await v.mutateAsync(s)}catch(h){console.error("Failed to decline invitation:",h)}},u=i.filter(s=>s.status==="pending").length;return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Invitations"}),e.jsx("p",{className:"text-muted-foreground",children:u>0?`You have ${u} pending invitation${u>1?"s":""}`:"No pending invitations"})]}),e.jsx(w.InvitationList,{invitations:i,mode:"user",onAccept:f,onDecline:b,isLoading:a,emptyMessage:"You don't have any pending invitations"})]})}const F={ultra_yearly:"bandwidth_ultra",ultra_monthly:"bandwidth_ultra",pro_yearly:"bandwidth_pro",pro_monthly:"bandwidth_pro",dev_yearly:"bandwidth_dev",dev_monthly:"bandwidth_dev"};function G({subscription:d,rateLimitsConfig:r,labels:i,formatters:a,onPurchaseSuccess:m,onRestoreSuccess:v,onError:f,onWarning:b}){const{products:u,currentSubscription:s,isLoading:h,error:S,purchase:M,restore:k,clearError:l}=d,[N,P]=o.useState("monthly"),[p,T]=o.useState(null),[I,A]=o.useState(!1),[L,D]=o.useState(!1);o.useEffect(()=>{S&&(f?.(i.errorTitle,S),l())},[S,l,i.errorTitle,f]);const z=u.filter(t=>{if(!t.period)return!1;const n=t.period.includes("Y")||t.period.includes("year");return N==="yearly"?n:!n}).sort((t,n)=>parseFloat(t.price)-parseFloat(n.price)),K=t=>{P(t),T(null)},J=async()=>{if(p){A(!0),l();try{await M(p)&&(m?.(),T(null))}catch(t){f?.(i.errorTitle,t instanceof Error?t.message:i.purchaseError)}finally{A(!1)}}},Q=async()=>{D(!0),l();try{await k()?v?.():b?.(i.errorTitle,i.restoreNoPurchases)}catch(t){f?.(i.errorTitle,t instanceof Error?t.message:i.restoreError)}finally{D(!1)}},X=o.useCallback(t=>t?new Intl.DateTimeFormat(void 0,{year:"numeric",month:"long",day:"numeric"}).format(t):"",[]),Z=o.useCallback(t=>t?t.includes("Y")||t.includes("year")?i.periodYear:t.includes("M")||t.includes("month")?i.periodMonth:t.includes("W")||t.includes("week")?i.periodWeek:"":"",[i]),R=o.useCallback(t=>{if(!t)return;const n=parseInt(t.replace(/\D/g,"")||"1",10);return t.includes("W")?a.formatTrialWeeks(n):t.includes("M")?a.formatTrialMonths(n):a.formatTrialDays(n)},[a]),j=o.useCallback(t=>{if(!r?.tiers)return;const n=F[t];return n?r.tiers.find(y=>y.entitlement===n):r.tiers.find(y=>y.entitlement==="none")},[r]),x=o.useCallback(t=>t===null?i.unlimited:t.toLocaleString(),[i.unlimited]),q=o.useCallback(t=>{const n=j(t);if(!n)return[];const y=[];return n.limits.hourly!==null&&y.push(a.formatHourlyLimit(x(n.limits.hourly))),n.limits.daily!==null&&y.push(a.formatDailyLimit(x(n.limits.daily))),n.limits.monthly!==null&&y.push(a.formatMonthlyLimit(x(n.limits.monthly))),n.limits.hourly===null&&n.limits.daily===null&&n.limits.monthly===null&&y.push(i.unlimitedRequests),y},[j,x,a,i.unlimitedRequests]),ee=o.useCallback(t=>q(t),[q]),te=o.useCallback(()=>{const t=[...i.freeTierFeatures];if(r?.tiers){const n=r.tiers.find(y=>y.entitlement==="none");n&&(n.limits.hourly!==null&&t.push(a.formatHourlyLimit(x(n.limits.hourly))),n.limits.daily!==null&&t.push(a.formatDailyLimit(x(n.limits.daily))),n.limits.monthly!==null&&t.push(a.formatMonthlyLimit(x(n.limits.monthly))))}return t},[r,x,a,i.freeTierFeatures]),ie=o.useCallback(t=>{const n=F[t];if(!n)return;const y=u.find(E=>E.identifier===t);if(!y)return;const Y=Object.entries(F).find(([E,ae])=>ae===n&&E.includes("monthly"))?.[0];if(!Y)return;const W=u.find(E=>E.identifier===Y);if(!W)return;const O=parseFloat(y.price),B=parseFloat(W.price);if(B<=0||O<=0)return;const _=B*12,re=(_-O)/_*100;return Math.round(re)},[u]),ne=[{value:"monthly",label:i.billingMonthly},{value:"yearly",label:i.billingYearly}];return e.jsx(C.SubscriptionLayout,{title:i.title,error:S,currentStatusLabel:i.currentStatusLabel,currentStatus:{isActive:s?.isActive??!1,activeContent:s?.isActive?{title:i.statusActive,fields:[{label:i.labelPlan,value:s.productIdentifier||i.labelPremium},{label:i.labelExpires,value:X(s.expirationDate)},{label:i.labelWillRenew,value:s.willRenew?i.yes:i.no},...r?[{label:i.labelMonthlyUsage,value:`${r.currentUsage.monthly.toLocaleString()} / ${x(r.currentLimits.monthly)}`},{label:i.labelDailyUsage,value:`${r.currentUsage.daily.toLocaleString()} / ${x(r.currentLimits.daily)}`}]:[]]}:void 0,inactiveContent:s?.isActive?void 0:{title:i.statusInactive,message:i.statusInactiveMessage}},aboveProducts:!h&&u.length>0?e.jsx("div",{className:"flex justify-center mb-6",children:e.jsx(C.SegmentedControl,{options:ne,value:N,onChange:K})}):null,primaryAction:{label:I?i.buttonPurchasing:i.buttonSubscribe,onClick:J,disabled:!p||I||L,loading:I},secondaryAction:{label:L?i.buttonRestoring:i.buttonRestore,onClick:Q,disabled:I||L,loading:L},children:h?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"})}):u.length===0?e.jsx("div",{className:"text-center py-12 text-theme-text-secondary",children:i.noProducts}):z.length===0?e.jsx("div",{className:"text-center py-12 text-theme-text-secondary",children:i.noProductsForPeriod}):e.jsxs(e.Fragment,{children:[e.jsx(C.SubscriptionTile,{id:"free",title:i.freeTierTitle,price:i.freeTierPrice,periodLabel:i.periodMonth,features:te(),isSelected:!s?.isActive&&p===null,onSelect:()=>T(null),topBadge:s?.isActive?void 0:{text:i.currentPlanBadge,color:"green"},disabled:I||L,hideSelectionIndicator:!0},"free"),z.map(t=>e.jsx(C.SubscriptionTile,{id:t.identifier,title:t.title,price:t.priceString,periodLabel:Z(t.period),features:ee(t.identifier),isSelected:p===t.identifier,onSelect:()=>T(t.identifier),isBestValue:t.identifier.includes("pro"),discountBadge:t.period?.includes("Y")?(()=>{const n=ie(t.identifier);return n&&n>0?{text:a.formatSavePercent(n),isBestValue:!0}:void 0})():void 0,introPriceNote:t.freeTrialPeriod?R(t.freeTrialPeriod):t.introPrice?a.formatIntroNote(t.introPrice):void 0,disabled:I||L},t.identifier))]})})}c.EntityListPage=U,c.EntitySubscriptionsPage=G,c.InvitationsPage=V,c.MembersManagementPage=H,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
@@ -26,15 +26,71 @@ export interface SubscriptionContextValue {
26
26
  restore: () => Promise<boolean>;
27
27
  clearError: () => void;
28
28
  }
29
- /** Translation function type */
30
- export type TranslationFunction = (key: string, defaultValueOrOptions?: string | Record<string, unknown>, options?: Record<string, unknown>) => string;
29
+ /** All localized labels for the subscription page */
30
+ export interface SubscriptionPageLabels {
31
+ title: string;
32
+ errorTitle: string;
33
+ purchaseError: string;
34
+ restoreError: string;
35
+ restoreNoPurchases: string;
36
+ periodYear: string;
37
+ periodMonth: string;
38
+ periodWeek: string;
39
+ billingMonthly: string;
40
+ billingYearly: string;
41
+ unlimited: string;
42
+ unlimitedRequests: string;
43
+ currentStatusLabel: string;
44
+ statusActive: string;
45
+ statusInactive: string;
46
+ statusInactiveMessage: string;
47
+ labelPlan: string;
48
+ labelPremium: string;
49
+ labelExpires: string;
50
+ labelWillRenew: string;
51
+ labelMonthlyUsage: string;
52
+ labelDailyUsage: string;
53
+ yes: string;
54
+ no: string;
55
+ buttonSubscribe: string;
56
+ buttonPurchasing: string;
57
+ buttonRestore: string;
58
+ buttonRestoring: string;
59
+ noProducts: string;
60
+ noProductsForPeriod: string;
61
+ freeTierTitle: string;
62
+ freeTierPrice: string;
63
+ freeTierFeatures: string[];
64
+ currentPlanBadge: string;
65
+ }
66
+ /** Formatter functions for dynamic strings */
67
+ export interface SubscriptionPageFormatters {
68
+ /** Format rate limit: "1,000 requests/hour" */
69
+ formatHourlyLimit: (limit: string) => string;
70
+ /** Format rate limit: "10,000 requests/day" */
71
+ formatDailyLimit: (limit: string) => string;
72
+ /** Format rate limit: "100,000 requests/month" */
73
+ formatMonthlyLimit: (limit: string) => string;
74
+ /** Format trial period: "7 days free trial" */
75
+ formatTrialDays: (count: number) => string;
76
+ /** Format trial period: "2 weeks free trial" */
77
+ formatTrialWeeks: (count: number) => string;
78
+ /** Format trial period: "1 month free trial" */
79
+ formatTrialMonths: (count: number) => string;
80
+ /** Format savings badge: "Save 20%" */
81
+ formatSavePercent: (percent: number) => string;
82
+ /** Format intro price note */
83
+ formatIntroNote: (price: string) => string;
84
+ }
31
85
  export interface EntitySubscriptionsPageProps {
32
86
  /** Subscription context value */
33
87
  subscription: SubscriptionContextValue;
34
88
  /** Rate limit configuration */
35
89
  rateLimitsConfig?: RateLimitsConfigData | null;
36
- /** Translation function */
37
- t: TranslationFunction;
90
+ /** All localized labels */
91
+ labels: SubscriptionPageLabels;
92
+ /** Formatter functions for dynamic strings */
93
+ formatters: SubscriptionPageFormatters;
38
94
  /** Called when purchase succeeds */
39
95
  onPurchaseSuccess?: () => void;
40
96
  /** Called when restore succeeds */
@@ -47,4 +103,4 @@ export interface EntitySubscriptionsPageProps {
47
103
  /**
48
104
  * Page for managing entity subscriptions.
49
105
  */
50
- export declare function EntitySubscriptionsPage({ subscription, rateLimitsConfig, t, onPurchaseSuccess, onRestoreSuccess, onError, onWarning, }: EntitySubscriptionsPageProps): import("react/jsx-runtime").JSX.Element;
106
+ export declare function EntitySubscriptionsPage({ subscription, rateLimitsConfig, labels, formatters, onPurchaseSuccess, onRestoreSuccess, onError, onWarning, }: EntitySubscriptionsPageProps): import("react/jsx-runtime").JSX.Element;
@@ -4,4 +4,4 @@
4
4
  export { EntityListPage, type EntityListPageProps } from './EntityListPage';
5
5
  export { MembersManagementPage, type MembersManagementPageProps, } from './MembersManagementPage';
6
6
  export { InvitationsPage, type InvitationsPageProps } from './InvitationsPage';
7
- export { EntitySubscriptionsPage, type EntitySubscriptionsPageProps, type SubscriptionProduct, type CurrentSubscription, type SubscriptionContextValue, type TranslationFunction, } from './EntitySubscriptionsPage';
7
+ export { EntitySubscriptionsPage, type EntitySubscriptionsPageProps, type SubscriptionProduct, type CurrentSubscription, type SubscriptionContextValue, type SubscriptionPageLabels, type SubscriptionPageFormatters, } from './EntitySubscriptionsPage';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/entity_pages",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "Page containers for entity/organization management",
5
5
  "type": "module",
6
6
  "main": "dist/index.umd.js",