deepspace 0.4.1 → 0.4.3

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.js CHANGED
@@ -4888,6 +4888,9 @@ async function request(method, endpoint, body, options) {
4888
4888
  } catch {
4889
4889
  }
4890
4890
  const controller = new AbortController();
4891
+ const abortFromCaller = () => controller.abort();
4892
+ if (options?.signal?.aborted) controller.abort();
4893
+ else options?.signal?.addEventListener("abort", abortFromCaller, { once: true });
4891
4894
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
4892
4895
  try {
4893
4896
  const res = await fetch(url, {
@@ -4924,6 +4927,7 @@ async function request(method, endpoint, body, options) {
4924
4927
  };
4925
4928
  } finally {
4926
4929
  clearTimeout(timeout);
4930
+ options?.signal?.removeEventListener("abort", abortFromCaller);
4927
4931
  }
4928
4932
  }
4929
4933
  var integration = {
@@ -5017,8 +5021,364 @@ function decodeAiStreamChunk(chunk) {
5017
5021
  }
5018
5022
  }
5019
5023
 
5024
+ // src/client/status.ts
5025
+ import { useCallback as useCallback26, useEffect as useEffect20, useMemo as useMemo15, useRef as useRef17, useState as useState17 } from "react";
5026
+
5027
+ // src/client/status-core.ts
5028
+ var ASYNC_RESOURCE_DEFAULTS = {
5029
+ retry: 0,
5030
+ retryDelayMs: 2e3,
5031
+ slowAfterMs: 1e4
5032
+ };
5033
+ function isAsyncResourceSlow(input) {
5034
+ return input.slowAfterMs > 0 && input.now - input.startedAt >= input.slowAfterMs;
5035
+ }
5036
+ function getPagedResourceCooldownMs(input) {
5037
+ const failureCount = Math.max(1, input.failureCount);
5038
+ return Math.min(input.maxRetryDelayMs, input.retryDelayMs * 2 ** (failureCount - 1));
5039
+ }
5040
+ function canAutoLoadPagedResource(input) {
5041
+ return input.hasMore && !input.isLoading && input.cooldownUntil <= input.now;
5042
+ }
5043
+ function clampPagedResourceItems(input) {
5044
+ if (input.maxItemsPerPage <= 0 || input.items.length <= input.maxItemsPerPage) {
5045
+ return { items: input.items, droppedItemCount: 0 };
5046
+ }
5047
+ return {
5048
+ items: input.items.slice(0, input.maxItemsPerPage),
5049
+ droppedItemCount: input.items.length - input.maxItemsPerPage
5050
+ };
5051
+ }
5052
+ function deriveLoadState(input) {
5053
+ const auth = input.auth;
5054
+ if (auth) {
5055
+ if (!auth.isLoaded) return "loading";
5056
+ if (auth.requireSignedIn && !auth.isSignedIn) return "signedOut";
5057
+ if (auth.requireUser && auth.isSignedIn && auth.userLoading) return "loading";
5058
+ }
5059
+ const statuses = [...input.queries ?? [], ...input.resources ?? []];
5060
+ if (statuses.some((item) => item.status === "error" || item.error)) return "error";
5061
+ if (statuses.some((item) => item.status === "loading" || item.status === "idle")) return "loading";
5062
+ if (input.empty) return "empty";
5063
+ return "ready";
5064
+ }
5065
+
5066
+ // src/client/status.ts
5067
+ function useAuthStatus(options = {}) {
5068
+ const auth = useAuth();
5069
+ const status = deriveLoadState({
5070
+ auth: {
5071
+ isLoaded: auth.isLoaded,
5072
+ isSignedIn: auth.isSignedIn,
5073
+ requireSignedIn: options.requireSignedIn
5074
+ }
5075
+ });
5076
+ return {
5077
+ ...auth,
5078
+ status,
5079
+ isReady: status === "ready"
5080
+ };
5081
+ }
5082
+ function useAuthProfileReady(options = {}) {
5083
+ const auth = useAuth();
5084
+ const { user, isLoading: userLoading, refetch } = useUser();
5085
+ const status = deriveLoadState({
5086
+ auth: {
5087
+ isLoaded: auth.isLoaded,
5088
+ isSignedIn: auth.isSignedIn,
5089
+ requireSignedIn: options.requireSignedIn,
5090
+ requireUser: options.requireUser,
5091
+ userLoading
5092
+ }
5093
+ });
5094
+ return {
5095
+ ...auth,
5096
+ user,
5097
+ userLoading,
5098
+ refetchUser: refetch,
5099
+ status,
5100
+ isReady: status === "ready"
5101
+ };
5102
+ }
5103
+ var useAuthReady = useAuthProfileReady;
5104
+ function useAsyncResource(fetcher, deps, options = {}) {
5105
+ const enabled = options.enabled ?? true;
5106
+ const keepPreviousData = options.keepPreviousData ?? true;
5107
+ const retry = options.retry ?? ASYNC_RESOURCE_DEFAULTS.retry;
5108
+ const retryDelayMs = options.retryDelayMs ?? ASYNC_RESOURCE_DEFAULTS.retryDelayMs;
5109
+ const slowAfterMs = options.slowAfterMs ?? ASYNC_RESOURCE_DEFAULTS.slowAfterMs;
5110
+ const [state, setState] = useState17(() => ({
5111
+ status: enabled ? "loading" : "idle",
5112
+ data: options.initialData ?? null,
5113
+ error: null,
5114
+ isRefreshing: false,
5115
+ isSlow: false,
5116
+ retryCount: 0
5117
+ }));
5118
+ const requestIdRef = useRef17(0);
5119
+ const [reloadTick, setReloadTick] = useState17(0);
5120
+ const reload = useCallback26(() => {
5121
+ setReloadTick((tick) => tick + 1);
5122
+ }, []);
5123
+ useEffect20(() => {
5124
+ if (!enabled) {
5125
+ setState((prev) => ({ ...prev, status: "idle", isRefreshing: false, isSlow: false, retryCount: 0 }));
5126
+ return;
5127
+ }
5128
+ const requestId = ++requestIdRef.current;
5129
+ const controller = new AbortController();
5130
+ let retryTimer = null;
5131
+ let slowTimer = null;
5132
+ setState((prev) => {
5133
+ const hasData = keepPreviousData && prev.data != null;
5134
+ return {
5135
+ ...prev,
5136
+ status: hasData ? "ready" : "loading",
5137
+ error: null,
5138
+ isRefreshing: hasData,
5139
+ isSlow: false,
5140
+ data: hasData ? prev.data : options.initialData ?? null,
5141
+ retryCount: 0
5142
+ };
5143
+ });
5144
+ if (slowAfterMs > 0) {
5145
+ const startedAt = Date.now();
5146
+ slowTimer = setTimeout(() => {
5147
+ if (requestIdRef.current !== requestId || controller.signal.aborted) return;
5148
+ setState((prev) => ({
5149
+ ...prev,
5150
+ isSlow: isAsyncResourceSlow({ startedAt, now: Date.now(), slowAfterMs })
5151
+ }));
5152
+ }, slowAfterMs);
5153
+ }
5154
+ const wait = (ms) => new Promise((resolve) => {
5155
+ retryTimer = setTimeout(resolve, ms);
5156
+ });
5157
+ const load = async () => {
5158
+ let attempt = 0;
5159
+ while (!controller.signal.aborted) {
5160
+ try {
5161
+ const data = await fetcher(controller.signal);
5162
+ if (requestIdRef.current !== requestId || controller.signal.aborted) return;
5163
+ if (slowTimer) clearTimeout(slowTimer);
5164
+ setState({ status: "ready", data, error: null, isRefreshing: false, isSlow: false, retryCount: attempt });
5165
+ return;
5166
+ } catch (err) {
5167
+ if (requestIdRef.current !== requestId || controller.signal.aborted) return;
5168
+ const message = err instanceof Error ? err.message : "Request failed";
5169
+ if (attempt < retry) {
5170
+ attempt += 1;
5171
+ setState((prev) => ({
5172
+ ...prev,
5173
+ error: message,
5174
+ retryCount: attempt,
5175
+ isRefreshing: keepPreviousData && prev.data != null
5176
+ }));
5177
+ await wait(retryDelayMs);
5178
+ continue;
5179
+ }
5180
+ if (slowTimer) clearTimeout(slowTimer);
5181
+ setState((prev) => ({
5182
+ status: keepPreviousData && prev.data != null ? "ready" : "error",
5183
+ data: keepPreviousData ? prev.data : null,
5184
+ error: message,
5185
+ isRefreshing: false,
5186
+ isSlow: false,
5187
+ retryCount: attempt
5188
+ }));
5189
+ return;
5190
+ }
5191
+ }
5192
+ };
5193
+ load();
5194
+ return () => {
5195
+ if (retryTimer) clearTimeout(retryTimer);
5196
+ if (slowTimer) clearTimeout(slowTimer);
5197
+ controller.abort();
5198
+ };
5199
+ }, [enabled, keepPreviousData, retry, retryDelayMs, slowAfterMs, reloadTick, ...deps]);
5200
+ return useMemo15(() => ({ ...state, reload }), [state, reload]);
5201
+ }
5202
+ function usePagedResource(fetchPage, deps, options = {}) {
5203
+ const enabled = options.enabled ?? true;
5204
+ const initialItems = options.initialItems ?? [];
5205
+ const pageSize = options.pageSize ?? 20;
5206
+ const maxItemsPerPage = options.maxItemsPerPage ?? pageSize;
5207
+ const keepPreviousData = options.keepPreviousData ?? true;
5208
+ const autoRetryOnError = options.autoRetryOnError ?? false;
5209
+ const retryDelayMs = options.retryDelayMs ?? ASYNC_RESOURCE_DEFAULTS.retryDelayMs;
5210
+ const maxRetryDelayMs = options.maxRetryDelayMs ?? 3e4;
5211
+ const hasInitialItems = initialItems.length > 0;
5212
+ const [state, setState] = useState17(() => ({
5213
+ status: enabled ? hasInitialItems ? "ready" : "loading" : "idle",
5214
+ items: initialItems,
5215
+ error: null,
5216
+ warning: null,
5217
+ hasMore: true,
5218
+ isLoadingInitial: enabled && !hasInitialItems,
5219
+ isLoadingMore: false,
5220
+ isRefreshing: false
5221
+ }));
5222
+ const requestIdRef = useRef17(0);
5223
+ const controllerRef = useRef17(null);
5224
+ const loadingRef = useRef17(false);
5225
+ const nextPageRef = useRef17(hasInitialItems ? 2 : 1);
5226
+ const failedPageRef = useRef17(null);
5227
+ const failureCountRef = useRef17(0);
5228
+ const cooldownUntilRef = useRef17(0);
5229
+ const autoRetryTimerRef = useRef17(null);
5230
+ const clearAutoRetryTimer = useCallback26(() => {
5231
+ if (autoRetryTimerRef.current) {
5232
+ clearTimeout(autoRetryTimerRef.current);
5233
+ autoRetryTimerRef.current = null;
5234
+ }
5235
+ }, []);
5236
+ const resetCooldown = useCallback26(() => {
5237
+ failureCountRef.current = 0;
5238
+ cooldownUntilRef.current = 0;
5239
+ }, []);
5240
+ const setFailureCooldown = useCallback26(() => {
5241
+ failureCountRef.current += 1;
5242
+ const delay = getPagedResourceCooldownMs({
5243
+ failureCount: failureCountRef.current,
5244
+ retryDelayMs,
5245
+ maxRetryDelayMs
5246
+ });
5247
+ cooldownUntilRef.current = Date.now() + delay;
5248
+ return delay;
5249
+ }, [maxRetryDelayMs, retryDelayMs]);
5250
+ const startLoad = useCallback26(async (page, mode) => {
5251
+ if (!enabled || loadingRef.current) return;
5252
+ if (mode === "auto" && !canAutoLoadPagedResource({
5253
+ hasMore: true,
5254
+ isLoading: false,
5255
+ now: Date.now(),
5256
+ cooldownUntil: cooldownUntilRef.current
5257
+ })) {
5258
+ return;
5259
+ }
5260
+ clearAutoRetryTimer();
5261
+ loadingRef.current = true;
5262
+ const requestId = ++requestIdRef.current;
5263
+ controllerRef.current?.abort();
5264
+ const controller = new AbortController();
5265
+ controllerRef.current = controller;
5266
+ setState((prev) => {
5267
+ const hasItems = prev.items.length > 0;
5268
+ return {
5269
+ ...prev,
5270
+ status: hasItems && mode !== "refresh" ? "ready" : "loading",
5271
+ error: mode === "auto" && prev.error ? prev.error : null,
5272
+ warning: null,
5273
+ isLoadingInitial: !hasItems && mode !== "refresh",
5274
+ isLoadingMore: hasItems && mode !== "refresh",
5275
+ isRefreshing: mode === "refresh" && hasItems,
5276
+ items: mode === "refresh" && !keepPreviousData ? [] : prev.items
5277
+ };
5278
+ });
5279
+ try {
5280
+ const result = await fetchPage({ page, pageSize, signal: controller.signal });
5281
+ if (requestIdRef.current !== requestId || controller.signal.aborted) return;
5282
+ const { items: pageItems, droppedItemCount } = clampPagedResourceItems({
5283
+ items: result.items,
5284
+ maxItemsPerPage
5285
+ });
5286
+ resetCooldown();
5287
+ failedPageRef.current = null;
5288
+ nextPageRef.current = page + 1;
5289
+ setState((prev) => ({
5290
+ status: "ready",
5291
+ items: page === 1 || mode === "refresh" ? pageItems : [...prev.items, ...pageItems],
5292
+ error: null,
5293
+ warning: droppedItemCount > 0 ? `The last API page returned ${result.items.length} items; only ${pageItems.length} were kept. Request a smaller page from the API instead of fetching the whole feed.` : null,
5294
+ hasMore: droppedItemCount > 0 || (result.hasMore ?? result.items.length >= pageSize),
5295
+ isLoadingInitial: false,
5296
+ isLoadingMore: false,
5297
+ isRefreshing: false
5298
+ }));
5299
+ } catch (err) {
5300
+ if (requestIdRef.current !== requestId || controller.signal.aborted) return;
5301
+ const message = err instanceof Error ? err.message : "Request failed";
5302
+ failedPageRef.current = page;
5303
+ const cooldownMs = setFailureCooldown();
5304
+ setState((prev) => {
5305
+ const hasItems = prev.items.length > 0;
5306
+ return {
5307
+ ...prev,
5308
+ status: hasItems ? "ready" : "error",
5309
+ error: message,
5310
+ warning: prev.warning,
5311
+ hasMore: hasItems ? prev.hasMore : false,
5312
+ isLoadingInitial: false,
5313
+ isLoadingMore: false,
5314
+ isRefreshing: false
5315
+ };
5316
+ });
5317
+ if (autoRetryOnError) {
5318
+ autoRetryTimerRef.current = setTimeout(() => {
5319
+ autoRetryTimerRef.current = null;
5320
+ void startLoad(page, "auto");
5321
+ }, cooldownMs);
5322
+ }
5323
+ } finally {
5324
+ if (requestIdRef.current === requestId) {
5325
+ loadingRef.current = false;
5326
+ controllerRef.current = null;
5327
+ }
5328
+ }
5329
+ }, [autoRetryOnError, clearAutoRetryTimer, enabled, fetchPage, keepPreviousData, pageSize, resetCooldown, setFailureCooldown]);
5330
+ const loadMore = useCallback26(() => {
5331
+ if (!state.hasMore || state.isLoadingInitial || state.isLoadingMore || state.isRefreshing) return;
5332
+ void startLoad(nextPageRef.current, "auto");
5333
+ }, [startLoad, state.hasMore, state.isLoadingInitial, state.isLoadingMore, state.isRefreshing]);
5334
+ const retry = useCallback26(() => {
5335
+ const page = failedPageRef.current ?? nextPageRef.current;
5336
+ void startLoad(page, "manual");
5337
+ }, [startLoad]);
5338
+ const refresh = useCallback26(() => {
5339
+ failedPageRef.current = null;
5340
+ resetCooldown();
5341
+ nextPageRef.current = 1;
5342
+ void startLoad(1, "refresh");
5343
+ }, [resetCooldown, startLoad]);
5344
+ useEffect20(() => {
5345
+ requestIdRef.current += 1;
5346
+ controllerRef.current?.abort();
5347
+ clearAutoRetryTimer();
5348
+ loadingRef.current = false;
5349
+ failedPageRef.current = null;
5350
+ resetCooldown();
5351
+ nextPageRef.current = hasInitialItems ? 2 : 1;
5352
+ setState({
5353
+ status: enabled ? hasInitialItems ? "ready" : "loading" : "idle",
5354
+ items: initialItems,
5355
+ error: null,
5356
+ warning: null,
5357
+ hasMore: true,
5358
+ isLoadingInitial: enabled && !hasInitialItems,
5359
+ isLoadingMore: false,
5360
+ isRefreshing: false
5361
+ });
5362
+ if (enabled && !hasInitialItems) {
5363
+ void startLoad(1, "auto");
5364
+ }
5365
+ return () => {
5366
+ requestIdRef.current += 1;
5367
+ controllerRef.current?.abort();
5368
+ clearAutoRetryTimer();
5369
+ loadingRef.current = false;
5370
+ };
5371
+ }, [enabled, pageSize, maxItemsPerPage, keepPreviousData, autoRetryOnError, retryDelayMs, maxRetryDelayMs, ...deps]);
5372
+ return useMemo15(() => ({
5373
+ ...state,
5374
+ loadMore,
5375
+ retry,
5376
+ refresh
5377
+ }), [loadMore, refresh, retry, state]);
5378
+ }
5379
+
5020
5380
  // src/client/subscriptions/useSubscription.ts
5021
- import { useCallback as useCallback26, useEffect as useEffect20, useState as useState17 } from "react";
5381
+ import { useCallback as useCallback27, useEffect as useEffect21, useState as useState18 } from "react";
5022
5382
 
5023
5383
  // src/shared/subscription.ts
5024
5384
  var ENTITLED_STATUSES = /* @__PURE__ */ new Set([
@@ -5049,7 +5409,7 @@ async function authedJson(path, init) {
5049
5409
  return data;
5050
5410
  }
5051
5411
  function useSubscription() {
5052
- const [state, setState] = useState17({
5412
+ const [state, setState] = useState18({
5053
5413
  tier: "free",
5054
5414
  status: "none",
5055
5415
  interval: null,
@@ -5058,9 +5418,9 @@ function useSubscription() {
5058
5418
  trialEndsAt: null,
5059
5419
  plans: []
5060
5420
  });
5061
- const [isLoading, setLoading] = useState17(true);
5062
- const [error, setError] = useState17(null);
5063
- const refresh = useCallback26(async () => {
5421
+ const [isLoading, setLoading] = useState18(true);
5422
+ const [error, setError] = useState18(null);
5423
+ const refresh = useCallback27(async () => {
5064
5424
  setLoading(true);
5065
5425
  try {
5066
5426
  const r = await authedJson("/_deepspace/subscriptions/me");
@@ -5080,15 +5440,15 @@ function useSubscription() {
5080
5440
  setLoading(false);
5081
5441
  }
5082
5442
  }, []);
5083
- useEffect20(() => {
5443
+ useEffect21(() => {
5084
5444
  refresh();
5085
5445
  }, [refresh]);
5086
5446
  const entitled = isEntitled(state.tier, state.status);
5087
- const hasTier = useCallback26(
5447
+ const hasTier = useCallback27(
5088
5448
  (slug) => state.tier === slug && isEntitled(state.tier, state.status),
5089
5449
  [state.tier, state.status]
5090
5450
  );
5091
- const isAtLeast = useCallback26(
5451
+ const isAtLeast = useCallback27(
5092
5452
  (slug) => {
5093
5453
  if (!isEntitled(state.tier, state.status)) return false;
5094
5454
  const targetRank = state.plans.find((p) => p.slug === slug)?.rank;
@@ -5098,7 +5458,7 @@ function useSubscription() {
5098
5458
  },
5099
5459
  [state.plans, state.tier, state.status]
5100
5460
  );
5101
- const subscribe = useCallback26(
5461
+ const subscribe = useCallback27(
5102
5462
  async (planSlug, opts) => {
5103
5463
  const result = await authedJson("/_deepspace/subscriptions/checkout", {
5104
5464
  method: "POST",
@@ -5118,7 +5478,7 @@ function useSubscription() {
5118
5478
  },
5119
5479
  [refresh]
5120
5480
  );
5121
- const openPortal = useCallback26(
5481
+ const openPortal = useCallback27(
5122
5482
  async (returnUrl) => {
5123
5483
  return authedJson("/_deepspace/subscriptions/portal", {
5124
5484
  method: "POST",
@@ -5187,7 +5547,7 @@ function PricingTable(props) {
5187
5547
  }
5188
5548
 
5189
5549
  // src/client/charges/useCheckout.ts
5190
- import { useCallback as useCallback27, useEffect as useEffect21, useMemo as useMemo15, useState as useState18 } from "react";
5550
+ import { useCallback as useCallback28, useEffect as useEffect22, useMemo as useMemo16, useState as useState19 } from "react";
5191
5551
  async function authedJson2(path, init) {
5192
5552
  const token = await getAuthToken();
5193
5553
  const res = await fetch(path, {
@@ -5206,10 +5566,10 @@ async function authedJson2(path, init) {
5206
5566
  return data;
5207
5567
  }
5208
5568
  function useCheckout(opts) {
5209
- const [purchases, setPurchases] = useState18([]);
5210
- const [isLoading, setLoading] = useState18(true);
5211
- const [error, setError] = useState18(null);
5212
- const refresh = useCallback27(async () => {
5569
+ const [purchases, setPurchases] = useState19([]);
5570
+ const [isLoading, setLoading] = useState19(true);
5571
+ const [error, setError] = useState19(null);
5572
+ const refresh = useCallback28(async () => {
5213
5573
  setLoading(true);
5214
5574
  try {
5215
5575
  const r = await authedJson2(
@@ -5223,10 +5583,10 @@ function useCheckout(opts) {
5223
5583
  setLoading(false);
5224
5584
  }
5225
5585
  }, []);
5226
- useEffect21(() => {
5586
+ useEffect22(() => {
5227
5587
  refresh();
5228
5588
  }, [refresh]);
5229
- const chargeOnce = useCallback27(
5589
+ const chargeOnce = useCallback28(
5230
5590
  async (chargeOpts) => {
5231
5591
  setError(null);
5232
5592
  const common = {
@@ -5260,11 +5620,11 @@ function useCheckout(opts) {
5260
5620
  },
5261
5621
  []
5262
5622
  );
5263
- const ownsProduct = useCallback27(
5623
+ const ownsProduct = useCallback28(
5264
5624
  (productId) => purchases.some((p) => p.productId === productId),
5265
5625
  [purchases]
5266
5626
  );
5267
- const owned = useMemo15(
5627
+ const owned = useMemo16(
5268
5628
  () => !!opts?.productId && purchases.some((p) => p.productId === opts.productId),
5269
5629
  [opts?.productId, purchases]
5270
5630
  );
@@ -5516,13 +5876,14 @@ var buttonVariants = cva(
5516
5876
  }
5517
5877
  );
5518
5878
  var Button = React11.forwardRef(
5519
- ({ className, variant, size, asChild = false, loading = false, disabled, children, ...props }, ref) => {
5879
+ ({ className, variant, size, asChild = false, loading = false, disabled, children, type, ...props }, ref) => {
5520
5880
  const Comp = asChild ? Slot : "button";
5521
5881
  return /* @__PURE__ */ jsxs6(
5522
5882
  Comp,
5523
5883
  {
5524
5884
  className: cn(buttonVariants({ variant, size, className })),
5525
5885
  ref,
5886
+ type: asChild ? void 0 : type ?? "button",
5526
5887
  disabled: disabled || loading,
5527
5888
  ...props,
5528
5889
  children: [
@@ -6111,9 +6472,9 @@ AlertDescription.displayName = "AlertDescription";
6111
6472
  import {
6112
6473
  createContext as createContext4,
6113
6474
  useContext as useContext6,
6114
- useState as useState19,
6115
- useCallback as useCallback28,
6116
- useEffect as useEffect22
6475
+ useState as useState20,
6476
+ useCallback as useCallback29,
6477
+ useEffect as useEffect23
6117
6478
  } from "react";
6118
6479
  import { jsx as jsx28, jsxs as jsxs10 } from "react/jsx-runtime";
6119
6480
  function CheckCircleIcon({ className }) {
@@ -6160,14 +6521,14 @@ function ToastProvider({
6160
6521
  position = "bottom-right",
6161
6522
  maxToasts = 5
6162
6523
  }) {
6163
- const [toasts, setToasts] = useState19([]);
6164
- const dismiss = useCallback28((id) => {
6524
+ const [toasts, setToasts] = useState20([]);
6525
+ const dismiss = useCallback29((id) => {
6165
6526
  setToasts((prev) => prev.filter((t) => t.id !== id));
6166
6527
  }, []);
6167
- const dismissAll = useCallback28(() => {
6528
+ const dismissAll = useCallback29(() => {
6168
6529
  setToasts([]);
6169
6530
  }, []);
6170
- const addToast = useCallback28(
6531
+ const addToast = useCallback29(
6171
6532
  (options) => {
6172
6533
  const id = Math.random().toString(36).slice(2);
6173
6534
  const duration = options.duration ?? 5e3;
@@ -6181,23 +6542,23 @@ function ToastProvider({
6181
6542
  },
6182
6543
  [dismiss, maxToasts]
6183
6544
  );
6184
- const toast = useCallback28(
6545
+ const toast = useCallback29(
6185
6546
  (options) => addToast(options),
6186
6547
  [addToast]
6187
6548
  );
6188
- const success = useCallback28(
6549
+ const success = useCallback29(
6189
6550
  (title, description) => addToast({ type: "success", title, description }),
6190
6551
  [addToast]
6191
6552
  );
6192
- const error = useCallback28(
6553
+ const error = useCallback29(
6193
6554
  (title, description) => addToast({ type: "error", title, description }),
6194
6555
  [addToast]
6195
6556
  );
6196
- const warning = useCallback28(
6557
+ const warning = useCallback29(
6197
6558
  (title, description) => addToast({ type: "warning", title, description }),
6198
6559
  [addToast]
6199
6560
  );
6200
- const info = useCallback28(
6561
+ const info = useCallback29(
6201
6562
  (title, description) => addToast({ type: "info", title, description }),
6202
6563
  [addToast]
6203
6564
  );
@@ -6234,8 +6595,8 @@ var TOAST_CONFIG = {
6234
6595
  };
6235
6596
  function ToastItem({ toast, onDismiss }) {
6236
6597
  const { Icon: Icon2, accent, icon } = TOAST_CONFIG[toast.type];
6237
- const [exiting, setExiting] = useState19(false);
6238
- useEffect22(() => {
6598
+ const [exiting, setExiting] = useState20(false);
6599
+ useEffect23(() => {
6239
6600
  if (exiting) {
6240
6601
  const timer = setTimeout(onDismiss, 150);
6241
6602
  return () => clearTimeout(timer);
@@ -6272,9 +6633,109 @@ function ToastItem({ toast, onDismiss }) {
6272
6633
  );
6273
6634
  }
6274
6635
 
6636
+ // src/ui/ErrorBoundary.tsx
6637
+ import { AlertTriangle, RefreshCw } from "lucide-react";
6638
+ import { jsx as jsx29, jsxs as jsxs11 } from "react/jsx-runtime";
6639
+ var REACT_ERROR_TABLE = {
6640
+ 300: {
6641
+ title: "A component changed how many hooks it runs",
6642
+ explanation: "This component called fewer hooks than it did on its previous render.",
6643
+ hint: "Almost always an early return placed above a hook. Move every hook (useState, useEffect, useQuery, \u2026) above any conditional return so the same hooks run in the same order on every render."
6644
+ },
6645
+ 310: {
6646
+ title: "A component changed how many hooks it runs",
6647
+ explanation: "This component called more hooks than it did on its previous render.",
6648
+ hint: "Almost always an early return placed above a hook. Move every hook (useState, useEffect, useQuery, \u2026) above any conditional return so the same hooks run in the same order on every render."
6649
+ },
6650
+ 301: {
6651
+ title: "Too many re-renders",
6652
+ explanation: "React hit its render limit because the component updated state while rendering, which triggers an infinite render loop.",
6653
+ hint: "Don\u2019t call setState (or a mutation) directly in the render body. Move it into an event handler or an effect with the right dependencies."
6654
+ },
6655
+ 321: {
6656
+ title: "A hook was called in an invalid place",
6657
+ explanation: "Hooks can only be called at the top level of a function component or another hook.",
6658
+ hint: "Move the hook out of any condition, loop, callback, or plain (non-component) function. This can also mean two copies of React are installed."
6659
+ }
6660
+ };
6661
+ function extractReactErrorCode(message) {
6662
+ const patterns = [/react\.dev\/errors\/(\d+)/, /invariant=(\d+)/, /Minified React error #(\d+)/];
6663
+ for (const re of patterns) {
6664
+ const match = message.match(re);
6665
+ if (match) return Number(match[1]);
6666
+ }
6667
+ return null;
6668
+ }
6669
+ function errorMessage(error) {
6670
+ if (typeof error === "string") return error;
6671
+ if (error instanceof Error) return error.message;
6672
+ return null;
6673
+ }
6674
+ function decodeReactError(error) {
6675
+ const message = errorMessage(error);
6676
+ if (!message) return null;
6677
+ const code = extractReactErrorCode(message);
6678
+ if (code == null) return null;
6679
+ const known = REACT_ERROR_TABLE[code];
6680
+ return {
6681
+ code,
6682
+ docsUrl: `https://react.dev/errors/${code}`,
6683
+ title: known?.title ?? `React error #${code}`,
6684
+ explanation: known?.explanation ?? "React stopped rendering because of an error.",
6685
+ hint: known?.hint ?? "Run the app in development (npm run dev) to see the full, unminified message and the component that failed."
6686
+ };
6687
+ }
6688
+ function ErrorScreen({ error, onReset }) {
6689
+ const decoded = decodeReactError(error);
6690
+ const rawMessage = error instanceof Error ? error.message : typeof error === "string" ? error : "";
6691
+ const stack = error instanceof Error ? error.stack : void 0;
6692
+ const reset = onReset ?? (() => window.location.reload());
6693
+ return /* @__PURE__ */ jsx29(
6694
+ "div",
6695
+ {
6696
+ "data-testid": "ds-error-boundary",
6697
+ className: "flex h-full min-h-[60vh] flex-col items-center justify-center bg-background px-4 py-10 text-foreground",
6698
+ children: /* @__PURE__ */ jsxs11("div", { className: "w-full max-w-lg text-center", children: [
6699
+ /* @__PURE__ */ jsx29("div", { className: "mb-4 flex justify-center", children: /* @__PURE__ */ jsx29("span", { className: "inline-flex h-12 w-12 items-center justify-center rounded-full bg-destructive/10 text-destructive", children: /* @__PURE__ */ jsx29(AlertTriangle, { className: "h-6 w-6", "aria-hidden": true }) }) }),
6700
+ /* @__PURE__ */ jsx29("h1", { className: "text-lg font-semibold tracking-tight", children: decoded?.title ?? "Something went wrong" }),
6701
+ decoded?.explanation && /* @__PURE__ */ jsx29("p", { className: "mt-1.5 text-sm text-muted-foreground", children: decoded.explanation }),
6702
+ decoded?.hint && /* @__PURE__ */ jsxs11(Alert, { variant: "warning", className: "mt-4 text-left", children: [
6703
+ /* @__PURE__ */ jsx29(AlertTitle, { children: "How to fix" }),
6704
+ /* @__PURE__ */ jsx29(AlertDescription, { children: decoded.hint })
6705
+ ] }),
6706
+ rawMessage && /* @__PURE__ */ jsx29("pre", { className: "mt-4 overflow-x-auto rounded-lg border bg-muted/40 px-3 py-2 text-left text-xs text-muted-foreground", children: rawMessage }),
6707
+ stack && /* @__PURE__ */ jsxs11("details", { className: "mt-2 text-left", children: [
6708
+ /* @__PURE__ */ jsx29("summary", { className: "cursor-pointer text-xs text-muted-foreground", children: "Show stack trace" }),
6709
+ /* @__PURE__ */ jsx29("pre", { className: "mt-1 max-h-60 overflow-auto rounded-lg border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: stack })
6710
+ ] }),
6711
+ /* @__PURE__ */ jsxs11("div", { className: "mt-6 flex items-center justify-center gap-3", children: [
6712
+ /* @__PURE__ */ jsxs11(Button, { onClick: reset, children: [
6713
+ /* @__PURE__ */ jsx29(RefreshCw, { className: "h-4 w-4", "aria-hidden": true }),
6714
+ "Reload"
6715
+ ] }),
6716
+ decoded && /* @__PURE__ */ jsxs11(
6717
+ "a",
6718
+ {
6719
+ href: decoded.docsUrl,
6720
+ target: "_blank",
6721
+ rel: "noreferrer",
6722
+ className: "text-sm text-muted-foreground underline-offset-4 hover:underline",
6723
+ children: [
6724
+ "React error #",
6725
+ decoded.code,
6726
+ " reference"
6727
+ ]
6728
+ }
6729
+ )
6730
+ ] })
6731
+ ] })
6732
+ }
6733
+ );
6734
+ }
6735
+
6275
6736
  // src/ui/EmptyState.tsx
6276
6737
  import { FileText, Search, Inbox, Plus, FolderOpen, Users, AlertCircle } from "lucide-react";
6277
- import { jsx as jsx29, jsxs as jsxs11 } from "react/jsx-runtime";
6738
+ import { jsx as jsx30, jsxs as jsxs12 } from "react/jsx-runtime";
6278
6739
  function EmptyState({
6279
6740
  icon,
6280
6741
  title,
@@ -6284,23 +6745,23 @@ function EmptyState({
6284
6745
  className = "",
6285
6746
  ...rest
6286
6747
  }) {
6287
- return /* @__PURE__ */ jsxs11("div", { className: cn("flex flex-col items-center justify-center py-16 px-4 text-center", className), ...rest, children: [
6288
- icon && /* @__PURE__ */ jsx29("div", { className: "w-16 h-16 rounded-2xl bg-muted/50 border border-border flex items-center justify-center mb-5", children: /* @__PURE__ */ jsx29("span", { className: "text-muted-foreground", children: icon }) }),
6289
- /* @__PURE__ */ jsx29("h3", { className: "text-lg font-semibold text-foreground mb-2", children: title }),
6290
- description && /* @__PURE__ */ jsx29("p", { className: "text-muted-foreground text-sm max-w-sm mb-6", children: description }),
6291
- (action || secondaryAction) && /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3", children: [
6292
- action && /* @__PURE__ */ jsxs11(
6748
+ return /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-col items-center justify-center py-16 px-4 text-center", className), ...rest, children: [
6749
+ icon && /* @__PURE__ */ jsx30("div", { className: "w-16 h-16 rounded-2xl bg-muted/50 border border-border flex items-center justify-center mb-5", children: /* @__PURE__ */ jsx30("span", { className: "text-muted-foreground", children: icon }) }),
6750
+ /* @__PURE__ */ jsx30("h3", { className: "text-lg font-semibold text-foreground mb-2", children: title }),
6751
+ description && /* @__PURE__ */ jsx30("p", { className: "text-muted-foreground text-sm max-w-sm mb-6", children: description }),
6752
+ (action || secondaryAction) && /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
6753
+ action && /* @__PURE__ */ jsxs12(
6293
6754
  "button",
6294
6755
  {
6295
6756
  onClick: action.onClick,
6296
6757
  className: "inline-flex items-center gap-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg font-medium text-sm hover:bg-primary/90 shadow-lg shadow-primary/25 transition-all",
6297
6758
  children: [
6298
- /* @__PURE__ */ jsx29(Plus, { className: "w-4 h-4" }),
6759
+ /* @__PURE__ */ jsx30(Plus, { className: "w-4 h-4" }),
6299
6760
  action.label
6300
6761
  ]
6301
6762
  }
6302
6763
  ),
6303
- secondaryAction && /* @__PURE__ */ jsx29(
6764
+ secondaryAction && /* @__PURE__ */ jsx30(
6304
6765
  "button",
6305
6766
  {
6306
6767
  onClick: secondaryAction.onClick,
@@ -6312,10 +6773,10 @@ function EmptyState({
6312
6773
  ] });
6313
6774
  }
6314
6775
  function EmptyItems({ action, className }) {
6315
- return /* @__PURE__ */ jsx29(
6776
+ return /* @__PURE__ */ jsx30(
6316
6777
  EmptyState,
6317
6778
  {
6318
- icon: /* @__PURE__ */ jsx29(Inbox, { className: "w-8 h-8" }),
6779
+ icon: /* @__PURE__ */ jsx30(Inbox, { className: "w-8 h-8" }),
6319
6780
  title: "No items yet",
6320
6781
  description: "Get started by creating your first item.",
6321
6782
  action: action ? { label: action.label, onClick: action.onClick } : void 0,
@@ -6324,10 +6785,10 @@ function EmptyItems({ action, className }) {
6324
6785
  );
6325
6786
  }
6326
6787
  function EmptySearch({ query, onClear, className }) {
6327
- return /* @__PURE__ */ jsx29(
6788
+ return /* @__PURE__ */ jsx30(
6328
6789
  EmptyState,
6329
6790
  {
6330
- icon: /* @__PURE__ */ jsx29(Search, { className: "w-8 h-8" }),
6791
+ icon: /* @__PURE__ */ jsx30(Search, { className: "w-8 h-8" }),
6331
6792
  title: "No results found",
6332
6793
  description: query ? `No results for "${query}". Try a different search term.` : "Try adjusting your search or filters.",
6333
6794
  secondaryAction: onClear ? { label: "Clear search", onClick: onClear } : void 0,
@@ -6336,10 +6797,10 @@ function EmptySearch({ query, onClear, className }) {
6336
6797
  );
6337
6798
  }
6338
6799
  function EmptyDocuments({ action, className }) {
6339
- return /* @__PURE__ */ jsx29(
6800
+ return /* @__PURE__ */ jsx30(
6340
6801
  EmptyState,
6341
6802
  {
6342
- icon: /* @__PURE__ */ jsx29(FileText, { className: "w-8 h-8" }),
6803
+ icon: /* @__PURE__ */ jsx30(FileText, { className: "w-8 h-8" }),
6343
6804
  title: "No documents",
6344
6805
  description: "Create a document to start writing.",
6345
6806
  action: action ? { label: action.label, onClick: action.onClick } : void 0,
@@ -6348,10 +6809,10 @@ function EmptyDocuments({ action, className }) {
6348
6809
  );
6349
6810
  }
6350
6811
  function EmptyProjects({ action, className }) {
6351
- return /* @__PURE__ */ jsx29(
6812
+ return /* @__PURE__ */ jsx30(
6352
6813
  EmptyState,
6353
6814
  {
6354
- icon: /* @__PURE__ */ jsx29(FolderOpen, { className: "w-8 h-8" }),
6815
+ icon: /* @__PURE__ */ jsx30(FolderOpen, { className: "w-8 h-8" }),
6355
6816
  title: "No projects",
6356
6817
  description: "Create a project to organize your work.",
6357
6818
  action: action ? { label: action.label, onClick: action.onClick } : void 0,
@@ -6360,10 +6821,10 @@ function EmptyProjects({ action, className }) {
6360
6821
  );
6361
6822
  }
6362
6823
  function EmptyTeam({ action, className }) {
6363
- return /* @__PURE__ */ jsx29(
6824
+ return /* @__PURE__ */ jsx30(
6364
6825
  EmptyState,
6365
6826
  {
6366
- icon: /* @__PURE__ */ jsx29(Users, { className: "w-8 h-8" }),
6827
+ icon: /* @__PURE__ */ jsx30(Users, { className: "w-8 h-8" }),
6367
6828
  title: "No team members",
6368
6829
  description: "Invite people to collaborate with you.",
6369
6830
  action: action ? { label: action.label, onClick: action.onClick } : void 0,
@@ -6372,10 +6833,10 @@ function EmptyTeam({ action, className }) {
6372
6833
  );
6373
6834
  }
6374
6835
  function EmptyError({ error, onRetry, className }) {
6375
- return /* @__PURE__ */ jsx29(
6836
+ return /* @__PURE__ */ jsx30(
6376
6837
  EmptyState,
6377
6838
  {
6378
- icon: /* @__PURE__ */ jsx29(AlertCircle, { className: "w-8 h-8 text-destructive" }),
6839
+ icon: /* @__PURE__ */ jsx30(AlertCircle, { className: "w-8 h-8 text-destructive" }),
6379
6840
  title: "Something went wrong",
6380
6841
  description: error || "An error occurred. Please try again.",
6381
6842
  action: onRetry ? { label: "Try again", onClick: onRetry } : void 0,
@@ -6388,12 +6849,12 @@ function EmptyError({ error, onRetry, className }) {
6388
6849
  import * as React22 from "react";
6389
6850
  import * as DialogPrimitive from "@radix-ui/react-dialog";
6390
6851
  import { X } from "lucide-react";
6391
- import { jsx as jsx30, jsxs as jsxs12 } from "react/jsx-runtime";
6852
+ import { jsx as jsx31, jsxs as jsxs13 } from "react/jsx-runtime";
6392
6853
  var Dialog = DialogPrimitive.Root;
6393
6854
  var DialogTrigger = DialogPrimitive.Trigger;
6394
6855
  var DialogPortal = DialogPrimitive.Portal;
6395
6856
  var DialogClose = DialogPrimitive.Close;
6396
- var DialogOverlay = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
6857
+ var DialogOverlay = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
6397
6858
  DialogPrimitive.Overlay,
6398
6859
  {
6399
6860
  ref,
@@ -6405,9 +6866,9 @@ var DialogOverlay = React22.forwardRef(({ className, ...props }, ref) => /* @__P
6405
6866
  }
6406
6867
  ));
6407
6868
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
6408
- var DialogContent = React22.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs12(DialogPortal, { children: [
6409
- /* @__PURE__ */ jsx30(DialogOverlay, {}),
6410
- /* @__PURE__ */ jsxs12(
6869
+ var DialogContent = React22.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs13(DialogPortal, { children: [
6870
+ /* @__PURE__ */ jsx31(DialogOverlay, {}),
6871
+ /* @__PURE__ */ jsxs13(
6411
6872
  DialogPrimitive.Content,
6412
6873
  {
6413
6874
  ref,
@@ -6418,9 +6879,9 @@ var DialogContent = React22.forwardRef(({ className, children, ...props }, ref)
6418
6879
  ...props,
6419
6880
  children: [
6420
6881
  children,
6421
- /* @__PURE__ */ jsxs12(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm p-1 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
6422
- /* @__PURE__ */ jsx30(X, { className: "h-4 w-4" }),
6423
- /* @__PURE__ */ jsx30("span", { className: "sr-only", children: "Close" })
6882
+ /* @__PURE__ */ jsxs13(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm p-1 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
6883
+ /* @__PURE__ */ jsx31(X, { className: "h-4 w-4" }),
6884
+ /* @__PURE__ */ jsx31("span", { className: "sr-only", children: "Close" })
6424
6885
  ] })
6425
6886
  ]
6426
6887
  }
@@ -6430,7 +6891,7 @@ DialogContent.displayName = DialogPrimitive.Content.displayName;
6430
6891
  var DialogHeader = ({
6431
6892
  className,
6432
6893
  ...props
6433
- }) => /* @__PURE__ */ jsx30(
6894
+ }) => /* @__PURE__ */ jsx31(
6434
6895
  "div",
6435
6896
  {
6436
6897
  className: cn(
@@ -6444,7 +6905,7 @@ DialogHeader.displayName = "DialogHeader";
6444
6905
  var DialogFooter = ({
6445
6906
  className,
6446
6907
  ...props
6447
- }) => /* @__PURE__ */ jsx30(
6908
+ }) => /* @__PURE__ */ jsx31(
6448
6909
  "div",
6449
6910
  {
6450
6911
  className: cn(
@@ -6455,7 +6916,7 @@ var DialogFooter = ({
6455
6916
  }
6456
6917
  );
6457
6918
  DialogFooter.displayName = "DialogFooter";
6458
- var DialogTitle = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
6919
+ var DialogTitle = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
6459
6920
  DialogPrimitive.Title,
6460
6921
  {
6461
6922
  ref,
@@ -6467,7 +6928,7 @@ var DialogTitle = React22.forwardRef(({ className, ...props }, ref) => /* @__PUR
6467
6928
  }
6468
6929
  ));
6469
6930
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
6470
- var DialogDescription = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
6931
+ var DialogDescription = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
6471
6932
  DialogPrimitive.Description,
6472
6933
  {
6473
6934
  ref,
@@ -6481,14 +6942,14 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
6481
6942
  import * as React23 from "react";
6482
6943
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
6483
6944
  import { Check as Check3, ChevronRight, Circle } from "lucide-react";
6484
- import { jsx as jsx31, jsxs as jsxs13 } from "react/jsx-runtime";
6945
+ import { jsx as jsx32, jsxs as jsxs14 } from "react/jsx-runtime";
6485
6946
  var DropdownMenu = DropdownMenuPrimitive.Root;
6486
6947
  var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
6487
6948
  var DropdownMenuGroup = DropdownMenuPrimitive.Group;
6488
6949
  var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
6489
6950
  var DropdownMenuSub = DropdownMenuPrimitive.Sub;
6490
6951
  var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
6491
- var DropdownMenuSubTrigger = React23.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs13(
6952
+ var DropdownMenuSubTrigger = React23.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
6492
6953
  DropdownMenuPrimitive.SubTrigger,
6493
6954
  {
6494
6955
  ref,
@@ -6500,12 +6961,12 @@ var DropdownMenuSubTrigger = React23.forwardRef(({ className, inset, children, .
6500
6961
  ...props,
6501
6962
  children: [
6502
6963
  children,
6503
- /* @__PURE__ */ jsx31(ChevronRight, { className: "ml-auto" })
6964
+ /* @__PURE__ */ jsx32(ChevronRight, { className: "ml-auto" })
6504
6965
  ]
6505
6966
  }
6506
6967
  ));
6507
6968
  DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
6508
- var DropdownMenuSubContent = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
6969
+ var DropdownMenuSubContent = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx32(
6509
6970
  DropdownMenuPrimitive.SubContent,
6510
6971
  {
6511
6972
  ref,
@@ -6517,7 +6978,7 @@ var DropdownMenuSubContent = React23.forwardRef(({ className, ...props }, ref) =
6517
6978
  }
6518
6979
  ));
6519
6980
  DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
6520
- var DropdownMenuContent = React23.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx31(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx31(
6981
+ var DropdownMenuContent = React23.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx32(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx32(
6521
6982
  DropdownMenuPrimitive.Content,
6522
6983
  {
6523
6984
  ref,
@@ -6531,7 +6992,7 @@ var DropdownMenuContent = React23.forwardRef(({ className, sideOffset = 4, ...pr
6531
6992
  }
6532
6993
  ) }));
6533
6994
  DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
6534
- var DropdownMenuItem = React23.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx31(
6995
+ var DropdownMenuItem = React23.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx32(
6535
6996
  DropdownMenuPrimitive.Item,
6536
6997
  {
6537
6998
  ref,
@@ -6544,7 +7005,7 @@ var DropdownMenuItem = React23.forwardRef(({ className, inset, ...props }, ref)
6544
7005
  }
6545
7006
  ));
6546
7007
  DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
6547
- var DropdownMenuCheckboxItem = React23.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs13(
7008
+ var DropdownMenuCheckboxItem = React23.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs14(
6548
7009
  DropdownMenuPrimitive.CheckboxItem,
6549
7010
  {
6550
7011
  ref,
@@ -6555,13 +7016,13 @@ var DropdownMenuCheckboxItem = React23.forwardRef(({ className, children, checke
6555
7016
  checked,
6556
7017
  ...props,
6557
7018
  children: [
6558
- /* @__PURE__ */ jsx31("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx31(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx31(Check3, { className: "h-4 w-4" }) }) }),
7019
+ /* @__PURE__ */ jsx32("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx32(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx32(Check3, { className: "h-4 w-4" }) }) }),
6559
7020
  children
6560
7021
  ]
6561
7022
  }
6562
7023
  ));
6563
7024
  DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
6564
- var DropdownMenuRadioItem = React23.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs13(
7025
+ var DropdownMenuRadioItem = React23.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
6565
7026
  DropdownMenuPrimitive.RadioItem,
6566
7027
  {
6567
7028
  ref,
@@ -6571,13 +7032,13 @@ var DropdownMenuRadioItem = React23.forwardRef(({ className, children, ...props
6571
7032
  ),
6572
7033
  ...props,
6573
7034
  children: [
6574
- /* @__PURE__ */ jsx31("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx31(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx31(Circle, { className: "h-2 w-2 fill-current" }) }) }),
7035
+ /* @__PURE__ */ jsx32("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx32(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx32(Circle, { className: "h-2 w-2 fill-current" }) }) }),
6575
7036
  children
6576
7037
  ]
6577
7038
  }
6578
7039
  ));
6579
7040
  DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
6580
- var DropdownMenuLabel = React23.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx31(
7041
+ var DropdownMenuLabel = React23.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx32(
6581
7042
  DropdownMenuPrimitive.Label,
6582
7043
  {
6583
7044
  ref,
@@ -6590,7 +7051,7 @@ var DropdownMenuLabel = React23.forwardRef(({ className, inset, ...props }, ref)
6590
7051
  }
6591
7052
  ));
6592
7053
  DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
6593
- var DropdownMenuSeparator = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
7054
+ var DropdownMenuSeparator = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx32(
6594
7055
  DropdownMenuPrimitive.Separator,
6595
7056
  {
6596
7057
  ref,
@@ -6603,7 +7064,7 @@ var DropdownMenuShortcut = ({
6603
7064
  className,
6604
7065
  ...props
6605
7066
  }) => {
6606
- return /* @__PURE__ */ jsx31(
7067
+ return /* @__PURE__ */ jsx32(
6607
7068
  "span",
6608
7069
  {
6609
7070
  className: cn("ml-auto text-xs tracking-widest opacity-60", className),
@@ -6616,11 +7077,11 @@ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
6616
7077
  // src/ui/Tooltip.tsx
6617
7078
  import * as React24 from "react";
6618
7079
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
6619
- import { jsx as jsx32 } from "react/jsx-runtime";
7080
+ import { jsx as jsx33 } from "react/jsx-runtime";
6620
7081
  var TooltipProvider = TooltipPrimitive.Provider;
6621
7082
  var Tooltip = TooltipPrimitive.Root;
6622
7083
  var TooltipTrigger = TooltipPrimitive.Trigger;
6623
- var TooltipContent = React24.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx32(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx32(
7084
+ var TooltipContent = React24.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx33(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx33(
6624
7085
  TooltipPrimitive.Content,
6625
7086
  {
6626
7087
  ref,
@@ -6635,7 +7096,7 @@ var TooltipContent = React24.forwardRef(({ className, sideOffset = 4, ...props }
6635
7096
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
6636
7097
 
6637
7098
  // src/ui/Modal.tsx
6638
- import { jsx as jsx33, jsxs as jsxs14 } from "react/jsx-runtime";
7099
+ import { jsx as jsx34, jsxs as jsxs15 } from "react/jsx-runtime";
6639
7100
  function Modal({
6640
7101
  open,
6641
7102
  onClose,
@@ -6649,24 +7110,24 @@ function Modal({
6649
7110
  lg: "max-w-[calc(100vw-2rem)] sm:max-w-2xl",
6650
7111
  xl: "max-w-[calc(100vw-2rem)] sm:max-w-4xl"
6651
7112
  };
6652
- return /* @__PURE__ */ jsx33(Dialog, { open, onOpenChange: (v) => {
7113
+ return /* @__PURE__ */ jsx34(Dialog, { open, onOpenChange: (v) => {
6653
7114
  if (!v) onClose();
6654
- }, children: /* @__PURE__ */ jsx33(DialogContent, { "aria-describedby": void 0, className: cn(sizes[size], "flex flex-col max-h-[85vh]", className), children }) });
7115
+ }, children: /* @__PURE__ */ jsx34(DialogContent, { "aria-describedby": void 0, className: cn(sizes[size], "flex flex-col max-h-[85vh]", className), children }) });
6655
7116
  }
6656
7117
  function ModalHeader({ children, className = "" }) {
6657
- return /* @__PURE__ */ jsx33(DialogHeader, { className, children });
7118
+ return /* @__PURE__ */ jsx34(DialogHeader, { className, children });
6658
7119
  }
6659
7120
  function ModalTitle({ children, className = "" }) {
6660
- return /* @__PURE__ */ jsx33(DialogTitle, { className, children });
7121
+ return /* @__PURE__ */ jsx34(DialogTitle, { className, children });
6661
7122
  }
6662
7123
  function ModalDescription({ children, className = "" }) {
6663
- return /* @__PURE__ */ jsx33(DialogDescription, { className, children });
7124
+ return /* @__PURE__ */ jsx34(DialogDescription, { className, children });
6664
7125
  }
6665
7126
  function ModalBody({ children, className = "" }) {
6666
- return /* @__PURE__ */ jsx33("div", { className: cn("flex-1 overflow-y-auto py-4", className), children });
7127
+ return /* @__PURE__ */ jsx34("div", { className: cn("flex-1 overflow-y-auto py-4", className), children });
6667
7128
  }
6668
7129
  function ModalFooter({ children, className = "" }) {
6669
- return /* @__PURE__ */ jsx33(DialogFooter, { className, children });
7130
+ return /* @__PURE__ */ jsx34(DialogFooter, { className, children });
6670
7131
  }
6671
7132
  function ConfirmModal({
6672
7133
  open,
@@ -6679,14 +7140,14 @@ function ConfirmModal({
6679
7140
  variant = "destructive",
6680
7141
  loading = false
6681
7142
  }) {
6682
- return /* @__PURE__ */ jsxs14(Modal, { open, onClose, size: "sm", children: [
6683
- /* @__PURE__ */ jsxs14(Modal.Header, { children: [
6684
- /* @__PURE__ */ jsx33(Modal.Title, { children: title }),
6685
- description && /* @__PURE__ */ jsx33(Modal.Description, { children: description })
7143
+ return /* @__PURE__ */ jsxs15(Modal, { open, onClose, size: "sm", children: [
7144
+ /* @__PURE__ */ jsxs15(Modal.Header, { children: [
7145
+ /* @__PURE__ */ jsx34(Modal.Title, { children: title }),
7146
+ description && /* @__PURE__ */ jsx34(Modal.Description, { children: description })
6686
7147
  ] }),
6687
- /* @__PURE__ */ jsxs14(Modal.Footer, { children: [
6688
- /* @__PURE__ */ jsx33(Button, { variant: "ghost", onClick: onClose, disabled: loading, children: cancelText }),
6689
- /* @__PURE__ */ jsx33(Button, { variant, onClick: onConfirm, loading, children: confirmText })
7148
+ /* @__PURE__ */ jsxs15(Modal.Footer, { children: [
7149
+ /* @__PURE__ */ jsx34(Button, { variant: "ghost", onClick: onClose, disabled: loading, children: cancelText }),
7150
+ /* @__PURE__ */ jsx34(Button, { variant, onClick: onConfirm, loading, children: confirmText })
6690
7151
  ] })
6691
7152
  ] });
6692
7153
  }
@@ -6699,12 +7160,12 @@ Modal.Footer = ModalFooter;
6699
7160
  // src/ui/SearchInput.tsx
6700
7161
  import * as React25 from "react";
6701
7162
  import { Search as Search2, X as X2 } from "lucide-react";
6702
- import { jsx as jsx34, jsxs as jsxs15 } from "react/jsx-runtime";
7163
+ import { jsx as jsx35, jsxs as jsxs16 } from "react/jsx-runtime";
6703
7164
  var SearchInput = React25.forwardRef(
6704
7165
  ({ className, onClear, value, ...props }, ref) => {
6705
- return /* @__PURE__ */ jsxs15("div", { className: "relative", children: [
6706
- /* @__PURE__ */ jsx34(Search2, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
6707
- /* @__PURE__ */ jsx34(
7166
+ return /* @__PURE__ */ jsxs16("div", { className: "relative", children: [
7167
+ /* @__PURE__ */ jsx35(Search2, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
7168
+ /* @__PURE__ */ jsx35(
6708
7169
  Input,
6709
7170
  {
6710
7171
  ref,
@@ -6714,13 +7175,13 @@ var SearchInput = React25.forwardRef(
6714
7175
  ...props
6715
7176
  }
6716
7177
  ),
6717
- value && onClear && /* @__PURE__ */ jsx34(
7178
+ value && onClear && /* @__PURE__ */ jsx35(
6718
7179
  "button",
6719
7180
  {
6720
7181
  type: "button",
6721
7182
  onClick: onClear,
6722
7183
  className: "absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground hover:text-foreground transition-colors",
6723
- children: /* @__PURE__ */ jsx34(X2, { className: "h-4 w-4" })
7184
+ children: /* @__PURE__ */ jsx35(X2, { className: "h-4 w-4" })
6724
7185
  }
6725
7186
  )
6726
7187
  ] });
@@ -6728,6 +7189,7 @@ var SearchInput = React25.forwardRef(
6728
7189
  );
6729
7190
  SearchInput.displayName = "SearchInput";
6730
7191
  export {
7192
+ ASYNC_RESOURCE_DEFAULTS,
6731
7193
  Alert,
6732
7194
  AlertDescription,
6733
7195
  AlertTitle,
@@ -6785,6 +7247,7 @@ export {
6785
7247
  EmptySearch,
6786
7248
  EmptyState,
6787
7249
  EmptyTeam,
7250
+ ErrorScreen,
6788
7251
  GridCard,
6789
7252
  GuestBanner,
6790
7253
  Input,
@@ -6854,6 +7317,8 @@ export {
6854
7317
  authClient,
6855
7318
  badgeVariants,
6856
7319
  buttonVariants,
7320
+ canAutoLoadPagedResource,
7321
+ clampPagedResourceItems,
6857
7322
  clearAuthToken,
6858
7323
  clearDeepSpaceTheme,
6859
7324
  clientBuild,
@@ -6861,6 +7326,8 @@ export {
6861
7326
  createDecoder,
6862
7327
  createEncoder,
6863
7328
  decodeAiStreamChunk,
7329
+ decodeReactError,
7330
+ deriveLoadState,
6864
7331
  detectEnvironment,
6865
7332
  dispatch,
6866
7333
  encode,
@@ -6878,6 +7345,7 @@ export {
6878
7345
  getConversationParticipantIds,
6879
7346
  getEnvironmentConfig,
6880
7347
  getMessageType,
7348
+ getPagedResourceCooldownMs,
6881
7349
  getPlatformWorkerUrl,
6882
7350
  getThreadCounts,
6883
7351
  getUserColor,
@@ -6886,6 +7354,7 @@ export {
6886
7354
  handleSyncMessage,
6887
7355
  hasContent,
6888
7356
  integration,
7357
+ isAsyncResourceSlow,
6889
7358
  isDMConversation,
6890
7359
  isDarkColor,
6891
7360
  isImageFile,
@@ -6903,7 +7372,11 @@ export {
6903
7372
  signOut,
6904
7373
  toConnectionStatus,
6905
7374
  toUint8Array,
7375
+ useAsyncResource,
6906
7376
  useAuth,
7377
+ useAuthProfileReady,
7378
+ useAuthReady,
7379
+ useAuthStatus,
6907
7380
  useAuthUser,
6908
7381
  useCanvas,
6909
7382
  useChannelMembers,
@@ -6920,6 +7393,7 @@ export {
6920
7393
  useJobs,
6921
7394
  useMessages,
6922
7395
  useMutations,
7396
+ usePagedResource,
6923
7397
  usePlatform,
6924
7398
  usePlatformWS,
6925
7399
  usePosts,