@datarecce/ui 0.1.1 → 0.1.8

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/hooks.js CHANGED
@@ -2,14 +2,34 @@
2
2
 
3
3
  var reactQuery = require('@tanstack/react-query');
4
4
  var axios = require('axios');
5
- var react = require('@chakra-ui/react');
5
+ require('@mui/material/Alert');
6
+ require('@mui/material/CircularProgress');
7
+ require('@mui/material/Snackbar');
8
+ var Stack2 = require('@mui/material/Stack');
9
+ require('@mui/material/Typography');
10
+ var react = require('react');
6
11
  var jsxRuntime = require('react/jsx-runtime');
7
- var react$1 = require('react');
12
+ var Box = require('@mui/material/Box');
13
+ var Button = require('@mui/material/Button');
14
+ var MuiDialog = require('@mui/material/Dialog');
15
+ var DialogActions = require('@mui/material/DialogActions');
16
+ var DialogContent = require('@mui/material/DialogContent');
17
+ var DialogTitle = require('@mui/material/DialogTitle');
18
+ var IconButton = require('@mui/material/IconButton');
19
+ var io5 = require('react-icons/io5');
8
20
  var unified = require('@amplitude/unified');
9
21
 
10
22
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
23
 
12
24
  var axios__default = /*#__PURE__*/_interopDefault(axios);
25
+ var Stack2__default = /*#__PURE__*/_interopDefault(Stack2);
26
+ var Box__default = /*#__PURE__*/_interopDefault(Box);
27
+ var Button__default = /*#__PURE__*/_interopDefault(Button);
28
+ var MuiDialog__default = /*#__PURE__*/_interopDefault(MuiDialog);
29
+ var DialogActions__default = /*#__PURE__*/_interopDefault(DialogActions);
30
+ var DialogContent__default = /*#__PURE__*/_interopDefault(DialogContent);
31
+ var DialogTitle__default = /*#__PURE__*/_interopDefault(DialogTitle);
32
+ var IconButton__default = /*#__PURE__*/_interopDefault(IconButton);
13
33
 
14
34
  // recce-source/js/src/lib/api/cacheKeys.ts
15
35
  var cacheKeys = {
@@ -52,10 +72,37 @@ var useRecceInstanceInfo = () => {
52
72
  queryFn: getRecceInstanceInfo
53
73
  });
54
74
  };
55
- var toaster = react.createToaster({
56
- placement: "bottom-end",
57
- pauseOnPageIdle: true
58
- });
75
+ react.createContext(null);
76
+ var toastIdCounter = 0;
77
+ var listeners = /* @__PURE__ */ new Set();
78
+ var toaster = {
79
+ create: (options) => {
80
+ const id = options.id || `toast-${++toastIdCounter}`;
81
+ listeners.forEach(
82
+ (listener) => listener({ type: "create", options: { ...options, id } })
83
+ );
84
+ return id;
85
+ },
86
+ success: (options) => toaster.create({ ...options, type: "success" }),
87
+ error: (options) => toaster.create({ ...options, type: "error" }),
88
+ warning: (options) => toaster.create({ ...options, type: "warning" }),
89
+ info: (options) => toaster.create({ ...options, type: "info" }),
90
+ loading: (options) => toaster.create({ ...options, type: "loading" }),
91
+ dismiss: (id) => {
92
+ listeners.forEach((listener) => listener({ type: "dismiss", id }));
93
+ },
94
+ // Alias for dismiss (for backward compatibility)
95
+ remove: (id) => {
96
+ listeners.forEach((listener) => listener({ type: "dismiss", id }));
97
+ },
98
+ update: (id, options) => {
99
+ listeners.forEach((listener) => listener({ type: "update", id, options }));
100
+ },
101
+ subscribe: (listener) => {
102
+ listeners.add(listener);
103
+ return () => listeners.delete(listener);
104
+ }
105
+ };
59
106
 
60
107
  // recce-source/js/src/lib/hooks/useCheckToast.tsx
61
108
  function useCheckToast() {
@@ -95,9 +142,9 @@ function useClipBoardToast() {
95
142
  failToast
96
143
  };
97
144
  }
98
- var LineageViewContext = react$1.createContext(void 0);
145
+ var LineageViewContext = react.createContext(void 0);
99
146
  var useLineageViewContext = () => {
100
- return react$1.useContext(LineageViewContext);
147
+ return react.useContext(LineageViewContext);
101
148
  };
102
149
  function track(eventInput, eventProperties, eventOptions) {
103
150
  {
@@ -115,27 +162,24 @@ function trackExploreActionForm(props) {
115
162
  track("[Web] explore_action_form", props);
116
163
  }
117
164
  function useValueDiffAlertDialog() {
118
- const { open, onOpen, onClose } = react.useDisclosure();
119
- const [nodeCount, setNodeCount] = react$1.useState(0);
120
- const [resolvePromise, setResolvePromise] = react$1.useState();
121
- const cancelRef = react$1.useRef(null);
122
- const confirm = react$1.useCallback(
123
- (nodeCount2) => {
124
- setNodeCount(nodeCount2);
125
- return new Promise((resolve) => {
126
- setResolvePromise(() => resolve);
127
- onOpen();
128
- });
129
- },
130
- [onOpen]
131
- );
165
+ const [open, setOpen] = react.useState(false);
166
+ const [nodeCount, setNodeCount] = react.useState(0);
167
+ const [resolvePromise, setResolvePromise] = react.useState();
168
+ const cancelRef = react.useRef(null);
169
+ const confirm = react.useCallback((nodeCount2) => {
170
+ setNodeCount(nodeCount2);
171
+ return new Promise((resolve) => {
172
+ setResolvePromise(() => resolve);
173
+ setOpen(true);
174
+ });
175
+ }, []);
132
176
  const handleConfirm = () => {
133
177
  trackExploreActionForm({
134
178
  action: EXPLORE_ACTION.VALUE_DIFF,
135
179
  event: EXPLORE_FORM_EVENT.EXECUTE
136
180
  });
137
181
  resolvePromise?.(true);
138
- onClose();
182
+ setOpen(false);
139
183
  };
140
184
  const handleCancel = () => {
141
185
  trackExploreActionForm({
@@ -143,47 +187,71 @@ function useValueDiffAlertDialog() {
143
187
  event: EXPLORE_FORM_EVENT.CANCEL
144
188
  });
145
189
  resolvePromise?.(false);
146
- onClose();
190
+ setOpen(false);
147
191
  };
148
- const ValueDiffAlertDialog = /* @__PURE__ */ jsxRuntime.jsx(
149
- react.Dialog.Root,
192
+ const ValueDiffAlertDialog = /* @__PURE__ */ jsxRuntime.jsxs(
193
+ MuiDialog__default.default,
150
194
  {
151
- size: "xl",
152
195
  open,
153
- role: "alertdialog",
154
- initialFocusEl: () => {
155
- return cancelRef.current;
156
- },
157
- onOpenChange: handleCancel,
158
- children: /* @__PURE__ */ jsxRuntime.jsxs(react.Portal, { children: [
159
- /* @__PURE__ */ jsxRuntime.jsx(react.Dialog.Backdrop, {}),
160
- /* @__PURE__ */ jsxRuntime.jsx(react.Dialog.Positioner, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Dialog.Content, { children: [
161
- /* @__PURE__ */ jsxRuntime.jsx(react.Dialog.Header, { fontSize: "lg", fontWeight: "bold", children: /* @__PURE__ */ jsxRuntime.jsxs(react.Dialog.Title, { children: [
162
- "Value Diff on ",
163
- nodeCount,
164
- " nodes"
165
- ] }) }),
166
- /* @__PURE__ */ jsxRuntime.jsx(react.Dialog.Body, { gap: "20px", as: react.Flex, direction: "column", children: /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { children: [
167
- "Value diff will be executed on ",
168
- nodeCount,
169
- " nodes in the Lineage, which can add extra costs to your bill."
170
- ] }) }),
171
- /* @__PURE__ */ jsxRuntime.jsxs(react.Dialog.Footer, { gap: 1, children: [
172
- /* @__PURE__ */ jsxRuntime.jsx(
173
- react.Button,
174
- {
175
- ref: cancelRef,
176
- onClick: handleCancel,
177
- variant: "outline",
178
- colorPalette: "gray",
179
- children: "Cancel"
180
- }
181
- ),
182
- /* @__PURE__ */ jsxRuntime.jsx(react.Button, { colorPalette: "iochmara", onClick: handleConfirm, ml: 3, children: "Execute" })
183
- ] }),
184
- /* @__PURE__ */ jsxRuntime.jsx(react.Dialog.CloseTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(react.CloseButton, { size: "sm" }) })
185
- ] }) })
186
- ] })
196
+ onClose: handleCancel,
197
+ maxWidth: "md",
198
+ fullWidth: true,
199
+ "aria-labelledby": "value-diff-alert-dialog-title",
200
+ children: [
201
+ /* @__PURE__ */ jsxRuntime.jsxs(
202
+ DialogTitle__default.default,
203
+ {
204
+ id: "value-diff-alert-dialog-title",
205
+ sx: { fontSize: "1.125rem", fontWeight: "bold" },
206
+ children: [
207
+ "Value Diff on ",
208
+ nodeCount,
209
+ " nodes"
210
+ ]
211
+ }
212
+ ),
213
+ /* @__PURE__ */ jsxRuntime.jsx(
214
+ IconButton__default.default,
215
+ {
216
+ "aria-label": "close",
217
+ onClick: handleCancel,
218
+ sx: {
219
+ position: "absolute",
220
+ right: 8,
221
+ top: 8,
222
+ color: "grey.500"
223
+ },
224
+ children: /* @__PURE__ */ jsxRuntime.jsx(io5.IoClose, {})
225
+ }
226
+ ),
227
+ /* @__PURE__ */ jsxRuntime.jsx(DialogContent__default.default, { children: /* @__PURE__ */ jsxRuntime.jsx(Stack2__default.default, { spacing: "20px", children: /* @__PURE__ */ jsxRuntime.jsxs(Box__default.default, { children: [
228
+ "Value diff will be executed on ",
229
+ nodeCount,
230
+ " nodes in the Lineage, which can add extra costs to your bill."
231
+ ] }) }) }),
232
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogActions__default.default, { sx: { gap: 0.5 }, children: [
233
+ /* @__PURE__ */ jsxRuntime.jsx(
234
+ Button__default.default,
235
+ {
236
+ ref: cancelRef,
237
+ onClick: handleCancel,
238
+ variant: "outlined",
239
+ color: "neutral",
240
+ children: "Cancel"
241
+ }
242
+ ),
243
+ /* @__PURE__ */ jsxRuntime.jsx(
244
+ Button__default.default,
245
+ {
246
+ color: "iochmara",
247
+ variant: "contained",
248
+ onClick: handleConfirm,
249
+ sx: { ml: 1.5 },
250
+ children: "Execute"
251
+ }
252
+ )
253
+ ] })
254
+ ]
187
255
  }
188
256
  );
189
257
  return { confirm, AlertDialog: ValueDiffAlertDialog };
package/dist/hooks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../recce-source/js/src/lib/api/cacheKeys.ts","../recce-source/js/src/lib/const.ts","../recce-source/js/src/lib/api/axiosClient.ts","../recce-source/js/src/lib/api/instanceInfo.ts","../recce-source/js/src/lib/hooks/useRecceInstanceInfo.tsx","../recce-source/js/src/components/ui/toaster.tsx","../recce-source/js/src/lib/hooks/useCheckToast.tsx","../recce-source/js/src/lib/hooks/useClipBoardToast.tsx","../recce-source/js/src/components/lineage/LineageViewContext.tsx","../recce-source/js/src/lib/api/track.ts","../recce-source/js/src/components/lineage/useValueDiffAlertDialog.tsx"],"names":["axios","QueryClient","useQuery","createToaster","createContext","useContext","trk","useDisclosure","useState","useRef","useCallback","nodeCount","jsx","Dialog","jsxs","Portal","Flex","Box","Button","CloseButton"],"mappings":"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","file":"hooks.js","sourcesContent":["export const cacheKeys = {\n rowCount: (model: string) => [\"row_count\", model],\n lineage: () => [\"lineage\"],\n checks: () => [\"checks\", \"list\"],\n check: (checkId: string) => [\"checks\", checkId],\n checkEvents: (checkId: string) => [\"checks\", checkId, \"events\"],\n runs: () => [\"runs\"],\n run: (runId: string) => [\"runs\", runId],\n runsAggregated: () => [\"runs_aggregated\"],\n flag: () => [\"flag\"],\n instanceInfo: () => [\"instance_info\"],\n user: () => [\"user\"],\n};\n","let apiUrl = process.env.NEXT_PUBLIC_API_URL;\napiUrl ??= typeof window !== \"undefined\" ? window.location.origin : \"\";\n\nexport const PUBLIC_API_URL = apiUrl;\n\nlet cloudWebUrl = process.env.NEXT_PUBLIC_CLOUD_WEB_URL;\ncloudWebUrl ??= \"https://cloud.datarecce.io\";\n\nexport const PUBLIC_CLOUD_WEB_URL = cloudWebUrl;\n","import { QueryClient } from \"@tanstack/react-query\";\nimport axios from \"axios\";\nimport { PUBLIC_API_URL } from \"@/lib/const\";\n\nexport const axiosClient = axios.create({\n baseURL: PUBLIC_API_URL,\n});\n\nexport const reactQueryClient = new QueryClient();\n","import { AxiosResponse } from \"axios\";\nimport { axiosClient } from \"./axiosClient\";\n\nexport interface RecceInstanceInfo {\n server_mode: \"server\" | \"preview\" | \"read-only\";\n single_env: boolean;\n authed: boolean;\n cloud_instance: boolean;\n lifetime_expired_at?: Date;\n idle_timeout?: number;\n share_url?: string;\n session_id?: string;\n organization_name?: string;\n web_url?: string;\n}\n\nexport async function getRecceInstanceInfo(): Promise<RecceInstanceInfo> {\n return (\n await axiosClient.get<never, AxiosResponse<RecceInstanceInfo>>(\n \"/api/instance-info\",\n )\n ).data;\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { cacheKeys } from \"../api/cacheKeys\";\nimport { getRecceInstanceInfo, RecceInstanceInfo } from \"../api/instanceInfo\";\n\nexport const useRecceInstanceInfo = () => {\n return useQuery<RecceInstanceInfo>({\n queryKey: cacheKeys.instanceInfo(),\n queryFn: getRecceInstanceInfo,\n });\n};\n","\"use client\";\n\nimport type { CreateToasterReturn } from \"@chakra-ui/react\";\nimport {\n Toaster as ChakraToaster,\n createToaster,\n Portal,\n Spinner,\n Stack,\n Toast,\n} from \"@chakra-ui/react\";\n\nexport const toaster: CreateToasterReturn = createToaster({\n placement: \"bottom-end\",\n pauseOnPageIdle: true,\n});\n\nexport const Toaster = () => {\n return (\n <Portal>\n <ChakraToaster toaster={toaster} insetInline={{ mdDown: \"4\" }}>\n {(toast) => (\n <Toast.Root width={{ md: \"sm\" }}>\n {toast.type === \"loading\" ? (\n <Spinner size=\"sm\" color=\"blue.solid\" />\n ) : (\n <Toast.Indicator />\n )}\n <Stack gap=\"1\" flex=\"1\" maxWidth=\"100%\">\n {toast.title && <Toast.Title>{toast.title}</Toast.Title>}\n {toast.description && (\n <Toast.Description>{toast.description}</Toast.Description>\n )}\n </Stack>\n {toast.action && (\n <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>\n )}\n {toast.closable && <Toast.CloseTrigger />}\n </Toast.Root>\n )}\n </ChakraToaster>\n </Portal>\n );\n};\n","import { toaster } from \"@/components/ui/toaster\";\n\nexport function useCheckToast() {\n function markedAsApprovedToast() {\n toaster.create({\n title: \"Marked as approved\",\n type: \"success\",\n duration: 2000,\n });\n }\n return {\n markedAsApprovedToast,\n };\n}\n","import { toaster } from \"@/components/ui/toaster\";\n\nexport function useClipBoardToast() {\n function successToast(message: string) {\n toaster.create({\n description: message,\n type: \"info\",\n duration: 5000,\n closable: true,\n });\n }\n\n function failToast(title: string, error: unknown) {\n toaster.create({\n title: title,\n description: String(error),\n type: \"error\",\n duration: 5000,\n closable: true,\n });\n }\n\n return {\n successToast,\n failToast,\n };\n}\n","import React, { createContext, useContext } from \"react\";\nimport { CllInput, ColumnLineageData } from \"@/lib/api/cll\";\nimport { LineageDiffViewOptions } from \"@/lib/api/lineagecheck\";\nimport { Run } from \"@/lib/api/types\";\nimport { LineageGraphNode, LineageGraphNodes } from \"./lineage\";\n\ntype NewType = LineageDiffViewOptions;\ntype ActionMode = \"per_node\" | \"multi_nodes\";\n\ninterface NodeAction {\n mode: ActionMode;\n status?: \"pending\" | \"running\" | \"success\" | \"failure\" | \"skipped\";\n skipReason?: string;\n run?: Run;\n}\n\nexport interface ActionState {\n mode: ActionMode;\n status: \"pending\" | \"running\" | \"canceling\" | \"canceled\" | \"completed\";\n currentRun?: Partial<Run>;\n completed: number;\n total: number;\n actions: Record<string, NodeAction>;\n}\n\nexport interface LineageViewContextType {\n interactive: boolean;\n nodes: LineageGraphNodes[];\n focusedNode?: LineageGraphNode;\n selectedNodes: LineageGraphNode[];\n cll: ColumnLineageData | undefined;\n\n // context menu\n showContextMenu: (event: React.MouseEvent, node: LineageGraphNodes) => void;\n\n // filter\n viewOptions: LineageDiffViewOptions;\n onViewOptionsChanged: (options: NewType) => void;\n\n // Multi nodes selection\n selectMode: \"selecting\" | \"action_result\" | undefined;\n selectNode: (nodeId: string) => void;\n selectParentNodes: (nodeId: string, degree?: number) => void;\n selectChildNodes: (nodeId: string, degree?: number) => void;\n deselect: () => void;\n\n // node state\n isNodeHighlighted: (nodeId: string) => boolean;\n isNodeSelected: (nodeId: string) => boolean;\n isEdgeHighlighted: (source: string, target: string) => boolean;\n getNodeAction: (nodeId: string) => NodeAction;\n getNodeColumnSet: (nodeId: string) => Set<string>;\n isNodeShowingChangeAnalysis: (nodeId: string) => boolean;\n\n //actions\n runRowCount: () => Promise<void>;\n runRowCountDiff: () => Promise<void>;\n runValueDiff: () => Promise<void>;\n addLineageDiffCheck: (viewMode?: string) => void;\n addSchemaDiffCheck: () => void;\n cancel: () => void;\n actionState: ActionState;\n\n // Column Level Lineage\n centerNode: (nodeId: string) => void;\n showColumnLevelLineage: (cll?: CllInput) => Promise<void>;\n resetColumnLevelLineage: (previous?: boolean) => Promise<void>;\n}\n\nexport const LineageViewContext = createContext<\n LineageViewContextType | undefined\n>(undefined);\n\nexport const useLineageViewContextSafe = (): LineageViewContextType => {\n const context = useContext(LineageViewContext);\n if (!context) {\n throw new Error(\n \"useLineageViewContext must be used within a LineageViewProvider\",\n );\n }\n return context;\n};\n\nexport const useLineageViewContext = (): LineageViewContextType | undefined => {\n return useContext(LineageViewContext);\n};\n","import {\n AmplitudeReturn,\n BaseEvent,\n EventOptions,\n Result,\n} from \"@amplitude/analytics-core\";\nimport { initAll, track as trk } from \"@amplitude/unified\";\n\nfunction track(\n eventInput: string | BaseEvent,\n // biome-ignore lint/suspicious/noExplicitAny: Amplitude library uses any for event properties\n eventProperties?: Record<string, any> | undefined,\n eventOptions?: EventOptions | undefined,\n): AmplitudeReturn<Result> {\n // If Amplitude isn't initialized, log to console instead\n if (!amplitudeInitialized) {\n console.log(\"[Tracking]\", eventInput, eventProperties, eventOptions);\n }\n return trk(eventInput, eventProperties, eventOptions);\n}\n\nlet amplitudeInitialized = false;\n\nexport function trackInit() {\n function getCookie(key: string) {\n const b = document.cookie.match(\"(^|;)\\\\s*\" + key + \"\\\\s*=\\\\s*([^;]+)\");\n return b ? b.pop() : \"\";\n }\n\n const userId =\n process.env.NODE_ENV === \"development\"\n ? \"web_dev\"\n : getCookie(\"recce_user_id\");\n const apiKey = process.env.AMPLITUDE_API_KEY;\n if (userId && apiKey) {\n try {\n void initAll(apiKey, {\n analytics: {\n userId,\n autocapture: true,\n },\n sessionReplay: {\n sampleRate: 1,\n },\n });\n amplitudeInitialized = true;\n } catch (e) {\n console.error(e);\n }\n }\n\n // Log when Amplitude is not initialized (for development/debugging)\n if (!amplitudeInitialized) {\n console.log(\n \"[Tracking] Amplitude not initialized (missing API key or user ID). Events will be logged to console instead.\",\n );\n }\n}\n\ninterface MultiNodeActionProps {\n type:\n | \"row_count\"\n | \"row_count_diff\"\n | \"value_diff\"\n | \"schema_diff\"\n | \"lineage_diff\";\n selected: \"single\" | \"multi\" | \"none\";\n}\n\nexport function trackMultiNodesAction(props: MultiNodeActionProps) {\n track(\"[Web] multi_nodes_action\", props);\n}\n\ninterface HistoryActionProps {\n name: \"show\" | \"hide\" | \"click_run\" | \"add_to_checklist\" | \"go_to_check\";\n}\n\nexport function trackHistoryAction(props: HistoryActionProps) {\n track(\"[Web] history_action\", props);\n}\n\ninterface PreviewChangeProps {\n action: \"explore\" | \"run\" | \"close\";\n node?: string;\n status?: \"success\" | \"failure\";\n}\n\nexport function trackPreviewChange(props: PreviewChangeProps) {\n track(\"[Experiment] preview_change\", props);\n}\n\ninterface PreviewChangeFeedbackProps {\n feedback: \"like\" | \"dislike\" | \"form\";\n node?: string;\n}\n\nexport function trackPreviewChangeFeedback(props: PreviewChangeFeedbackProps) {\n track(\"[Experiment] preview_change\", props);\n}\n\ninterface SingleEnvironmentProps {\n action:\n | \"onboarding\"\n | \"external_link\"\n | \"preview_changes\"\n | `target_base_added`;\n from?: \"onboarding\" | \"preview_changes\";\n node?: string;\n}\n\nexport function trackSingleEnvironment(props: SingleEnvironmentProps) {\n track(\"[Experiment] single_environment\", props);\n}\n\nexport function getExperimentTrackingBreakingChangeEnabled() {\n return false;\n}\n\ninterface ColumnLevelLineageProps {\n action: \"view\";\n source: \"schema_column\" | \"changed_column\" | \"cll_column\";\n}\n\nexport function trackColumnLevelLineage(props: ColumnLevelLineageProps) {\n track(\"[Web] column_level_lineage\", props);\n}\n\ninterface ShareStateProps {\n name: \"enable\" | \"create\" | \"copy\";\n}\n\nexport function trackShareState(props: ShareStateProps) {\n track(\"[Web] share_state\", props);\n}\n\ninterface StateActionProps {\n name: \"import\" | \"export\";\n}\n\nexport function trackStateAction(props: StateActionProps) {\n track(\"[Web] state_action\", props);\n}\n\ninterface CopyToClipboardProps {\n from: \"run\" | \"check\" | \"lineage_view\";\n type: string;\n}\n\nexport function trackCopyToClipboard(props: CopyToClipboardProps) {\n track(\"[Click] copy_to_clipboard\", props);\n}\n\ninterface TrackNavProps {\n from: string;\n to: string;\n}\n\nexport function trackNavigation(props: TrackNavProps) {\n track(\"[Web] navigation_change\", props);\n}\n\nexport interface LineageViewRenderProps {\n node_count: number;\n view_mode: string;\n impact_radius_enabled: boolean;\n cll_column_active?: boolean;\n right_sidebar_open: boolean;\n [status: string]: number | string | boolean | undefined;\n}\n\nexport function trackLineageViewRender(props: LineageViewRenderProps) {\n track(\"[Web] lineage_view_render\", props);\n}\n\nexport interface EnvironmentConfigProps {\n review_mode: boolean;\n adapter_type: string | null;\n has_git_info: boolean;\n has_pr_info: boolean;\n // Adapter-specific (shape varies by adapter_type)\n base?: {\n schema_count?: number;\n dbt_version?: string | null;\n timestamp?: string | null;\n has_env?: boolean;\n };\n current?: {\n schema_count?: number;\n dbt_version?: string | null;\n timestamp?: string | null;\n has_env?: boolean;\n };\n schemas_match?: boolean;\n}\n\nexport function trackEnvironmentConfig(props: EnvironmentConfigProps) {\n track(\"[Web] environment_config\", props);\n}\n\n// Explore action types\nexport const EXPLORE_ACTION = {\n ROW_COUNT: \"row_count\",\n ROW_COUNT_DIFF: \"row_count_diff\",\n PROFILE: \"profile\",\n PROFILE_DIFF: \"profile_diff\",\n VALUE_DIFF: \"value_diff\",\n SCHEMA_DIFF: \"schema_diff\",\n LINEAGE_DIFF: \"lineage_diff\",\n QUERY: \"query\",\n HISTOGRAM_DIFF: \"histogram_diff\",\n TOP_K_DIFF: \"top_k_diff\",\n} as const;\n\n// Explore action sources\nexport const EXPLORE_SOURCE = {\n LINEAGE_VIEW_TOP_BAR: \"lineage_view_top_bar\",\n LINEAGE_VIEW_CONTEXT_MENU: \"lineage_view_context_menu\",\n NODE_KEBAB_MENU: \"node_kebab_menu\",\n NODE_SIDEBAR_SINGLE_ENV: \"node_sidebar_single_env\",\n NODE_SIDEBAR_MULTI_ENV: \"node_sidebar_multi_env\",\n SCHEMA_ROW_COUNT_BUTTON: \"schema_row_count_button\",\n SCHEMA_COLUMN_MENU: \"schema_column_menu\",\n} as const;\n\nexport type ExploreActionType =\n (typeof EXPLORE_ACTION)[keyof typeof EXPLORE_ACTION];\nexport type ExploreSourceType =\n (typeof EXPLORE_SOURCE)[keyof typeof EXPLORE_SOURCE];\n\ninterface ExploreActionProps {\n action: ExploreActionType;\n source: ExploreSourceType;\n node_count?: number;\n}\n\nexport function trackExploreAction(props: ExploreActionProps) {\n track(\"[Web] explore_action\", props);\n}\n\n// Explore action form events\nexport const EXPLORE_FORM_EVENT = {\n EXECUTE: \"execute\",\n CANCEL: \"cancel\",\n} as const;\n\nexport type ExploreFormEventType =\n (typeof EXPLORE_FORM_EVENT)[keyof typeof EXPLORE_FORM_EVENT];\n\ninterface ExploreActionFormProps {\n action: ExploreActionType;\n event: ExploreFormEventType;\n}\n\nexport function trackExploreActionForm(props: ExploreActionFormProps) {\n track(\"[Web] explore_action_form\", props);\n}\n\n// Helper to check if a run type is an explore action\nexport function isExploreAction(type: string): type is ExploreActionType {\n return Object.values(EXPLORE_ACTION).includes(type as ExploreActionType);\n}\n\n// Lineage selection action types\nexport const LINEAGE_SELECTION_ACTION = {\n SELECT_PARENT_NODES: \"select_parent_nodes\",\n SELECT_CHILD_NODES: \"select_child_nodes\",\n SELECT_ALL_UPSTREAM: \"select_all_upstream\",\n SELECT_ALL_DOWNSTREAM: \"select_all_downstream\",\n} as const;\n\nexport type LineageSelectionActionType =\n (typeof LINEAGE_SELECTION_ACTION)[keyof typeof LINEAGE_SELECTION_ACTION];\n\ninterface LineageSelectionProps {\n action: LineageSelectionActionType;\n node_count?: number;\n}\n\nexport function trackLineageSelection(props: LineageSelectionProps) {\n track(\"[Web] lineage_selection\", props);\n}\n","import {\n Box,\n Button,\n CloseButton,\n Dialog,\n Flex,\n Portal,\n useDisclosure,\n} from \"@chakra-ui/react\";\nimport React, { useCallback, useRef, useState } from \"react\";\nimport {\n EXPLORE_ACTION,\n EXPLORE_FORM_EVENT,\n trackExploreActionForm,\n} from \"@/lib/api/track\";\n\nfunction useValueDiffAlertDialog() {\n const { open, onOpen, onClose } = useDisclosure();\n const [nodeCount, setNodeCount] = useState(0);\n const [resolvePromise, setResolvePromise] =\n useState<(value: boolean) => void>();\n const cancelRef = useRef<HTMLButtonElement>(null);\n\n const confirm = useCallback(\n (nodeCount: number) => {\n setNodeCount(nodeCount);\n return new Promise<boolean>((resolve) => {\n setResolvePromise(() => resolve);\n onOpen();\n });\n },\n [onOpen],\n );\n\n const handleConfirm = () => {\n trackExploreActionForm({\n action: EXPLORE_ACTION.VALUE_DIFF,\n event: EXPLORE_FORM_EVENT.EXECUTE,\n });\n resolvePromise?.(true);\n onClose();\n };\n\n const handleCancel = () => {\n trackExploreActionForm({\n action: EXPLORE_ACTION.VALUE_DIFF,\n event: EXPLORE_FORM_EVENT.CANCEL,\n });\n resolvePromise?.(false);\n onClose();\n };\n\n const ValueDiffAlertDialog = (\n <Dialog.Root\n size={\"xl\"}\n open={open}\n role=\"alertdialog\"\n initialFocusEl={() => {\n return cancelRef.current;\n }}\n onOpenChange={handleCancel}\n >\n <Portal>\n <Dialog.Backdrop />\n <Dialog.Positioner>\n <Dialog.Content>\n <Dialog.Header fontSize=\"lg\" fontWeight=\"bold\">\n <Dialog.Title>Value Diff on {nodeCount} nodes</Dialog.Title>\n </Dialog.Header>\n\n <Dialog.Body gap=\"20px\" as={Flex} direction=\"column\">\n <Box>\n Value diff will be executed on {nodeCount} nodes in the Lineage,\n which can add extra costs to your bill.\n </Box>\n </Dialog.Body>\n\n <Dialog.Footer gap={1}>\n <Button\n ref={cancelRef}\n onClick={handleCancel}\n variant=\"outline\"\n colorPalette=\"gray\"\n >\n Cancel\n </Button>\n <Button colorPalette=\"iochmara\" onClick={handleConfirm} ml={3}>\n Execute\n </Button>\n </Dialog.Footer>\n <Dialog.CloseTrigger asChild>\n <CloseButton size=\"sm\" />\n </Dialog.CloseTrigger>\n </Dialog.Content>\n </Dialog.Positioner>\n </Portal>\n </Dialog.Root>\n );\n\n return { confirm, AlertDialog: ValueDiffAlertDialog };\n}\n\nexport default useValueDiffAlertDialog;\n"]}
1
+ {"version":3,"sources":["../recce-source/js/src/lib/api/cacheKeys.ts","../recce-source/js/src/lib/const.ts","../recce-source/js/src/lib/api/axiosClient.ts","../recce-source/js/src/lib/api/instanceInfo.ts","../recce-source/js/src/lib/hooks/useRecceInstanceInfo.tsx","../recce-source/js/src/components/ui/toaster.tsx","../recce-source/js/src/lib/hooks/useCheckToast.tsx","../recce-source/js/src/lib/hooks/useClipBoardToast.tsx","../recce-source/js/src/components/lineage/LineageViewContext.tsx","../recce-source/js/src/lib/api/track.ts","../recce-source/js/src/components/lineage/useValueDiffAlertDialog.tsx"],"names":["axios","QueryClient","useQuery","createContext","useContext","trk","useState","useRef","useCallback","nodeCount","jsxs","MuiDialog","DialogTitle","jsx","IconButton","IoClose","DialogContent","Stack","Box","DialogActions","Button"],"mappings":"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","file":"hooks.js","sourcesContent":["export const cacheKeys = {\n rowCount: (model: string) => [\"row_count\", model],\n lineage: () => [\"lineage\"],\n checks: () => [\"checks\", \"list\"],\n check: (checkId: string) => [\"checks\", checkId],\n checkEvents: (checkId: string) => [\"checks\", checkId, \"events\"],\n runs: () => [\"runs\"],\n run: (runId: string) => [\"runs\", runId],\n runsAggregated: () => [\"runs_aggregated\"],\n flag: () => [\"flag\"],\n instanceInfo: () => [\"instance_info\"],\n user: () => [\"user\"],\n};\n","let apiUrl = process.env.NEXT_PUBLIC_API_URL;\napiUrl ??= typeof window !== \"undefined\" ? window.location.origin : \"\";\n\nexport const PUBLIC_API_URL = apiUrl;\n\nlet cloudWebUrl = process.env.NEXT_PUBLIC_CLOUD_WEB_URL;\ncloudWebUrl ??= \"https://cloud.datarecce.io\";\n\nexport const PUBLIC_CLOUD_WEB_URL = cloudWebUrl;\n","import { QueryClient } from \"@tanstack/react-query\";\nimport axios from \"axios\";\nimport { PUBLIC_API_URL } from \"@/lib/const\";\n\nexport const axiosClient = axios.create({\n baseURL: PUBLIC_API_URL,\n});\n\nexport const reactQueryClient = new QueryClient();\n","import { AxiosResponse } from \"axios\";\nimport { axiosClient } from \"./axiosClient\";\n\nexport interface RecceInstanceInfo {\n server_mode: \"server\" | \"preview\" | \"read-only\";\n single_env: boolean;\n authed: boolean;\n cloud_instance: boolean;\n lifetime_expired_at?: Date;\n idle_timeout?: number;\n share_url?: string;\n session_id?: string;\n organization_name?: string;\n web_url?: string;\n}\n\nexport async function getRecceInstanceInfo(): Promise<RecceInstanceInfo> {\n return (\n await axiosClient.get<never, AxiosResponse<RecceInstanceInfo>>(\n \"/api/instance-info\",\n )\n ).data;\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { cacheKeys } from \"../api/cacheKeys\";\nimport { getRecceInstanceInfo, RecceInstanceInfo } from \"../api/instanceInfo\";\n\nexport const useRecceInstanceInfo = () => {\n return useQuery<RecceInstanceInfo>({\n queryKey: cacheKeys.instanceInfo(),\n queryFn: getRecceInstanceInfo,\n });\n};\n","\"use client\";\n\nimport Alert from \"@mui/material/Alert\";\nimport CircularProgress from \"@mui/material/CircularProgress\";\nimport Snackbar from \"@mui/material/Snackbar\";\nimport Stack from \"@mui/material/Stack\";\nimport Typography from \"@mui/material/Typography\";\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from \"react\";\n\n/**\n * Toast types and interfaces\n */\nexport interface ToastOptions {\n id?: string;\n title?: string;\n description?: ReactNode;\n type?: \"success\" | \"error\" | \"warning\" | \"info\" | \"loading\";\n duration?: number;\n closable?: boolean;\n action?: {\n label: string;\n onClick: () => void;\n };\n}\n\ninterface ToastState extends ToastOptions {\n id: string;\n open: boolean;\n}\n\ninterface ToasterContextValue {\n toast: (options: ToastOptions) => string;\n success: (options: Omit<ToastOptions, \"type\">) => string;\n error: (options: Omit<ToastOptions, \"type\">) => string;\n warning: (options: Omit<ToastOptions, \"type\">) => string;\n info: (options: Omit<ToastOptions, \"type\">) => string;\n loading: (options: Omit<ToastOptions, \"type\">) => string;\n dismiss: (id: string) => void;\n update: (id: string, options: Partial<ToastOptions>) => void;\n}\n\nconst ToasterContext = createContext<ToasterContextValue | null>(null);\n\nlet toastIdCounter = 0;\n\n/**\n * Simple toaster implementation using MUI Snackbar\n */\nexport function ToasterProvider({ children }: { children: ReactNode }) {\n const [toasts, setToasts] = useState<ToastState[]>([]);\n\n const createToast = useCallback((options: ToastOptions): string => {\n const id = options.id || `toast-${++toastIdCounter}`;\n const newToast: ToastState = {\n id,\n open: true,\n duration: options.type === \"loading\" ? null : (options.duration ?? 5000),\n closable: options.closable ?? true,\n ...options,\n } as ToastState;\n\n setToasts((prev) => {\n // Remove existing toast with same id\n const filtered = prev.filter((t) => t.id !== id);\n return [...filtered, newToast];\n });\n\n return id;\n }, []);\n\n const dismiss = useCallback((id: string) => {\n setToasts((prev) =>\n prev.map((t) => (t.id === id ? { ...t, open: false } : t)),\n );\n // Remove after animation\n setTimeout(() => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, 300);\n }, []);\n\n const update = useCallback((id: string, options: Partial<ToastOptions>) => {\n setToasts((prev) =>\n prev.map((t) => (t.id === id ? { ...t, ...options } : t)),\n );\n }, []);\n\n const contextValue: ToasterContextValue = {\n toast: createToast,\n success: (opts) => createToast({ ...opts, type: \"success\" }),\n error: (opts) => createToast({ ...opts, type: \"error\" }),\n warning: (opts) => createToast({ ...opts, type: \"warning\" }),\n info: (opts) => createToast({ ...opts, type: \"info\" }),\n loading: (opts) => createToast({ ...opts, type: \"loading\" }),\n dismiss,\n update,\n };\n\n return (\n <ToasterContext.Provider value={contextValue}>\n {children}\n {toasts.map((toast) => (\n <Snackbar\n key={toast.id}\n open={toast.open}\n autoHideDuration={toast.duration}\n onClose={() => toast.closable && dismiss(toast.id)}\n anchorOrigin={{ vertical: \"bottom\", horizontal: \"right\" }}\n >\n <Alert\n severity={toast.type === \"loading\" ? \"info\" : toast.type || \"info\"}\n onClose={toast.closable ? () => dismiss(toast.id) : undefined}\n icon={\n toast.type === \"loading\" ? (\n <CircularProgress size={20} color=\"inherit\" />\n ) : undefined\n }\n sx={{ width: \"100%\", minWidth: 300 }}\n >\n <Stack spacing={0.5}>\n {toast.title && (\n <Typography variant=\"subtitle2\" fontWeight=\"bold\">\n {toast.title}\n </Typography>\n )}\n {toast.description && (\n <Typography variant=\"body2\" component=\"div\">\n {toast.description}\n </Typography>\n )}\n </Stack>\n </Alert>\n </Snackbar>\n ))}\n </ToasterContext.Provider>\n );\n}\n\n/**\n * Hook to use the toaster\n */\nexport function useToaster(): ToasterContextValue {\n const context = useContext(ToasterContext);\n if (!context) {\n throw new Error(\"useToaster must be used within ToasterProvider\");\n }\n return context;\n}\n\n/**\n * Standalone toaster instance for use outside React context\n * Uses a simple event-based system\n */\ninterface ToastEvent {\n type: \"create\" | \"dismiss\" | \"update\";\n options?: ToastOptions;\n id?: string;\n}\n\nconst listeners: Set<(event: ToastEvent) => void> = new Set();\n\nexport const toaster = {\n create: (options: ToastOptions): string => {\n const id = options.id || `toast-${++toastIdCounter}`;\n listeners.forEach((listener) =>\n listener({ type: \"create\", options: { ...options, id } }),\n );\n return id;\n },\n success: (options: Omit<ToastOptions, \"type\">) =>\n toaster.create({ ...options, type: \"success\" }),\n error: (options: Omit<ToastOptions, \"type\">) =>\n toaster.create({ ...options, type: \"error\" }),\n warning: (options: Omit<ToastOptions, \"type\">) =>\n toaster.create({ ...options, type: \"warning\" }),\n info: (options: Omit<ToastOptions, \"type\">) =>\n toaster.create({ ...options, type: \"info\" }),\n loading: (options: Omit<ToastOptions, \"type\">) =>\n toaster.create({ ...options, type: \"loading\" }),\n dismiss: (id: string) => {\n listeners.forEach((listener) => listener({ type: \"dismiss\", id }));\n },\n // Alias for dismiss (for backward compatibility)\n remove: (id: string) => {\n listeners.forEach((listener) => listener({ type: \"dismiss\", id }));\n },\n update: (id: string, options: Partial<ToastOptions>) => {\n listeners.forEach((listener) => listener({ type: \"update\", id, options }));\n },\n subscribe: (listener: (event: ToastEvent) => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n};\n\n/**\n * Toaster component that renders toasts from the standalone toaster\n */\nexport function Toaster() {\n const [toasts, setToasts] = useState<ToastState[]>([]);\n\n // Subscribe to toast events\n useState(() => {\n const unsubscribe = toaster.subscribe((event) => {\n if (event.type === \"create\" && event.options) {\n const newToast: ToastState = {\n id: event.options.id || `toast-${++toastIdCounter}`,\n open: true,\n duration:\n event.options.type === \"loading\"\n ? undefined\n : (event.options.duration ?? 5000),\n closable: event.options.closable ?? true,\n ...event.options,\n } as ToastState;\n setToasts((prev) => {\n const filtered = prev.filter((t) => t.id !== newToast.id);\n return [...filtered, newToast];\n });\n } else if (event.type === \"dismiss\" && event.id) {\n const id = event.id;\n setToasts((prev) =>\n prev.map((t) => (t.id === id ? { ...t, open: false } : t)),\n );\n setTimeout(() => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, 300);\n } else if (event.type === \"update\" && event.id && event.options) {\n setToasts((prev) =>\n prev.map((t) => (t.id === event.id ? { ...t, ...event.options } : t)),\n );\n }\n });\n return unsubscribe;\n });\n\n const handleClose = (id: string) => {\n setToasts((prev) =>\n prev.map((t) => (t.id === id ? { ...t, open: false } : t)),\n );\n setTimeout(() => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, 300);\n };\n\n return (\n <>\n {toasts.map((toast) => (\n <Snackbar\n key={toast.id}\n open={toast.open}\n autoHideDuration={toast.duration}\n onClose={() => toast.closable && handleClose(toast.id)}\n anchorOrigin={{ vertical: \"bottom\", horizontal: \"right\" }}\n >\n <Alert\n severity={toast.type === \"loading\" ? \"info\" : toast.type || \"info\"}\n onClose={toast.closable ? () => handleClose(toast.id) : undefined}\n icon={\n toast.type === \"loading\" ? (\n <CircularProgress size={20} color=\"inherit\" />\n ) : undefined\n }\n sx={{ width: \"100%\", minWidth: 300 }}\n >\n <Stack spacing={0.5}>\n {toast.title && (\n <Typography variant=\"subtitle2\" fontWeight=\"bold\">\n {toast.title}\n </Typography>\n )}\n {toast.description && (\n <Typography variant=\"body2\" component=\"div\">\n {toast.description}\n </Typography>\n )}\n </Stack>\n </Alert>\n </Snackbar>\n ))}\n </>\n );\n}\n","import { toaster } from \"@/components/ui/toaster\";\n\nexport function useCheckToast() {\n function markedAsApprovedToast() {\n toaster.create({\n title: \"Marked as approved\",\n type: \"success\",\n duration: 2000,\n });\n }\n return {\n markedAsApprovedToast,\n };\n}\n","import { toaster } from \"@/components/ui/toaster\";\n\nexport function useClipBoardToast() {\n function successToast(message: string) {\n toaster.create({\n description: message,\n type: \"info\",\n duration: 5000,\n closable: true,\n });\n }\n\n function failToast(title: string, error: unknown) {\n toaster.create({\n title: title,\n description: String(error),\n type: \"error\",\n duration: 5000,\n closable: true,\n });\n }\n\n return {\n successToast,\n failToast,\n };\n}\n","import React, { createContext, useContext } from \"react\";\nimport { CllInput, ColumnLineageData } from \"@/lib/api/cll\";\nimport { LineageDiffViewOptions } from \"@/lib/api/lineagecheck\";\nimport { Run } from \"@/lib/api/types\";\nimport { LineageGraphNode, LineageGraphNodes } from \"./lineage\";\n\ntype NewType = LineageDiffViewOptions;\ntype ActionMode = \"per_node\" | \"multi_nodes\";\n\ninterface NodeAction {\n mode: ActionMode;\n status?: \"pending\" | \"running\" | \"success\" | \"failure\" | \"skipped\";\n skipReason?: string;\n run?: Run;\n}\n\nexport interface ActionState {\n mode: ActionMode;\n status: \"pending\" | \"running\" | \"canceling\" | \"canceled\" | \"completed\";\n currentRun?: Partial<Run>;\n completed: number;\n total: number;\n actions: Record<string, NodeAction>;\n}\n\nexport interface LineageViewContextType {\n interactive: boolean;\n nodes: LineageGraphNodes[];\n focusedNode?: LineageGraphNode;\n selectedNodes: LineageGraphNode[];\n cll: ColumnLineageData | undefined;\n\n // context menu\n showContextMenu: (event: React.MouseEvent, node: LineageGraphNodes) => void;\n\n // filter\n viewOptions: LineageDiffViewOptions;\n onViewOptionsChanged: (options: NewType) => void;\n\n // Multi nodes selection\n selectMode: \"selecting\" | \"action_result\" | undefined;\n selectNode: (nodeId: string) => void;\n selectParentNodes: (nodeId: string, degree?: number) => void;\n selectChildNodes: (nodeId: string, degree?: number) => void;\n deselect: () => void;\n\n // node state\n isNodeHighlighted: (nodeId: string) => boolean;\n isNodeSelected: (nodeId: string) => boolean;\n isEdgeHighlighted: (source: string, target: string) => boolean;\n getNodeAction: (nodeId: string) => NodeAction;\n getNodeColumnSet: (nodeId: string) => Set<string>;\n isNodeShowingChangeAnalysis: (nodeId: string) => boolean;\n\n //actions\n runRowCount: () => Promise<void>;\n runRowCountDiff: () => Promise<void>;\n runValueDiff: () => Promise<void>;\n addLineageDiffCheck: (viewMode?: string) => void;\n addSchemaDiffCheck: () => void;\n cancel: () => void;\n actionState: ActionState;\n\n // Column Level Lineage\n centerNode: (nodeId: string) => void;\n showColumnLevelLineage: (cll?: CllInput) => Promise<void>;\n resetColumnLevelLineage: (previous?: boolean) => Promise<void>;\n}\n\nexport const LineageViewContext = createContext<\n LineageViewContextType | undefined\n>(undefined);\n\nexport const useLineageViewContextSafe = (): LineageViewContextType => {\n const context = useContext(LineageViewContext);\n if (!context) {\n throw new Error(\n \"useLineageViewContext must be used within a LineageViewProvider\",\n );\n }\n return context;\n};\n\nexport const useLineageViewContext = (): LineageViewContextType | undefined => {\n return useContext(LineageViewContext);\n};\n","import {\n AmplitudeReturn,\n BaseEvent,\n EventOptions,\n Result,\n} from \"@amplitude/analytics-core\";\nimport { initAll, track as trk } from \"@amplitude/unified\";\n\nfunction track(\n eventInput: string | BaseEvent,\n // biome-ignore lint/suspicious/noExplicitAny: Amplitude library uses any for event properties\n eventProperties?: Record<string, any> | undefined,\n eventOptions?: EventOptions | undefined,\n): AmplitudeReturn<Result> {\n // If Amplitude isn't initialized, log to console instead\n if (!amplitudeInitialized) {\n console.log(\"[Tracking]\", eventInput, eventProperties, eventOptions);\n }\n return trk(eventInput, eventProperties, eventOptions);\n}\n\nlet amplitudeInitialized = false;\n\nexport function trackInit() {\n function getCookie(key: string) {\n const b = document.cookie.match(\"(^|;)\\\\s*\" + key + \"\\\\s*=\\\\s*([^;]+)\");\n return b ? b.pop() : \"\";\n }\n\n const userId =\n process.env.NODE_ENV === \"development\"\n ? \"web_dev\"\n : getCookie(\"recce_user_id\");\n const apiKey = process.env.AMPLITUDE_API_KEY;\n if (userId && apiKey) {\n try {\n void initAll(apiKey, {\n analytics: {\n userId,\n autocapture: true,\n },\n sessionReplay: {\n sampleRate: 1,\n },\n });\n amplitudeInitialized = true;\n } catch (e) {\n console.error(e);\n }\n }\n\n // Log when Amplitude is not initialized (for development/debugging)\n if (!amplitudeInitialized) {\n console.log(\n \"[Tracking] Amplitude not initialized (missing API key or user ID). Events will be logged to console instead.\",\n );\n }\n}\n\ninterface MultiNodeActionProps {\n type:\n | \"row_count\"\n | \"row_count_diff\"\n | \"value_diff\"\n | \"schema_diff\"\n | \"lineage_diff\";\n selected: \"single\" | \"multi\" | \"none\";\n}\n\nexport function trackMultiNodesAction(props: MultiNodeActionProps) {\n track(\"[Web] multi_nodes_action\", props);\n}\n\ninterface HistoryActionProps {\n name: \"show\" | \"hide\" | \"click_run\" | \"add_to_checklist\" | \"go_to_check\";\n}\n\nexport function trackHistoryAction(props: HistoryActionProps) {\n track(\"[Web] history_action\", props);\n}\n\ninterface PreviewChangeProps {\n action: \"explore\" | \"run\" | \"close\";\n node?: string;\n status?: \"success\" | \"failure\";\n}\n\nexport function trackPreviewChange(props: PreviewChangeProps) {\n track(\"[Experiment] preview_change\", props);\n}\n\ninterface PreviewChangeFeedbackProps {\n feedback: \"like\" | \"dislike\" | \"form\";\n node?: string;\n}\n\nexport function trackPreviewChangeFeedback(props: PreviewChangeFeedbackProps) {\n track(\"[Experiment] preview_change\", props);\n}\n\ninterface SingleEnvironmentProps {\n action:\n | \"onboarding\"\n | \"external_link\"\n | \"preview_changes\"\n | `target_base_added`;\n from?: \"onboarding\" | \"preview_changes\";\n node?: string;\n}\n\nexport function trackSingleEnvironment(props: SingleEnvironmentProps) {\n track(\"[Experiment] single_environment\", props);\n}\n\nexport function getExperimentTrackingBreakingChangeEnabled() {\n return false;\n}\n\ninterface ColumnLevelLineageProps {\n action: \"view\";\n source: \"schema_column\" | \"changed_column\" | \"cll_column\";\n}\n\nexport function trackColumnLevelLineage(props: ColumnLevelLineageProps) {\n track(\"[Web] column_level_lineage\", props);\n}\n\ninterface ShareStateProps {\n name: \"enable\" | \"create\" | \"copy\";\n}\n\nexport function trackShareState(props: ShareStateProps) {\n track(\"[Web] share_state\", props);\n}\n\ninterface StateActionProps {\n name: \"import\" | \"export\";\n}\n\nexport function trackStateAction(props: StateActionProps) {\n track(\"[Web] state_action\", props);\n}\n\ninterface CopyToClipboardProps {\n from: \"run\" | \"check\" | \"lineage_view\";\n type: string;\n}\n\nexport function trackCopyToClipboard(props: CopyToClipboardProps) {\n track(\"[Click] copy_to_clipboard\", props);\n}\n\ninterface TrackNavProps {\n from: string;\n to: string;\n}\n\nexport function trackNavigation(props: TrackNavProps) {\n track(\"[Web] navigation_change\", props);\n}\n\nexport interface LineageViewRenderProps {\n node_count: number;\n view_mode: string;\n impact_radius_enabled: boolean;\n cll_column_active?: boolean;\n right_sidebar_open: boolean;\n [status: string]: number | string | boolean | undefined;\n}\n\nexport function trackLineageViewRender(props: LineageViewRenderProps) {\n track(\"[Web] lineage_view_render\", props);\n}\n\nexport interface EnvironmentConfigProps {\n review_mode: boolean;\n adapter_type: string | null;\n has_git_info: boolean;\n has_pr_info: boolean;\n // Adapter-specific (shape varies by adapter_type)\n base?: {\n schema_count?: number;\n dbt_version?: string | null;\n timestamp?: string | null;\n has_env?: boolean;\n };\n current?: {\n schema_count?: number;\n dbt_version?: string | null;\n timestamp?: string | null;\n has_env?: boolean;\n };\n schemas_match?: boolean;\n}\n\nexport function trackEnvironmentConfig(props: EnvironmentConfigProps) {\n track(\"[Web] environment_config\", props);\n}\n\n// Explore action types\nexport const EXPLORE_ACTION = {\n ROW_COUNT: \"row_count\",\n ROW_COUNT_DIFF: \"row_count_diff\",\n PROFILE: \"profile\",\n PROFILE_DIFF: \"profile_diff\",\n VALUE_DIFF: \"value_diff\",\n SCHEMA_DIFF: \"schema_diff\",\n LINEAGE_DIFF: \"lineage_diff\",\n QUERY: \"query\",\n HISTOGRAM_DIFF: \"histogram_diff\",\n TOP_K_DIFF: \"top_k_diff\",\n} as const;\n\n// Explore action sources\nexport const EXPLORE_SOURCE = {\n LINEAGE_VIEW_TOP_BAR: \"lineage_view_top_bar\",\n LINEAGE_VIEW_CONTEXT_MENU: \"lineage_view_context_menu\",\n NODE_KEBAB_MENU: \"node_kebab_menu\",\n NODE_SIDEBAR_SINGLE_ENV: \"node_sidebar_single_env\",\n NODE_SIDEBAR_MULTI_ENV: \"node_sidebar_multi_env\",\n SCHEMA_ROW_COUNT_BUTTON: \"schema_row_count_button\",\n SCHEMA_COLUMN_MENU: \"schema_column_menu\",\n} as const;\n\nexport type ExploreActionType =\n (typeof EXPLORE_ACTION)[keyof typeof EXPLORE_ACTION];\nexport type ExploreSourceType =\n (typeof EXPLORE_SOURCE)[keyof typeof EXPLORE_SOURCE];\n\ninterface ExploreActionProps {\n action: ExploreActionType;\n source: ExploreSourceType;\n node_count?: number;\n}\n\nexport function trackExploreAction(props: ExploreActionProps) {\n track(\"[Web] explore_action\", props);\n}\n\n// Explore action form events\nexport const EXPLORE_FORM_EVENT = {\n EXECUTE: \"execute\",\n CANCEL: \"cancel\",\n} as const;\n\nexport type ExploreFormEventType =\n (typeof EXPLORE_FORM_EVENT)[keyof typeof EXPLORE_FORM_EVENT];\n\ninterface ExploreActionFormProps {\n action: ExploreActionType;\n event: ExploreFormEventType;\n}\n\nexport function trackExploreActionForm(props: ExploreActionFormProps) {\n track(\"[Web] explore_action_form\", props);\n}\n\n// Helper to check if a run type is an explore action\nexport function isExploreAction(type: string): type is ExploreActionType {\n return Object.values(EXPLORE_ACTION).includes(type as ExploreActionType);\n}\n\n// Lineage selection action types\nexport const LINEAGE_SELECTION_ACTION = {\n SELECT_PARENT_NODES: \"select_parent_nodes\",\n SELECT_CHILD_NODES: \"select_child_nodes\",\n SELECT_ALL_UPSTREAM: \"select_all_upstream\",\n SELECT_ALL_DOWNSTREAM: \"select_all_downstream\",\n} as const;\n\nexport type LineageSelectionActionType =\n (typeof LINEAGE_SELECTION_ACTION)[keyof typeof LINEAGE_SELECTION_ACTION];\n\ninterface LineageSelectionProps {\n action: LineageSelectionActionType;\n node_count?: number;\n}\n\nexport function trackLineageSelection(props: LineageSelectionProps) {\n track(\"[Web] lineage_selection\", props);\n}\n","import Box from \"@mui/material/Box\";\nimport Button from \"@mui/material/Button\";\nimport MuiDialog from \"@mui/material/Dialog\";\nimport DialogActions from \"@mui/material/DialogActions\";\nimport DialogContent from \"@mui/material/DialogContent\";\nimport DialogTitle from \"@mui/material/DialogTitle\";\nimport IconButton from \"@mui/material/IconButton\";\nimport Stack from \"@mui/material/Stack\";\nimport React, { useCallback, useRef, useState } from \"react\";\nimport { IoClose } from \"react-icons/io5\";\nimport {\n EXPLORE_ACTION,\n EXPLORE_FORM_EVENT,\n trackExploreActionForm,\n} from \"@/lib/api/track\";\n\nfunction useValueDiffAlertDialog() {\n const [open, setOpen] = useState(false);\n const [nodeCount, setNodeCount] = useState(0);\n const [resolvePromise, setResolvePromise] =\n useState<(value: boolean) => void>();\n const cancelRef = useRef<HTMLButtonElement>(null);\n\n const confirm = useCallback((nodeCount: number) => {\n setNodeCount(nodeCount);\n return new Promise<boolean>((resolve) => {\n setResolvePromise(() => resolve);\n setOpen(true);\n });\n }, []);\n\n const handleConfirm = () => {\n trackExploreActionForm({\n action: EXPLORE_ACTION.VALUE_DIFF,\n event: EXPLORE_FORM_EVENT.EXECUTE,\n });\n resolvePromise?.(true);\n setOpen(false);\n };\n\n const handleCancel = () => {\n trackExploreActionForm({\n action: EXPLORE_ACTION.VALUE_DIFF,\n event: EXPLORE_FORM_EVENT.CANCEL,\n });\n resolvePromise?.(false);\n setOpen(false);\n };\n\n const ValueDiffAlertDialog = (\n <MuiDialog\n open={open}\n onClose={handleCancel}\n maxWidth=\"md\"\n fullWidth\n aria-labelledby=\"value-diff-alert-dialog-title\"\n >\n <DialogTitle\n id=\"value-diff-alert-dialog-title\"\n sx={{ fontSize: \"1.125rem\", fontWeight: \"bold\" }}\n >\n Value Diff on {nodeCount} nodes\n </DialogTitle>\n <IconButton\n aria-label=\"close\"\n onClick={handleCancel}\n sx={{\n position: \"absolute\",\n right: 8,\n top: 8,\n color: \"grey.500\",\n }}\n >\n <IoClose />\n </IconButton>\n <DialogContent>\n <Stack spacing=\"20px\">\n <Box>\n Value diff will be executed on {nodeCount} nodes in the Lineage,\n which can add extra costs to your bill.\n </Box>\n </Stack>\n </DialogContent>\n <DialogActions sx={{ gap: 0.5 }}>\n <Button\n ref={cancelRef}\n onClick={handleCancel}\n variant=\"outlined\"\n color=\"neutral\"\n >\n Cancel\n </Button>\n <Button\n color=\"iochmara\"\n variant=\"contained\"\n onClick={handleConfirm}\n sx={{ ml: 1.5 }}\n >\n Execute\n </Button>\n </DialogActions>\n </MuiDialog>\n );\n\n return { confirm, AlertDialog: ValueDiffAlertDialog };\n}\n\nexport default useValueDiffAlertDialog;\n"]}
package/dist/hooks.mjs CHANGED
@@ -1,8 +1,20 @@
1
1
  import { QueryClient, useQuery } from '@tanstack/react-query';
2
2
  import axios from 'axios';
3
- import { createToaster, useDisclosure, Dialog, Portal, Flex, Box, Button, CloseButton } from '@chakra-ui/react';
4
- import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import '@mui/material/Alert';
4
+ import '@mui/material/CircularProgress';
5
+ import '@mui/material/Snackbar';
6
+ import Stack2 from '@mui/material/Stack';
7
+ import '@mui/material/Typography';
5
8
  import { createContext, useContext, useState, useRef, useCallback } from 'react';
9
+ import { jsxs, jsx } from 'react/jsx-runtime';
10
+ import Box from '@mui/material/Box';
11
+ import Button from '@mui/material/Button';
12
+ import MuiDialog from '@mui/material/Dialog';
13
+ import DialogActions from '@mui/material/DialogActions';
14
+ import DialogContent from '@mui/material/DialogContent';
15
+ import DialogTitle from '@mui/material/DialogTitle';
16
+ import IconButton from '@mui/material/IconButton';
17
+ import { IoClose } from 'react-icons/io5';
6
18
  import { track as track$1 } from '@amplitude/unified';
7
19
 
8
20
  // recce-source/js/src/lib/api/cacheKeys.ts
@@ -46,10 +58,37 @@ var useRecceInstanceInfo = () => {
46
58
  queryFn: getRecceInstanceInfo
47
59
  });
48
60
  };
49
- var toaster = createToaster({
50
- placement: "bottom-end",
51
- pauseOnPageIdle: true
52
- });
61
+ createContext(null);
62
+ var toastIdCounter = 0;
63
+ var listeners = /* @__PURE__ */ new Set();
64
+ var toaster = {
65
+ create: (options) => {
66
+ const id = options.id || `toast-${++toastIdCounter}`;
67
+ listeners.forEach(
68
+ (listener) => listener({ type: "create", options: { ...options, id } })
69
+ );
70
+ return id;
71
+ },
72
+ success: (options) => toaster.create({ ...options, type: "success" }),
73
+ error: (options) => toaster.create({ ...options, type: "error" }),
74
+ warning: (options) => toaster.create({ ...options, type: "warning" }),
75
+ info: (options) => toaster.create({ ...options, type: "info" }),
76
+ loading: (options) => toaster.create({ ...options, type: "loading" }),
77
+ dismiss: (id) => {
78
+ listeners.forEach((listener) => listener({ type: "dismiss", id }));
79
+ },
80
+ // Alias for dismiss (for backward compatibility)
81
+ remove: (id) => {
82
+ listeners.forEach((listener) => listener({ type: "dismiss", id }));
83
+ },
84
+ update: (id, options) => {
85
+ listeners.forEach((listener) => listener({ type: "update", id, options }));
86
+ },
87
+ subscribe: (listener) => {
88
+ listeners.add(listener);
89
+ return () => listeners.delete(listener);
90
+ }
91
+ };
53
92
 
54
93
  // recce-source/js/src/lib/hooks/useCheckToast.tsx
55
94
  function useCheckToast() {
@@ -109,27 +148,24 @@ function trackExploreActionForm(props) {
109
148
  track("[Web] explore_action_form", props);
110
149
  }
111
150
  function useValueDiffAlertDialog() {
112
- const { open, onOpen, onClose } = useDisclosure();
151
+ const [open, setOpen] = useState(false);
113
152
  const [nodeCount, setNodeCount] = useState(0);
114
153
  const [resolvePromise, setResolvePromise] = useState();
115
154
  const cancelRef = useRef(null);
116
- const confirm = useCallback(
117
- (nodeCount2) => {
118
- setNodeCount(nodeCount2);
119
- return new Promise((resolve) => {
120
- setResolvePromise(() => resolve);
121
- onOpen();
122
- });
123
- },
124
- [onOpen]
125
- );
155
+ const confirm = useCallback((nodeCount2) => {
156
+ setNodeCount(nodeCount2);
157
+ return new Promise((resolve) => {
158
+ setResolvePromise(() => resolve);
159
+ setOpen(true);
160
+ });
161
+ }, []);
126
162
  const handleConfirm = () => {
127
163
  trackExploreActionForm({
128
164
  action: EXPLORE_ACTION.VALUE_DIFF,
129
165
  event: EXPLORE_FORM_EVENT.EXECUTE
130
166
  });
131
167
  resolvePromise?.(true);
132
- onClose();
168
+ setOpen(false);
133
169
  };
134
170
  const handleCancel = () => {
135
171
  trackExploreActionForm({
@@ -137,47 +173,71 @@ function useValueDiffAlertDialog() {
137
173
  event: EXPLORE_FORM_EVENT.CANCEL
138
174
  });
139
175
  resolvePromise?.(false);
140
- onClose();
176
+ setOpen(false);
141
177
  };
142
- const ValueDiffAlertDialog = /* @__PURE__ */ jsx(
143
- Dialog.Root,
178
+ const ValueDiffAlertDialog = /* @__PURE__ */ jsxs(
179
+ MuiDialog,
144
180
  {
145
- size: "xl",
146
181
  open,
147
- role: "alertdialog",
148
- initialFocusEl: () => {
149
- return cancelRef.current;
150
- },
151
- onOpenChange: handleCancel,
152
- children: /* @__PURE__ */ jsxs(Portal, { children: [
153
- /* @__PURE__ */ jsx(Dialog.Backdrop, {}),
154
- /* @__PURE__ */ jsx(Dialog.Positioner, { children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
155
- /* @__PURE__ */ jsx(Dialog.Header, { fontSize: "lg", fontWeight: "bold", children: /* @__PURE__ */ jsxs(Dialog.Title, { children: [
156
- "Value Diff on ",
157
- nodeCount,
158
- " nodes"
159
- ] }) }),
160
- /* @__PURE__ */ jsx(Dialog.Body, { gap: "20px", as: Flex, direction: "column", children: /* @__PURE__ */ jsxs(Box, { children: [
161
- "Value diff will be executed on ",
162
- nodeCount,
163
- " nodes in the Lineage, which can add extra costs to your bill."
164
- ] }) }),
165
- /* @__PURE__ */ jsxs(Dialog.Footer, { gap: 1, children: [
166
- /* @__PURE__ */ jsx(
167
- Button,
168
- {
169
- ref: cancelRef,
170
- onClick: handleCancel,
171
- variant: "outline",
172
- colorPalette: "gray",
173
- children: "Cancel"
174
- }
175
- ),
176
- /* @__PURE__ */ jsx(Button, { colorPalette: "iochmara", onClick: handleConfirm, ml: 3, children: "Execute" })
177
- ] }),
178
- /* @__PURE__ */ jsx(Dialog.CloseTrigger, { asChild: true, children: /* @__PURE__ */ jsx(CloseButton, { size: "sm" }) })
179
- ] }) })
180
- ] })
182
+ onClose: handleCancel,
183
+ maxWidth: "md",
184
+ fullWidth: true,
185
+ "aria-labelledby": "value-diff-alert-dialog-title",
186
+ children: [
187
+ /* @__PURE__ */ jsxs(
188
+ DialogTitle,
189
+ {
190
+ id: "value-diff-alert-dialog-title",
191
+ sx: { fontSize: "1.125rem", fontWeight: "bold" },
192
+ children: [
193
+ "Value Diff on ",
194
+ nodeCount,
195
+ " nodes"
196
+ ]
197
+ }
198
+ ),
199
+ /* @__PURE__ */ jsx(
200
+ IconButton,
201
+ {
202
+ "aria-label": "close",
203
+ onClick: handleCancel,
204
+ sx: {
205
+ position: "absolute",
206
+ right: 8,
207
+ top: 8,
208
+ color: "grey.500"
209
+ },
210
+ children: /* @__PURE__ */ jsx(IoClose, {})
211
+ }
212
+ ),
213
+ /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsx(Stack2, { spacing: "20px", children: /* @__PURE__ */ jsxs(Box, { children: [
214
+ "Value diff will be executed on ",
215
+ nodeCount,
216
+ " nodes in the Lineage, which can add extra costs to your bill."
217
+ ] }) }) }),
218
+ /* @__PURE__ */ jsxs(DialogActions, { sx: { gap: 0.5 }, children: [
219
+ /* @__PURE__ */ jsx(
220
+ Button,
221
+ {
222
+ ref: cancelRef,
223
+ onClick: handleCancel,
224
+ variant: "outlined",
225
+ color: "neutral",
226
+ children: "Cancel"
227
+ }
228
+ ),
229
+ /* @__PURE__ */ jsx(
230
+ Button,
231
+ {
232
+ color: "iochmara",
233
+ variant: "contained",
234
+ onClick: handleConfirm,
235
+ sx: { ml: 1.5 },
236
+ children: "Execute"
237
+ }
238
+ )
239
+ ] })
240
+ ]
181
241
  }
182
242
  );
183
243
  return { confirm, AlertDialog: ValueDiffAlertDialog };