@procore/saved-views 6.0.2 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +13 -2
  2. package/dist/legacy/adapters/hub-data-loader.d.mts +22 -0
  3. package/dist/legacy/adapters/hub-data-loader.d.ts +22 -0
  4. package/dist/legacy/adapters/hub-data-loader.js +273 -0
  5. package/dist/legacy/adapters/hub-data-loader.mjs +273 -0
  6. package/dist/legacy/chunk-6DZX6EAA.mjs +37 -0
  7. package/dist/legacy/chunk-QGM4M3NI.js +37 -0
  8. package/dist/legacy/index.d.mts +22 -3
  9. package/dist/legacy/index.d.ts +22 -3
  10. package/dist/legacy/index.js +755 -487
  11. package/dist/legacy/index.mjs +493 -268
  12. package/dist/legacy/transport/default.d.mts +15 -0
  13. package/dist/legacy/transport/default.d.ts +15 -0
  14. package/dist/legacy/transport/default.js +104 -0
  15. package/dist/legacy/transport/default.mjs +104 -0
  16. package/dist/legacy/types-BWhJ-on3.d.mts +109 -0
  17. package/dist/legacy/types-BWhJ-on3.d.ts +109 -0
  18. package/dist/modern/adapters/hub-data-loader.d.mts +22 -0
  19. package/dist/modern/adapters/hub-data-loader.d.ts +22 -0
  20. package/dist/modern/adapters/hub-data-loader.js +270 -0
  21. package/dist/modern/adapters/hub-data-loader.mjs +270 -0
  22. package/dist/modern/chunk-6DZX6EAA.mjs +37 -0
  23. package/dist/modern/chunk-QGM4M3NI.js +37 -0
  24. package/dist/modern/index.d.mts +22 -3
  25. package/dist/modern/index.d.ts +22 -3
  26. package/dist/modern/index.js +807 -540
  27. package/dist/modern/index.mjs +492 -268
  28. package/dist/modern/transport/default.d.mts +15 -0
  29. package/dist/modern/transport/default.d.ts +15 -0
  30. package/dist/modern/transport/default.js +104 -0
  31. package/dist/modern/transport/default.mjs +104 -0
  32. package/dist/modern/types-BWhJ-on3.d.mts +109 -0
  33. package/dist/modern/types-BWhJ-on3.d.ts +109 -0
  34. package/package.json +35 -2
package/README.md CHANGED
@@ -134,7 +134,15 @@ const MyDataTableView = () => {
134
134
  const savedViewsWrapperRef = useRef<IDataTableSavedViewsRef>(null);
135
135
 
136
136
  // Panel visibility control
137
- const { SavedViewsButton, isOpen: isPanelOpen } = useSavedViewsPanel('your_domain', 'your_table');
137
+ // `SavedViewsProvider` is required if you want the `SavedViewsButton` label
138
+ // to display the currently active view name (e.g. "Views: My View"). Wrap
139
+ // the subtree that contains both the button and the `<DataTableSavedViews>`
140
+ // / `<SavedViews>` component below.
141
+ const {
142
+ SavedViewsButton,
143
+ SavedViewsProvider,
144
+ isOpen: isPanelOpen,
145
+ } = useSavedViewsPanel('your_domain', 'your_table');
138
146
  ```
139
147
 
140
148
  **Key Points**:
@@ -181,6 +189,7 @@ const defaultViewConfig = useMemo(
181
189
 
182
190
  ```tsx
183
191
  return (
192
+ <SavedViewsProvider>
184
193
  <div className="table-with-saved-views">
185
194
  <ServerSideDataTable
186
195
  columnDefinitions={columnDefinitions}
@@ -227,7 +236,7 @@ const defaultViewConfig = useMemo(
227
236
  {/* Top Controls */}
228
237
  <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '12px' }}>
229
238
  <div style={{ display: 'flex', gap: '8px' }}>
230
- <SavedViewsButton /> {/* Toggle saved views panel */}
239
+ <SavedViewsButton /> {/* Toggle saved views panel; shows active view name when wrapped in <SavedViewsProvider> */}
231
240
  <ServerSideDataTable.Search />
232
241
  <ServerSideDataTable.FiltersPanelButton />
233
242
  </div>
@@ -253,6 +262,7 @@ const defaultViewConfig = useMemo(
253
262
  </div>
254
263
  </ServerSideDataTable>
255
264
  </div>
265
+ </SavedViewsProvider>
256
266
  );
257
267
  };
258
268
  ```
@@ -263,6 +273,7 @@ const defaultViewConfig = useMemo(
263
273
  2. **API Sharing**: `tableApi={tableApi}` gives saved views control over table state
264
274
  3. **Config Sync**: `onTableConfigChange={handleTableConfigChange}` keeps everything in sync
265
275
  4. **Layout**: Saved views typically go in a left sidebar with fixed width
276
+ 5. **Active view label**: Wrapping the subtree in `<SavedViewsProvider>` lets the toggle button display the currently active view name (e.g. "Views: All RFIs"). The provider is a no-op when omitted, so existing integrations continue to render the plain "Views" label.
266
277
 
267
278
  ---
268
279
 
@@ -0,0 +1,22 @@
1
+ import { SystemEvents } from '@procore/web-sdk-events';
2
+ import { S as SavedViewsTransport } from '../types-BWhJ-on3.mjs';
3
+ export { a as SavedViewsCacheControl, b as SavedViewsHttpRequest, c as SavedViewsMutationArgs, d as SavedViewsMutationResult, e as SavedViewsQueryArgs, f as SavedViewsQueryResult, g as SavedViewsUrlAdapter } from '../types-BWhJ-on3.mjs';
4
+ import 'react';
5
+
6
+ interface CreateHubDataLoaderTransportOptions {
7
+ /**
8
+ * Stable identifier of the Hub Card consuming saved-views. Forwarded to
9
+ * `useHubDataLoader(hubCardId, systemEvents)`. Use the same `HUB_CARD_ID`
10
+ * the card already uses elsewhere (e.g. for `system:request` events).
11
+ */
12
+ hubCardId: string;
13
+ /**
14
+ * The card's `SystemEvents` instance, initialized against the card's mount
15
+ * node. The Hub Card platform requires this to be scoped to the card, not
16
+ * `window`, so multiple cards on the same page don't cross-talk.
17
+ */
18
+ systemEvents: SystemEvents;
19
+ }
20
+ declare const createHubDataLoaderTransport: (options: CreateHubDataLoaderTransportOptions) => SavedViewsTransport;
21
+
22
+ export { type CreateHubDataLoaderTransportOptions, SavedViewsTransport, createHubDataLoaderTransport };
@@ -0,0 +1,22 @@
1
+ import { SystemEvents } from '@procore/web-sdk-events';
2
+ import { S as SavedViewsTransport } from '../types-BWhJ-on3.js';
3
+ export { a as SavedViewsCacheControl, b as SavedViewsHttpRequest, c as SavedViewsMutationArgs, d as SavedViewsMutationResult, e as SavedViewsQueryArgs, f as SavedViewsQueryResult, g as SavedViewsUrlAdapter } from '../types-BWhJ-on3.js';
4
+ import 'react';
5
+
6
+ interface CreateHubDataLoaderTransportOptions {
7
+ /**
8
+ * Stable identifier of the Hub Card consuming saved-views. Forwarded to
9
+ * `useHubDataLoader(hubCardId, systemEvents)`. Use the same `HUB_CARD_ID`
10
+ * the card already uses elsewhere (e.g. for `system:request` events).
11
+ */
12
+ hubCardId: string;
13
+ /**
14
+ * The card's `SystemEvents` instance, initialized against the card's mount
15
+ * node. The Hub Card platform requires this to be scoped to the card, not
16
+ * `window`, so multiple cards on the same page don't cross-talk.
17
+ */
18
+ systemEvents: SystemEvents;
19
+ }
20
+ declare const createHubDataLoaderTransport: (options: CreateHubDataLoaderTransportOptions) => SavedViewsTransport;
21
+
22
+ export { type CreateHubDataLoaderTransportOptions, SavedViewsTransport, createHubDataLoaderTransport };
@@ -0,0 +1,273 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }require('../chunk-QGM4M3NI.js');
2
+
3
+ // src/transport/hub-data-loader.tsx
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ var _react = require('react'); var _react2 = _interopRequireDefault(_react);
14
+
15
+
16
+ var _websdkhubdataloader = require('@procore/web-sdk-hub-data-loader');
17
+ var HubDataLoaderCache = class {
18
+ constructor() {
19
+ this.entries = /* @__PURE__ */ new Map();
20
+ }
21
+ getOrCreate(key) {
22
+ let entry = this.entries.get(key);
23
+ if (!entry) {
24
+ entry = { data: void 0, listeners: /* @__PURE__ */ new Set() };
25
+ this.entries.set(key, entry);
26
+ }
27
+ return entry;
28
+ }
29
+ subscribe(key, listener) {
30
+ const entry = this.getOrCreate(key);
31
+ entry.listeners.add(listener);
32
+ return () => {
33
+ entry.listeners.delete(listener);
34
+ };
35
+ }
36
+ get(key) {
37
+ var _a;
38
+ return (_a = this.entries.get(key)) == null ? void 0 : _a.data;
39
+ }
40
+ set(key, data) {
41
+ const entry = this.getOrCreate(key);
42
+ entry.data = data;
43
+ entry.listeners.forEach((listener) => listener());
44
+ }
45
+ invalidate(key) {
46
+ const entry = this.entries.get(key);
47
+ if (!entry) return;
48
+ entry.data = void 0;
49
+ entry.listeners.forEach((listener) => listener());
50
+ }
51
+ };
52
+ var stringifyQueryKey = (queryKey) => JSON.stringify(queryKey);
53
+ var HubDataLoaderCacheContext = _react.createContext.call(void 0, void 0);
54
+ var useHubDataLoaderCache = () => {
55
+ const ctx = _react.useContext.call(void 0, HubDataLoaderCacheContext);
56
+ if (!ctx) {
57
+ throw new Error(
58
+ "HubDataLoaderCacheProvider is missing. This indicates the saved-views transport was not constructed via createHubDataLoaderTransport()."
59
+ );
60
+ }
61
+ return ctx.cache;
62
+ };
63
+ var METHOD_TO_OPERATION_TYPE = {
64
+ GET: "GET",
65
+ POST: "POST",
66
+ PUT: "PUT",
67
+ DELETE: "DELETE"
68
+ };
69
+ var splitUrl = (url) => {
70
+ const queryIndex = url.indexOf("?");
71
+ if (queryIndex === -1) {
72
+ return { operationName: url, queryParams: {} };
73
+ }
74
+ const operationName = url.slice(0, queryIndex);
75
+ const search = new URLSearchParams(url.slice(queryIndex + 1));
76
+ const queryParams = {};
77
+ search.forEach((value, key) => {
78
+ queryParams[key] = value;
79
+ });
80
+ return { operationName, queryParams };
81
+ };
82
+ var parseBody = (body) => {
83
+ if (body === void 0 || body === null) return void 0;
84
+ if (typeof body === "string") {
85
+ try {
86
+ return JSON.parse(body);
87
+ } catch (e) {
88
+ return void 0;
89
+ }
90
+ }
91
+ if (typeof body === "object") {
92
+ return body;
93
+ }
94
+ return void 0;
95
+ };
96
+ var createHubDataLoaderTransport = (options) => {
97
+ const { hubCardId, systemEvents } = options;
98
+ const CacheProvider = ({ children }) => {
99
+ const cacheRef = _react.useRef.call(void 0, );
100
+ if (!cacheRef.current) {
101
+ cacheRef.current = new HubDataLoaderCache();
102
+ }
103
+ const value = _react.useMemo.call(void 0,
104
+ () => ({ cache: cacheRef.current }),
105
+ []
106
+ );
107
+ return /* @__PURE__ */ _react2.default.createElement(HubDataLoaderCacheContext.Provider, { value }, children);
108
+ };
109
+ const useHttp = () => {
110
+ const { sendRequest } = _websdkhubdataloader.useHubDataLoader.call(void 0, hubCardId, systemEvents);
111
+ return _react.useCallback.call(void 0,
112
+ async (req) => {
113
+ const { operationName, queryParams } = splitUrl(req.url);
114
+ const params = {
115
+ operationName,
116
+ operationType: METHOD_TO_OPERATION_TYPE[req.method],
117
+ queryParams,
118
+ body: parseBody(req.body),
119
+ headers: req.headers,
120
+ // Read saved-views GETs fresh from the network. This transport keeps
121
+ // its own local subscription cache (HubDataLoaderCache) and gates
122
+ // refetches on a local-cache miss, so it doesn't benefit from the
123
+ // host's stale-while-revalidate cache. Without preferFresh the host
124
+ // serves the GET via `ensureQueryData`, which returns the cached
125
+ // (pre-mutation) list — so a freshly created/renamed/deleted view
126
+ // wouldn't appear until the host cache expired. preferFresh routes
127
+ // the read through `fetchQuery({ staleTime: 0 })`, guaranteeing the
128
+ // post-mutation refetch reflects the change immediately.
129
+ preferFresh: req.method === "GET"
130
+ };
131
+ const response = await sendRequest(params);
132
+ if (response.error) {
133
+ throw response.error;
134
+ }
135
+ return response.responseData;
136
+ },
137
+ [sendRequest]
138
+ );
139
+ };
140
+ const useQueryAdapter = (args) => {
141
+ const cache = useHubDataLoaderCache();
142
+ const key = _react.useMemo.call(void 0,
143
+ () => stringifyQueryKey(args.queryKey),
144
+ [args.queryKey]
145
+ );
146
+ const queryFnRef = _react.useRef.call(void 0, args.queryFn);
147
+ queryFnRef.current = args.queryFn;
148
+ const subscribe = _react.useCallback.call(void 0,
149
+ (listener) => cache.subscribe(key, listener),
150
+ [cache, key]
151
+ );
152
+ const getSnapshot = _react.useCallback.call(void 0,
153
+ () => cache.get(key),
154
+ [cache, key]
155
+ );
156
+ const data = _react.useSyncExternalStore.call(void 0, subscribe, getSnapshot, getSnapshot);
157
+ const [isLoading, setIsLoading] = _react.useState.call(void 0,
158
+ args.enabled !== false && data === void 0
159
+ );
160
+ const [error, setError] = _react.useState.call(void 0, void 0);
161
+ const fetchInFlight = _react.useRef.call(void 0, false);
162
+ _react.useEffect.call(void 0, () => {
163
+ if (args.enabled === false) {
164
+ setIsLoading(false);
165
+ return;
166
+ }
167
+ if (data !== void 0) {
168
+ setIsLoading(false);
169
+ return;
170
+ }
171
+ if (fetchInFlight.current) return;
172
+ let abandoned = false;
173
+ fetchInFlight.current = true;
174
+ setIsLoading(true);
175
+ setError(void 0);
176
+ queryFnRef.current().then((result) => {
177
+ if (!abandoned) {
178
+ cache.set(key, result);
179
+ setError(void 0);
180
+ }
181
+ }).catch((err) => {
182
+ if (!abandoned) setError(err);
183
+ }).finally(() => {
184
+ if (!abandoned) {
185
+ fetchInFlight.current = false;
186
+ setIsLoading(false);
187
+ }
188
+ });
189
+ return () => {
190
+ abandoned = true;
191
+ fetchInFlight.current = false;
192
+ };
193
+ }, [cache, key, args.enabled, data]);
194
+ return {
195
+ data,
196
+ isLoading,
197
+ isError: error !== void 0,
198
+ error
199
+ };
200
+ };
201
+ const useMutationAdapter = (args) => {
202
+ const [isPending, setIsPending] = _react.useState.call(void 0, false);
203
+ const [error, setError] = _react.useState.call(void 0, null);
204
+ const mutationFnRef = _react.useRef.call(void 0, args.mutationFn);
205
+ const onSuccessRef = _react.useRef.call(void 0, args.onSuccess);
206
+ const onErrorRef = _react.useRef.call(void 0, args.onError);
207
+ mutationFnRef.current = args.mutationFn;
208
+ onSuccessRef.current = args.onSuccess;
209
+ onErrorRef.current = args.onError;
210
+ const mutate = _react.useCallback.call(void 0,
211
+ (variables, callOptions) => {
212
+ setIsPending(true);
213
+ setError(null);
214
+ mutationFnRef.current(variables).then((result) => {
215
+ var _a, _b;
216
+ (_a = onSuccessRef.current) == null ? void 0 : _a.call(onSuccessRef, result, variables);
217
+ (_b = callOptions == null ? void 0 : callOptions.onSuccess) == null ? void 0 : _b.call(callOptions, result, variables);
218
+ }).catch((err) => {
219
+ var _a, _b;
220
+ setError(err);
221
+ (_a = onErrorRef.current) == null ? void 0 : _a.call(onErrorRef, err, variables);
222
+ (_b = callOptions == null ? void 0 : callOptions.onError) == null ? void 0 : _b.call(callOptions, err, variables);
223
+ }).finally(() => {
224
+ setIsPending(false);
225
+ });
226
+ },
227
+ []
228
+ );
229
+ const reset = _react.useCallback.call(void 0, () => {
230
+ setError(null);
231
+ setIsPending(false);
232
+ }, []);
233
+ return { mutate, isPending, error, reset };
234
+ };
235
+ const useCacheControl = () => {
236
+ const cache = useHubDataLoaderCache();
237
+ return {
238
+ invalidate: (queryKey) => {
239
+ cache.invalidate(stringifyQueryKey(queryKey));
240
+ },
241
+ setData: (queryKey, updater) => {
242
+ const key = stringifyQueryKey(queryKey);
243
+ const existing = cache.get(key);
244
+ const next = updater(existing);
245
+ cache.set(key, next);
246
+ },
247
+ getData: (queryKey) => cache.get(stringifyQueryKey(queryKey))
248
+ };
249
+ };
250
+ const useUrlAdapter = () => ({
251
+ // Hub Cards cannot read or write the host's URL. The host owns routing.
252
+ // The saved-views package falls back to localStorage-only persistence
253
+ // when these return null / no-op.
254
+ getViewToken: () => null,
255
+ setViewToken: () => {
256
+ }
257
+ });
258
+ return {
259
+ // Hub Cards cannot own the host URL, so the `?saved-view=<token>` share link
260
+ // cannot be read back on load. Hide the copy-link affordance in this context
261
+ // (see routing-in-hub-cards.md). The rest of saved views works unchanged.
262
+ supportsUrlSharing: false,
263
+ CacheProvider,
264
+ useHttp,
265
+ useQueryAdapter,
266
+ useMutationAdapter,
267
+ useCacheControl,
268
+ useUrlAdapter
269
+ };
270
+ };
271
+
272
+
273
+ exports.createHubDataLoaderTransport = createHubDataLoaderTransport;
@@ -0,0 +1,273 @@
1
+ import "../chunk-6DZX6EAA.mjs";
2
+
3
+ // src/transport/hub-data-loader.tsx
4
+ import React, {
5
+ createContext,
6
+ useCallback,
7
+ useContext,
8
+ useEffect,
9
+ useMemo,
10
+ useRef,
11
+ useState,
12
+ useSyncExternalStore
13
+ } from "react";
14
+ import {
15
+ useHubDataLoader
16
+ } from "@procore/web-sdk-hub-data-loader";
17
+ var HubDataLoaderCache = class {
18
+ constructor() {
19
+ this.entries = /* @__PURE__ */ new Map();
20
+ }
21
+ getOrCreate(key) {
22
+ let entry = this.entries.get(key);
23
+ if (!entry) {
24
+ entry = { data: void 0, listeners: /* @__PURE__ */ new Set() };
25
+ this.entries.set(key, entry);
26
+ }
27
+ return entry;
28
+ }
29
+ subscribe(key, listener) {
30
+ const entry = this.getOrCreate(key);
31
+ entry.listeners.add(listener);
32
+ return () => {
33
+ entry.listeners.delete(listener);
34
+ };
35
+ }
36
+ get(key) {
37
+ var _a;
38
+ return (_a = this.entries.get(key)) == null ? void 0 : _a.data;
39
+ }
40
+ set(key, data) {
41
+ const entry = this.getOrCreate(key);
42
+ entry.data = data;
43
+ entry.listeners.forEach((listener) => listener());
44
+ }
45
+ invalidate(key) {
46
+ const entry = this.entries.get(key);
47
+ if (!entry) return;
48
+ entry.data = void 0;
49
+ entry.listeners.forEach((listener) => listener());
50
+ }
51
+ };
52
+ var stringifyQueryKey = (queryKey) => JSON.stringify(queryKey);
53
+ var HubDataLoaderCacheContext = createContext(void 0);
54
+ var useHubDataLoaderCache = () => {
55
+ const ctx = useContext(HubDataLoaderCacheContext);
56
+ if (!ctx) {
57
+ throw new Error(
58
+ "HubDataLoaderCacheProvider is missing. This indicates the saved-views transport was not constructed via createHubDataLoaderTransport()."
59
+ );
60
+ }
61
+ return ctx.cache;
62
+ };
63
+ var METHOD_TO_OPERATION_TYPE = {
64
+ GET: "GET",
65
+ POST: "POST",
66
+ PUT: "PUT",
67
+ DELETE: "DELETE"
68
+ };
69
+ var splitUrl = (url) => {
70
+ const queryIndex = url.indexOf("?");
71
+ if (queryIndex === -1) {
72
+ return { operationName: url, queryParams: {} };
73
+ }
74
+ const operationName = url.slice(0, queryIndex);
75
+ const search = new URLSearchParams(url.slice(queryIndex + 1));
76
+ const queryParams = {};
77
+ search.forEach((value, key) => {
78
+ queryParams[key] = value;
79
+ });
80
+ return { operationName, queryParams };
81
+ };
82
+ var parseBody = (body) => {
83
+ if (body === void 0 || body === null) return void 0;
84
+ if (typeof body === "string") {
85
+ try {
86
+ return JSON.parse(body);
87
+ } catch {
88
+ return void 0;
89
+ }
90
+ }
91
+ if (typeof body === "object") {
92
+ return body;
93
+ }
94
+ return void 0;
95
+ };
96
+ var createHubDataLoaderTransport = (options) => {
97
+ const { hubCardId, systemEvents } = options;
98
+ const CacheProvider = ({ children }) => {
99
+ const cacheRef = useRef();
100
+ if (!cacheRef.current) {
101
+ cacheRef.current = new HubDataLoaderCache();
102
+ }
103
+ const value = useMemo(
104
+ () => ({ cache: cacheRef.current }),
105
+ []
106
+ );
107
+ return /* @__PURE__ */ React.createElement(HubDataLoaderCacheContext.Provider, { value }, children);
108
+ };
109
+ const useHttp = () => {
110
+ const { sendRequest } = useHubDataLoader(hubCardId, systemEvents);
111
+ return useCallback(
112
+ async (req) => {
113
+ const { operationName, queryParams } = splitUrl(req.url);
114
+ const params = {
115
+ operationName,
116
+ operationType: METHOD_TO_OPERATION_TYPE[req.method],
117
+ queryParams,
118
+ body: parseBody(req.body),
119
+ headers: req.headers,
120
+ // Read saved-views GETs fresh from the network. This transport keeps
121
+ // its own local subscription cache (HubDataLoaderCache) and gates
122
+ // refetches on a local-cache miss, so it doesn't benefit from the
123
+ // host's stale-while-revalidate cache. Without preferFresh the host
124
+ // serves the GET via `ensureQueryData`, which returns the cached
125
+ // (pre-mutation) list — so a freshly created/renamed/deleted view
126
+ // wouldn't appear until the host cache expired. preferFresh routes
127
+ // the read through `fetchQuery({ staleTime: 0 })`, guaranteeing the
128
+ // post-mutation refetch reflects the change immediately.
129
+ preferFresh: req.method === "GET"
130
+ };
131
+ const response = await sendRequest(params);
132
+ if (response.error) {
133
+ throw response.error;
134
+ }
135
+ return response.responseData;
136
+ },
137
+ [sendRequest]
138
+ );
139
+ };
140
+ const useQueryAdapter = (args) => {
141
+ const cache = useHubDataLoaderCache();
142
+ const key = useMemo(
143
+ () => stringifyQueryKey(args.queryKey),
144
+ [args.queryKey]
145
+ );
146
+ const queryFnRef = useRef(args.queryFn);
147
+ queryFnRef.current = args.queryFn;
148
+ const subscribe = useCallback(
149
+ (listener) => cache.subscribe(key, listener),
150
+ [cache, key]
151
+ );
152
+ const getSnapshot = useCallback(
153
+ () => cache.get(key),
154
+ [cache, key]
155
+ );
156
+ const data = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
157
+ const [isLoading, setIsLoading] = useState(
158
+ args.enabled !== false && data === void 0
159
+ );
160
+ const [error, setError] = useState(void 0);
161
+ const fetchInFlight = useRef(false);
162
+ useEffect(() => {
163
+ if (args.enabled === false) {
164
+ setIsLoading(false);
165
+ return;
166
+ }
167
+ if (data !== void 0) {
168
+ setIsLoading(false);
169
+ return;
170
+ }
171
+ if (fetchInFlight.current) return;
172
+ let abandoned = false;
173
+ fetchInFlight.current = true;
174
+ setIsLoading(true);
175
+ setError(void 0);
176
+ queryFnRef.current().then((result) => {
177
+ if (!abandoned) {
178
+ cache.set(key, result);
179
+ setError(void 0);
180
+ }
181
+ }).catch((err) => {
182
+ if (!abandoned) setError(err);
183
+ }).finally(() => {
184
+ if (!abandoned) {
185
+ fetchInFlight.current = false;
186
+ setIsLoading(false);
187
+ }
188
+ });
189
+ return () => {
190
+ abandoned = true;
191
+ fetchInFlight.current = false;
192
+ };
193
+ }, [cache, key, args.enabled, data]);
194
+ return {
195
+ data,
196
+ isLoading,
197
+ isError: error !== void 0,
198
+ error
199
+ };
200
+ };
201
+ const useMutationAdapter = (args) => {
202
+ const [isPending, setIsPending] = useState(false);
203
+ const [error, setError] = useState(null);
204
+ const mutationFnRef = useRef(args.mutationFn);
205
+ const onSuccessRef = useRef(args.onSuccess);
206
+ const onErrorRef = useRef(args.onError);
207
+ mutationFnRef.current = args.mutationFn;
208
+ onSuccessRef.current = args.onSuccess;
209
+ onErrorRef.current = args.onError;
210
+ const mutate = useCallback(
211
+ (variables, callOptions) => {
212
+ setIsPending(true);
213
+ setError(null);
214
+ mutationFnRef.current(variables).then((result) => {
215
+ var _a, _b;
216
+ (_a = onSuccessRef.current) == null ? void 0 : _a.call(onSuccessRef, result, variables);
217
+ (_b = callOptions == null ? void 0 : callOptions.onSuccess) == null ? void 0 : _b.call(callOptions, result, variables);
218
+ }).catch((err) => {
219
+ var _a, _b;
220
+ setError(err);
221
+ (_a = onErrorRef.current) == null ? void 0 : _a.call(onErrorRef, err, variables);
222
+ (_b = callOptions == null ? void 0 : callOptions.onError) == null ? void 0 : _b.call(callOptions, err, variables);
223
+ }).finally(() => {
224
+ setIsPending(false);
225
+ });
226
+ },
227
+ []
228
+ );
229
+ const reset = useCallback(() => {
230
+ setError(null);
231
+ setIsPending(false);
232
+ }, []);
233
+ return { mutate, isPending, error, reset };
234
+ };
235
+ const useCacheControl = () => {
236
+ const cache = useHubDataLoaderCache();
237
+ return {
238
+ invalidate: (queryKey) => {
239
+ cache.invalidate(stringifyQueryKey(queryKey));
240
+ },
241
+ setData: (queryKey, updater) => {
242
+ const key = stringifyQueryKey(queryKey);
243
+ const existing = cache.get(key);
244
+ const next = updater(existing);
245
+ cache.set(key, next);
246
+ },
247
+ getData: (queryKey) => cache.get(stringifyQueryKey(queryKey))
248
+ };
249
+ };
250
+ const useUrlAdapter = () => ({
251
+ // Hub Cards cannot read or write the host's URL. The host owns routing.
252
+ // The saved-views package falls back to localStorage-only persistence
253
+ // when these return null / no-op.
254
+ getViewToken: () => null,
255
+ setViewToken: () => {
256
+ }
257
+ });
258
+ return {
259
+ // Hub Cards cannot own the host URL, so the `?saved-view=<token>` share link
260
+ // cannot be read back on load. Hide the copy-link affordance in this context
261
+ // (see routing-in-hub-cards.md). The rest of saved views works unchanged.
262
+ supportsUrlSharing: false,
263
+ CacheProvider,
264
+ useHttp,
265
+ useQueryAdapter,
266
+ useMutationAdapter,
267
+ useCacheControl,
268
+ useUrlAdapter
269
+ };
270
+ };
271
+ export {
272
+ createHubDataLoaderTransport
273
+ };
@@ -0,0 +1,37 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ export {
34
+ __require,
35
+ __commonJS,
36
+ __toESM
37
+ };