@fusedio/widget-sdk 0.1.0 → 0.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.
@@ -1,3 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDuckDbSqlQueryPreprocessing = useDuckDbSqlQueryPreprocessing;
4
+ exports.useDuckDbSqlQuery = useDuckDbSqlQuery;
5
+ exports.useVfsRegistration = useVfsRegistration;
1
6
  /**
2
7
  * DuckDB SQL execution against UDF Parquet outputs.
3
8
  *
@@ -13,13 +18,14 @@
13
18
  * the host side via the bridge. Both hooks work identically in the
14
19
  * workbench, the catalog-template test harness, or any other host.
15
20
  */
16
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
17
- import { useFusedWidgetBridge } from "../bridge";
18
- import { useFormParams } from "../form";
19
- import { useJsonUiLog } from "./use-json-ui-log";
20
- import { useJsonUiEdgeAnimation } from "./use-json-ui-edge-animation";
21
- import { useCanvasParams } from "./use-canvas-params";
22
- import { computePlaceholderKey, extractSignableUrls, extractSqlParams, parseSqlUdfPlaceholders, resolveOverrideValue, rewriteSignedUrls, substituteSqlParams, getDollarRefName, } from "../utils/sql-placeholders";
21
+ const react_1 = require("react");
22
+ const bridge_1 = require("../bridge");
23
+ const form_1 = require("../form");
24
+ const use_json_ui_log_1 = require("./use-json-ui-log");
25
+ const use_json_ui_edge_animation_1 = require("./use-json-ui-edge-animation");
26
+ const use_canvas_params_1 = require("./use-canvas-params");
27
+ const sql_source_overrides_1 = require("./sql-source-overrides");
28
+ const sql_placeholders_1 = require("../utils/sql-placeholders");
23
29
  const DEFAULT_MAX_ROWS = 500;
24
30
  const EMPTY_ROWS = Object.freeze([]);
25
31
  const EMPTY_COLUMNS = Object.freeze([]);
@@ -63,53 +69,67 @@ function buildProcessedSql(sql, resolved, fileNameMap, sourceOverrides, sqlParam
63
69
  processedSql.slice(raw.end);
64
70
  }
65
71
  processedSql = appendLimitIfMissing(processedSql, maxRows);
66
- return substituteSqlParams(processedSql, sqlParamValues);
72
+ return (0, sql_placeholders_1.substituteSqlParams)(processedSql, sqlParamValues);
67
73
  }
68
74
  /**
69
75
  * Preprocess SQL: resolve placeholders, register UDFs via the bridge,
70
76
  * substitute params, sign URLs, append LIMIT. Returns the prepared SQL.
71
77
  */
72
- export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides, }) {
73
- const bridge = useFusedWidgetBridge();
74
- const { startLoading: startEdgeLoading, stopLoading: stopEdgeLoading } = useJsonUiEdgeAnimation();
75
- const { log } = useJsonUiLog();
76
- const [processedSql, setProcessedSql] = useState("");
77
- const [loading, setLoading] = useState(false);
78
- const [error, setError] = useState(null);
79
- const [fetchKey, setFetchKey] = useState(0);
80
- const sourcePlaceholders = useMemo(() => {
78
+ function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides: explicitSourceOverrides, }) {
79
+ const bridge = (0, bridge_1.useFusedWidgetBridge)();
80
+ // Auto-detect host-provided source overrides (e.g. the workbench's
81
+ // sql-runner exposes in-memory relations to descendants) and merge them with
82
+ // any explicit option. Explicit overrides win on key collision. Component
83
+ // authors never thread this manually.
84
+ const contextSourceOverrides = (0, sql_source_overrides_1.useSqlSourceOverrides)();
85
+ const sourceOverrides = (0, react_1.useMemo)(() => {
86
+ const hasContext = Object.keys(contextSourceOverrides).length > 0;
87
+ if (!explicitSourceOverrides) {
88
+ return hasContext ? contextSourceOverrides : undefined;
89
+ }
90
+ if (!hasContext)
91
+ return explicitSourceOverrides;
92
+ return { ...contextSourceOverrides, ...explicitSourceOverrides };
93
+ }, [contextSourceOverrides, explicitSourceOverrides]);
94
+ const { startLoading: startEdgeLoading, stopLoading: stopEdgeLoading } = (0, use_json_ui_edge_animation_1.useJsonUiEdgeAnimation)();
95
+ const { log } = (0, use_json_ui_log_1.useJsonUiLog)();
96
+ const [processedSql, setProcessedSql] = (0, react_1.useState)("");
97
+ const [loading, setLoading] = (0, react_1.useState)(false);
98
+ const [error, setError] = (0, react_1.useState)(null);
99
+ const [fetchKey, setFetchKey] = (0, react_1.useState)(0);
100
+ const sourcePlaceholders = (0, react_1.useMemo)(() => {
81
101
  if (!sql)
82
102
  return [];
83
- return parseSqlUdfPlaceholders(sql);
103
+ return (0, sql_placeholders_1.parseSqlUdfPlaceholders)(sql);
84
104
  }, [sql]);
85
105
  // Skip placeholders that have a sourceOverride active (workbench-only path).
86
- const placeholdersAfterOverride = useMemo(() => {
106
+ const placeholdersAfterOverride = (0, react_1.useMemo)(() => {
87
107
  if (!sourceOverrides)
88
108
  return sourcePlaceholders;
89
109
  return sourcePlaceholders.filter((p) => p.overrides !== null || !sourceOverrides[p.name]);
90
110
  }, [sourcePlaceholders, sourceOverrides]);
91
111
  // Override values may reference $params — collect those names so we can
92
112
  // subscribe to the same canvas/form param map the SQL body uses.
93
- const overrideParamNames = useMemo(() => {
113
+ const overrideParamNames = (0, react_1.useMemo)(() => {
94
114
  const set = new Set();
95
115
  for (const p of placeholdersAfterOverride) {
96
116
  if (!p.overrides)
97
117
  continue;
98
118
  for (const v of Object.values(p.overrides)) {
99
- const name = getDollarRefName(v);
119
+ const name = (0, sql_placeholders_1.getDollarRefName)(v);
100
120
  if (name)
101
121
  set.add(name);
102
122
  }
103
123
  }
104
124
  return Array.from(set);
105
125
  }, [placeholdersAfterOverride]);
106
- const sqlParamNames = useMemo(() => {
126
+ const sqlParamNames = (0, react_1.useMemo)(() => {
107
127
  if (!sql)
108
128
  return [];
109
- return extractSqlParams(sql);
129
+ return (0, sql_placeholders_1.extractSqlParams)(sql);
110
130
  }, [sql]);
111
131
  // Subscribe to canvas + form params for both the SQL body and override refs.
112
- const allParamNames = useMemo(() => {
132
+ const allParamNames = (0, react_1.useMemo)(() => {
113
133
  const seen = new Set();
114
134
  const out = [];
115
135
  for (const n of sqlParamNames) {
@@ -126,10 +146,10 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
126
146
  }
127
147
  return out;
128
148
  }, [sqlParamNames, overrideParamNames]);
129
- const canvasParamValues = useCanvasParams(allParamNames);
130
- const { inForm, values: formParamValues } = useFormParams(allParamNames);
131
- const sqlParamValues = useMemo(() => inForm ? { ...canvasParamValues, ...formParamValues } : canvasParamValues, [inForm, canvasParamValues, formParamValues]);
132
- const resolvedPlaceholders = useMemo(() => {
149
+ const canvasParamValues = (0, use_canvas_params_1.useCanvasParams)(allParamNames);
150
+ const { inForm, values: formParamValues } = (0, form_1.useFormParams)(allParamNames);
151
+ const sqlParamValues = (0, react_1.useMemo)(() => inForm ? { ...canvasParamValues, ...formParamValues } : canvasParamValues, [inForm, canvasParamValues, formParamValues]);
152
+ const resolvedPlaceholders = (0, react_1.useMemo)(() => {
133
153
  return placeholdersAfterOverride.map((p) => {
134
154
  if (!p.overrides) {
135
155
  return {
@@ -142,21 +162,21 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
142
162
  const resolvedOverrides = {};
143
163
  let unresolved = false;
144
164
  for (const [paramKey, rawValue] of Object.entries(p.overrides)) {
145
- const r = resolveOverrideValue(rawValue, sqlParamValues);
165
+ const r = (0, sql_placeholders_1.resolveOverrideValue)(rawValue, sqlParamValues);
146
166
  if (r.unresolved)
147
167
  unresolved = true;
148
168
  resolvedOverrides[paramKey] = r.value;
149
169
  }
150
170
  return {
151
171
  raw: p,
152
- key: computePlaceholderKey(p.name, resolvedOverrides),
172
+ key: (0, sql_placeholders_1.computePlaceholderKey)(p.name, resolvedOverrides),
153
173
  resolvedOverrides,
154
174
  unresolved,
155
175
  };
156
176
  });
157
177
  }, [placeholdersAfterOverride, sqlParamValues]);
158
178
  // Deduplicate refs we need to pass to the bridge for VFS registration.
159
- const vfsRefs = useMemo(() => {
179
+ const vfsRefs = (0, react_1.useMemo)(() => {
160
180
  const seen = new Set();
161
181
  const out = [];
162
182
  for (const rp of resolvedPlaceholders) {
@@ -175,7 +195,7 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
175
195
  }, [resolvedPlaceholders]);
176
196
  // Stable key for the refs list — avoids re-running the resolve effect when
177
197
  // the underlying refs are structurally identical.
178
- const refsKey = useMemo(() => {
198
+ const refsKey = (0, react_1.useMemo)(() => {
179
199
  return vfsRefs
180
200
  .map((r) => `${r.key}|${r.name}|${r.overrides
181
201
  ? Object.entries(r.overrides)
@@ -185,12 +205,12 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
185
205
  : ""}`)
186
206
  .join("\n");
187
207
  }, [vfsRefs]);
188
- const refetch = useCallback(() => {
208
+ const refetch = (0, react_1.useCallback)(() => {
189
209
  setFetchKey((k) => k + 1);
190
210
  }, []);
191
211
  // Subscribe to UDF output changes for every referenced UDF — `resolveVfsFilenames`
192
212
  // doesn't auto-rerun when a UDF re-executes, so we trigger a refetch.
193
- useEffect(() => {
213
+ (0, react_1.useEffect)(() => {
194
214
  if (!enabled || vfsRefs.length === 0)
195
215
  return;
196
216
  const unsubs = vfsRefs.map((ref) => bridge.udfs.subscribeOutput(ref.name, () => {
@@ -201,14 +221,14 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
201
221
  };
202
222
  }, [bridge, enabled, vfsRefs]);
203
223
  // Edge animation mirrors loading.
204
- useEffect(() => {
224
+ (0, react_1.useEffect)(() => {
205
225
  if (loading)
206
226
  startEdgeLoading();
207
227
  else
208
228
  stopEdgeLoading();
209
229
  }, [loading, startEdgeLoading, stopEdgeLoading]);
210
230
  // Watch for sourceOverride errors / loading so the preprocessing reflects them.
211
- const sourceOverrideError = useMemo(() => {
231
+ const sourceOverrideError = (0, react_1.useMemo)(() => {
212
232
  if (!sourceOverrides)
213
233
  return null;
214
234
  for (const p of sourcePlaceholders) {
@@ -220,13 +240,13 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
220
240
  }
221
241
  return null;
222
242
  }, [sourcePlaceholders, sourceOverrides]);
223
- const sourceOverrideLoading = useMemo(() => {
243
+ const sourceOverrideLoading = (0, react_1.useMemo)(() => {
224
244
  if (!sourceOverrides)
225
245
  return false;
226
246
  return sourcePlaceholders.some((p) => p.overrides === null && sourceOverrides[p.name]?.loading);
227
247
  }, [sourcePlaceholders, sourceOverrides]);
228
248
  const hasUnresolvedOverride = resolvedPlaceholders.some((rp) => rp.unresolved);
229
- useEffect(() => {
249
+ (0, react_1.useEffect)(() => {
230
250
  if (!enabled || !sql) {
231
251
  setProcessedSql("");
232
252
  setLoading(false);
@@ -338,7 +358,7 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
338
358
  log(`SQL preprocessing failed: ${msg}`, "error");
339
359
  return;
340
360
  }
341
- const urls = extractSignableUrls(nextProcessedSql);
361
+ const urls = (0, sql_placeholders_1.extractSignableUrls)(nextProcessedSql);
342
362
  if (urls.length === 0) {
343
363
  if (cancelled)
344
364
  return;
@@ -356,7 +376,7 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
356
376
  urls.forEach((u, i) => {
357
377
  signedMap[u] = signed[i].signed;
358
378
  });
359
- const signedSql = rewriteSignedUrls(nextProcessedSql, signedMap);
379
+ const signedSql = (0, sql_placeholders_1.rewriteSignedUrls)(nextProcessedSql, signedMap);
360
380
  setProcessedSql(signedSql);
361
381
  setError(null);
362
382
  setLoading(false);
@@ -402,15 +422,15 @@ export function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows =
402
422
  * `useDuckDbSqlQueryPreprocessing` to prepare the SQL string, then runs
403
423
  * it via the bridge.
404
424
  */
405
- export function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides, }) {
406
- const bridge = useFusedWidgetBridge();
407
- const { startLoading: startEdgeLoading, stopLoading: stopEdgeLoading } = useJsonUiEdgeAnimation();
408
- const { log } = useJsonUiLog();
409
- const [rows, setRows] = useState(EMPTY_ROWS);
410
- const [columns, setColumns] = useState(EMPTY_COLUMNS);
411
- const [queryLoading, setQueryLoading] = useState(false);
412
- const [error, setError] = useState(null);
413
- const [fetchKey, setFetchKey] = useState(0);
425
+ function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides, }) {
426
+ const bridge = (0, bridge_1.useFusedWidgetBridge)();
427
+ const { startLoading: startEdgeLoading, stopLoading: stopEdgeLoading } = (0, use_json_ui_edge_animation_1.useJsonUiEdgeAnimation)();
428
+ const { log } = (0, use_json_ui_log_1.useJsonUiLog)();
429
+ const [rows, setRows] = (0, react_1.useState)(EMPTY_ROWS);
430
+ const [columns, setColumns] = (0, react_1.useState)(EMPTY_COLUMNS);
431
+ const [queryLoading, setQueryLoading] = (0, react_1.useState)(false);
432
+ const [error, setError] = (0, react_1.useState)(null);
433
+ const [fetchKey, setFetchKey] = (0, react_1.useState)(0);
414
434
  const { processedSql, loading: preprocessingLoading, error: preprocessingError, refetch: refetchPreprocessing, } = useDuckDbSqlQueryPreprocessing({
415
435
  sql,
416
436
  enabled,
@@ -419,7 +439,7 @@ export function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_R
419
439
  });
420
440
  // Bridges the single-frame gap between preprocessing completing and the
421
441
  // query effect starting — keeps `loading` true through that frame.
422
- const consumedSqlRef = useRef("");
442
+ const consumedSqlRef = (0, react_1.useRef)("");
423
443
  const awaitingExecution = enabled &&
424
444
  !!sql &&
425
445
  !!processedSql &&
@@ -427,18 +447,18 @@ export function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_R
427
447
  !preprocessingError &&
428
448
  processedSql !== consumedSqlRef.current;
429
449
  const loading = preprocessingLoading || queryLoading || awaitingExecution;
430
- useEffect(() => {
450
+ (0, react_1.useEffect)(() => {
431
451
  if (loading)
432
452
  startEdgeLoading();
433
453
  else
434
454
  stopEdgeLoading();
435
455
  }, [loading, startEdgeLoading, stopEdgeLoading]);
436
- const refetch = useCallback(() => {
456
+ const refetch = (0, react_1.useCallback)(() => {
437
457
  consumedSqlRef.current = "";
438
458
  refetchPreprocessing();
439
459
  setFetchKey((k) => k + 1);
440
460
  }, [refetchPreprocessing]);
441
- useEffect(() => {
461
+ (0, react_1.useEffect)(() => {
442
462
  if (!enabled || !sql) {
443
463
  consumedSqlRef.current = "";
444
464
  setRows(EMPTY_ROWS);
@@ -524,11 +544,11 @@ export function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_R
524
544
  * Resolve UDF names to VFS filenames, registering them in DuckDB if needed.
525
545
  * Exposed for advanced use cases (e.g. building your own query string).
526
546
  */
527
- export function useVfsRegistration(udfNames, enabled = true) {
528
- const bridge = useFusedWidgetBridge();
529
- const [state, setState] = useState({ filenames: new Map(), loading: false });
530
- const namesKey = useMemo(() => udfNames.slice().sort().join("|"), [udfNames]);
531
- useEffect(() => {
547
+ function useVfsRegistration(udfNames, enabled = true) {
548
+ const bridge = (0, bridge_1.useFusedWidgetBridge)();
549
+ const [state, setState] = (0, react_1.useState)({ filenames: new Map(), loading: false });
550
+ const namesKey = (0, react_1.useMemo)(() => udfNames.slice().sort().join("|"), [udfNames]);
551
+ (0, react_1.useEffect)(() => {
532
552
  if (!enabled || udfNames.length === 0) {
533
553
  setState({ filenames: new Map(), loading: false });
534
554
  return;
@@ -0,0 +1,18 @@
1
+ import type { UseFusedParamOptions, UseFusedParamReturn } from "../types";
2
+ /**
3
+ * Form-aware variant of {@link useFusedParam}.
4
+ *
5
+ * When the component is rendered inside a built-in Form, the field becomes
6
+ * local state (its value is NOT broadcast to the canvas) and its live value is
7
+ * mirrored into the form's subscription store, so sibling components (a
8
+ * dropdown's SQL options, a chart, a text binding, …) can react to it before
9
+ * the form is submitted. Outside a form it behaves exactly like
10
+ * `useFusedParam` — two-way canvas binding with debounced broadcast.
11
+ *
12
+ * Requires a `FusedWidgetBridgeContext` ancestor (like `useFusedParam`) and a
13
+ * `FormContext` ancestor for the in-form behavior (the built-in Form component
14
+ * provides one).
15
+ */
16
+ export declare function useFusedParamWithForm<T extends string | number>(options: UseFusedParamOptions<T>): UseFusedParamReturn<T> & {
17
+ isInForm: boolean;
18
+ };
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFusedParamWithForm = useFusedParamWithForm;
4
+ const react_1 = require("react");
5
+ const form_1 = require("../form");
6
+ const use_fused_param_1 = require("./use-fused-param");
7
+ /**
8
+ * Form-aware variant of {@link useFusedParam}.
9
+ *
10
+ * When the component is rendered inside a built-in Form, the field becomes
11
+ * local state (its value is NOT broadcast to the canvas) and its live value is
12
+ * mirrored into the form's subscription store, so sibling components (a
13
+ * dropdown's SQL options, a chart, a text binding, …) can react to it before
14
+ * the form is submitted. Outside a form it behaves exactly like
15
+ * `useFusedParam` — two-way canvas binding with debounced broadcast.
16
+ *
17
+ * Requires a `FusedWidgetBridgeContext` ancestor (like `useFusedParam`) and a
18
+ * `FormContext` ancestor for the in-form behavior (the built-in Form component
19
+ * provides one).
20
+ */
21
+ function useFusedParamWithForm(options) {
22
+ const formContext = (0, form_1.useFormContext)();
23
+ const param = options.param;
24
+ const isFormField = Boolean(formContext.isInForm && param);
25
+ // Hook handles both cases: with param (canvas sync) or without (local state).
26
+ // Disable canvas messaging when inside a form by withholding the param.
27
+ const { value, setValue, broadcastNow, clearValue } = (0, use_fused_param_1.useFusedParam)({
28
+ ...options,
29
+ param: isFormField ? undefined : options.param,
30
+ });
31
+ // Mirror the live value into the form's subscription store so sibling
32
+ // components can react to it. Value updates use a dedicated effect so we
33
+ // don't briefly remove the field from the store between renders —
34
+ // unregistration runs only when the binding (store/param) actually changes
35
+ // or on unmount.
36
+ const store = formContext.store;
37
+ (0, react_1.useEffect)(() => {
38
+ if (!isFormField || !param || !store)
39
+ return;
40
+ store.setField(param, value);
41
+ }, [value, isFormField, param, store]);
42
+ (0, react_1.useEffect)(() => {
43
+ if (!isFormField || !param || !store)
44
+ return;
45
+ return () => {
46
+ store.removeField(param);
47
+ };
48
+ }, [isFormField, param, store]);
49
+ return {
50
+ value,
51
+ setValue,
52
+ broadcastNow,
53
+ clearValue,
54
+ isInForm: formContext.isInForm,
55
+ };
56
+ }
@@ -1,7 +1,10 @@
1
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
- import { useFusedWidgetBridge, useJsonUiNode } from "../bridge";
3
- import { useFormParams } from "../form";
4
- import { ParameterMessageType } from "../protocol";
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFusedParam = useFusedParam;
4
+ const react_1 = require("react");
5
+ const bridge_1 = require("../bridge");
6
+ const form_1 = require("../form");
7
+ const protocol_1 = require("../protocol");
5
8
  /**
6
9
  * Two-way bind a component to a named canvas parameter.
7
10
  *
@@ -40,9 +43,9 @@ import { ParameterMessageType } from "../protocol";
40
43
  * const { clearValue } = useFusedParam({ param: "selection", defaultValue: null });
41
44
  * <button onClick={() => clearValue(null)}>Reset</button>
42
45
  */
43
- export function useFusedParam({ param, debounceMs = 300, readOnly = false, defaultValue, broadcastDefaultValue = true, validate, preprocess, }) {
44
- const bridge = useFusedWidgetBridge();
45
- const { configHash } = useJsonUiNode();
46
+ function useFusedParam({ param, debounceMs = 300, readOnly = false, defaultValue, broadcastDefaultValue = true, validate, preprocess, }) {
47
+ const bridge = (0, bridge_1.useFusedWidgetBridge)();
48
+ const { configHash } = (0, bridge_1.useJsonUiNode)();
46
49
  const enabled = !!param;
47
50
  // Stable log helper — entries appear in the workbench's runtime logs panel.
48
51
  // configHash is passed through so nested JsonUiConfigHashOverride subtrees
@@ -61,20 +64,20 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
61
64
  // Stable validator and preprocessor. We deliberately omit `defaultValue`
62
65
  // from the deps so a parent re-render passing a new defaultValue literal
63
66
  // doesn't churn these. The type semantics only depend on the original.
64
- const preprocessor = useMemo(() => preprocess ?? createDefaultPreprocessor(defaultValue),
67
+ const preprocessor = (0, react_1.useMemo)(() => preprocess ?? createDefaultPreprocessor(defaultValue),
65
68
  // eslint-disable-next-line react-hooks/exhaustive-deps
66
69
  [preprocess]);
67
- const validator = useMemo(() => validate ?? createDefaultValidator(defaultValue),
70
+ const validator = (0, react_1.useMemo)(() => validate ?? createDefaultValidator(defaultValue),
68
71
  // eslint-disable-next-line react-hooks/exhaustive-deps
69
72
  [validate]);
70
73
  // Form-scoped value shadows canvas value when inside a form.
71
- const paramNamesForForm = useMemo(() => (param ? [param] : []), [param]);
72
- const { inForm, values: formParams } = useFormParams(paramNamesForForm);
74
+ const paramNamesForForm = (0, react_1.useMemo)(() => (param ? [param] : []), [param]);
75
+ const { inForm, values: formParams } = (0, form_1.useFormParams)(paramNamesForForm);
73
76
  const formValue = param ? formParams[param] : undefined;
74
77
  // ── Initial value resolution ────────────────────────────────────────────
75
78
  // Read snapshot once to seed local state — subsequent updates come via the
76
79
  // sync effect below. Reading the bridge here is safe (synchronous).
77
- const initialCanvasValue = useMemo(() => {
80
+ const initialCanvasValue = (0, react_1.useMemo)(() => {
78
81
  if (!enabled || !param)
79
82
  return undefined;
80
83
  return bridge.params.getSnapshot(param);
@@ -86,24 +89,24 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
86
89
  const processed = preprocessor(raw);
87
90
  return validator(processed) ? processed : defaultValue;
88
91
  };
89
- const [value, setValueState] = useState(computeInitialValue);
90
- const valueRef = useRef(value);
92
+ const [value, setValueState] = (0, react_1.useState)(computeInitialValue);
93
+ const valueRef = (0, react_1.useRef)(value);
91
94
  valueRef.current = value;
92
- const debounceRef = useRef(null);
93
- const isLocalChangeRef = useRef(false);
94
- const didBroadcastOnMountRef = useRef(false);
95
+ const debounceRef = (0, react_1.useRef)(null);
96
+ const isLocalChangeRef = (0, react_1.useRef)(false);
97
+ const didBroadcastOnMountRef = (0, react_1.useRef)(false);
95
98
  // Stable closure over the latest binding for the unmount cleanup.
96
99
  // bridge is captured by ref too so the cleanup effect's deps can stay `[]`
97
100
  // — otherwise any bridge identity flip would re-run the effect and
98
101
  // broadcast a stray CLEAR for every bound input, cascading through the
99
102
  // canvas-param listener fan-out.
100
- const latestBindingRef = useRef({ enabled, param });
103
+ const latestBindingRef = (0, react_1.useRef)({ enabled, param });
101
104
  latestBindingRef.current = { enabled, param };
102
- const bridgeRef = useRef(bridge);
105
+ const bridgeRef = (0, react_1.useRef)(bridge);
103
106
  bridgeRef.current = bridge;
104
107
  // ── Clear bound param when name changes (carry-over avoidance) ──────────
105
- const prevParamRef = useRef(param);
106
- useEffect(() => {
108
+ const prevParamRef = (0, react_1.useRef)(param);
109
+ (0, react_1.useEffect)(() => {
107
110
  const prev = prevParamRef.current;
108
111
  prevParamRef.current = param;
109
112
  if (prev && prev !== param) {
@@ -111,7 +114,7 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
111
114
  }
112
115
  }, [bridge, param]);
113
116
  // ── Subscribe to canvas (and form) updates ──────────────────────────────
114
- useEffect(() => {
117
+ (0, react_1.useEffect)(() => {
115
118
  if (!enabled || !param)
116
119
  return;
117
120
  if (isLocalChangeRef.current)
@@ -131,7 +134,7 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
131
134
  // eslint-disable-next-line react-hooks/exhaustive-deps
132
135
  }, [bridge, param, enabled, inForm, formValue, preprocessor, validator]);
133
136
  // Subscribe to bridge canvas updates so changes from other nodes flow in.
134
- useEffect(() => {
137
+ (0, react_1.useEffect)(() => {
135
138
  if (!enabled || !param)
136
139
  return;
137
140
  const unsub = bridge.params.subscribe(param, () => {
@@ -150,16 +153,16 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
150
153
  // eslint-disable-next-line react-hooks/exhaustive-deps
151
154
  }, [bridge, param, enabled, preprocessor, validator]);
152
155
  // ── Broadcast plumbing ──────────────────────────────────────────────────
153
- const broadcast = useCallback((newValue) => {
156
+ const broadcast = (0, react_1.useCallback)((newValue) => {
154
157
  if (!enabled || !param)
155
158
  return;
156
- bridge.params.set(param, newValue, ParameterMessageType.PARAM);
159
+ bridge.params.set(param, newValue, protocol_1.ParameterMessageType.PARAM);
157
160
  bridge.edges.stopLoading();
158
161
  logPreview("Broadcast", newValue);
159
162
  },
160
163
  // eslint-disable-next-line react-hooks/exhaustive-deps
161
164
  [bridge, enabled, param]);
162
- const broadcastNow = useCallback(() => {
165
+ const broadcastNow = (0, react_1.useCallback)(() => {
163
166
  if (!enabled || readOnly)
164
167
  return;
165
168
  if (debounceRef.current) {
@@ -170,7 +173,7 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
170
173
  broadcast(valueRef.current);
171
174
  isLocalChangeRef.current = false;
172
175
  }, [bridge, broadcast, enabled, readOnly]);
173
- const clearValue = useCallback((newValue) => {
176
+ const clearValue = (0, react_1.useCallback)((newValue) => {
174
177
  if (debounceRef.current) {
175
178
  clearTimeout(debounceRef.current);
176
179
  debounceRef.current = null;
@@ -187,11 +190,11 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
187
190
  // eslint-disable-next-line react-hooks/exhaustive-deps
188
191
  [bridge, enabled, param, readOnly]);
189
192
  // Reset one-time mount broadcast guard when binding changes.
190
- useEffect(() => {
193
+ (0, react_1.useEffect)(() => {
191
194
  didBroadcastOnMountRef.current = false;
192
195
  }, [param, enabled]);
193
196
  // Broadcast default value on mount when no canvas value exists.
194
- useEffect(() => {
197
+ (0, react_1.useEffect)(() => {
195
198
  if (!enabled || !param || readOnly)
196
199
  return;
197
200
  if (!broadcastDefaultValue)
@@ -211,7 +214,7 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
211
214
  broadcast(valueRef.current);
212
215
  didBroadcastOnMountRef.current = true;
213
216
  }, [bridge, enabled, param, readOnly, broadcastDefaultValue, broadcast]);
214
- const setValue = useCallback((newValue) => {
217
+ const setValue = (0, react_1.useCallback)((newValue) => {
215
218
  setValueState(newValue);
216
219
  if (!enabled || readOnly)
217
220
  return;
@@ -228,7 +231,7 @@ export function useFusedParam({ param, debounceMs = 300, readOnly = false, defau
228
231
  // type-swaps don't leave stale canvas state behind. Deps are `[]` so this
229
232
  // runs on unmount only — never on bridge identity flips. bridge is read
230
233
  // from the ref at cleanup time.
231
- useEffect(() => {
234
+ (0, react_1.useEffect)(() => {
232
235
  return () => {
233
236
  if (debounceRef.current)
234
237
  clearTimeout(debounceRef.current);
@@ -1,4 +1,7 @@
1
- import { useFusedWidgetBridge } from "../bridge";
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useJsonUiEdgeAnimation = useJsonUiEdgeAnimation;
4
+ const bridge_1 = require("../bridge");
2
5
  /**
3
6
  * Controls the edge-animation pellet for the current canvas node.
4
7
  *
@@ -17,8 +20,8 @@ import { useFusedWidgetBridge } from "../bridge";
17
20
  * try { await heavyCompute(); } finally { stopLoading(); }
18
21
  * }
19
22
  */
20
- export function useJsonUiEdgeAnimation() {
21
- const bridge = useFusedWidgetBridge();
23
+ function useJsonUiEdgeAnimation() {
24
+ const bridge = (0, bridge_1.useFusedWidgetBridge)();
22
25
  return {
23
26
  startLoading: bridge.edges.startLoading,
24
27
  stopLoading: bridge.edges.stopLoading,
@@ -1,5 +1,10 @@
1
- import { useCallback, useMemo, useRef, useSyncExternalStore } from "react";
2
- import { useFusedWidgetBridge, useJsonUiNode, } from "../bridge";
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useJsonUiLog = useJsonUiLog;
4
+ exports.useJsonUiLogs = useJsonUiLogs;
5
+ exports.useJsonUiLogClear = useJsonUiLogClear;
6
+ const react_1 = require("react");
7
+ const bridge_1 = require("../bridge");
3
8
  const EMPTY_LOGS = Object.freeze([]);
4
9
  /**
5
10
  * Logging hook for json-ui components. Entries appear in the workbench's
@@ -16,22 +21,22 @@ const EMPTY_LOGS = Object.freeze([]);
16
21
  * log("Selected city: " + city);
17
22
  * log("Failed to load chart data", "error");
18
23
  */
19
- export function useJsonUiLog() {
20
- const bridge = useFusedWidgetBridge();
21
- const { configHash } = useJsonUiNode();
24
+ function useJsonUiLog() {
25
+ const bridge = (0, bridge_1.useFusedWidgetBridge)();
26
+ const { configHash } = (0, bridge_1.useJsonUiNode)();
22
27
  // bridge and configHash are read from refs so the returned `log` callback
23
28
  // identity is stable across re-renders. Downstream effects with `log` in
24
29
  // their deps (e.g. use-duckdb-sql.ts's preprocessing effect) would
25
30
  // otherwise re-fire on every bridge flip / configHash change and cascade
26
31
  // setState across every SQL widget in the dashboard.
27
- const bridgeRef = useRef(bridge);
32
+ const bridgeRef = (0, react_1.useRef)(bridge);
28
33
  bridgeRef.current = bridge;
29
- const configHashRef = useRef(configHash);
34
+ const configHashRef = (0, react_1.useRef)(configHash);
30
35
  configHashRef.current = configHash;
31
- const log = useCallback((message, level = "info") => {
36
+ const log = (0, react_1.useCallback)((message, level = "info") => {
32
37
  bridgeRef.current.log.log(message, level, configHashRef.current);
33
38
  }, []);
34
- return useMemo(() => ({ log }), [log]);
39
+ return (0, react_1.useMemo)(() => ({ log }), [log]);
35
40
  }
36
41
  /**
37
42
  * Read-only hook returning the current log entries for a given node.
@@ -41,15 +46,15 @@ export function useJsonUiLog() {
41
46
  * rarely need to read logs they wrote, but the hook is exposed for
42
47
  * completeness (e.g. building a debug view component).
43
48
  */
44
- export function useJsonUiLogs(nodeId) {
45
- const bridge = useFusedWidgetBridge();
46
- const subscribe = useCallback((cb) => {
49
+ function useJsonUiLogs(nodeId) {
50
+ const bridge = (0, bridge_1.useFusedWidgetBridge)();
51
+ const subscribe = (0, react_1.useCallback)((cb) => {
47
52
  if (!nodeId)
48
53
  return () => { };
49
54
  return bridge.log.subscribeLogs(nodeId, cb);
50
55
  }, [bridge, nodeId]);
51
- const snapshotRef = useRef(EMPTY_LOGS);
52
- const getSnapshot = useCallback(() => {
56
+ const snapshotRef = (0, react_1.useRef)(EMPTY_LOGS);
57
+ const getSnapshot = (0, react_1.useCallback)(() => {
53
58
  if (!nodeId)
54
59
  return EMPTY_LOGS;
55
60
  const next = bridge.log.getLogsSnapshot(nodeId);
@@ -58,15 +63,15 @@ export function useJsonUiLogs(nodeId) {
58
63
  snapshotRef.current = next;
59
64
  return next;
60
65
  }, [bridge, nodeId]);
61
- return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
66
+ return (0, react_1.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
62
67
  }
63
68
  /**
64
69
  * Returns a stable callback that clears all log entries for the given node.
65
70
  * Returns a no-op function when `nodeId` is undefined.
66
71
  */
67
- export function useJsonUiLogClear(nodeId) {
68
- const bridge = useFusedWidgetBridge();
69
- return useCallback(() => {
72
+ function useJsonUiLogClear(nodeId) {
73
+ const bridge = (0, bridge_1.useFusedWidgetBridge)();
74
+ return (0, react_1.useCallback)(() => {
70
75
  if (!nodeId)
71
76
  return;
72
77
  bridge.log.clearLogs(nodeId);