@prismiq/react 0.1.0 → 0.1.1
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/{CustomSQLEditor-BXB4rf1q.d.cts → CustomSQLEditor-CYlOtecq.d.ts} +10 -3
- package/dist/{CustomSQLEditor-DYeId0Gp.d.ts → CustomSQLEditor-d84v_Cgp.d.cts} +10 -3
- package/dist/{DashboardDialog-LHmrtNQU.d.cts → DashboardDialog-CZD8I-6z.d.cts} +4 -4
- package/dist/{DashboardDialog-B3vYC5Gs.d.ts → DashboardDialog-DBNTVVSp.d.ts} +4 -4
- package/dist/{accessibility-2yy5yqRR.d.cts → accessibility-Bu2mNtaB.d.cts} +1 -1
- package/dist/{accessibility-2yy5yqRR.d.ts → accessibility-Bu2mNtaB.d.ts} +1 -1
- package/dist/charts/index.cjs +27 -27
- package/dist/charts/index.d.cts +2 -2
- package/dist/charts/index.d.ts +2 -2
- package/dist/charts/index.js +2 -2
- package/dist/{chunk-MOAEEF5P.js → chunk-3LDRRDJ6.js} +185 -91
- package/dist/chunk-3LDRRDJ6.js.map +1 -0
- package/dist/{chunk-NK7HKX2J.cjs → chunk-73TPDGXB.cjs} +7 -7
- package/dist/{chunk-NK7HKX2J.cjs.map → chunk-73TPDGXB.cjs.map} +1 -1
- package/dist/{chunk-UPYINBZU.js → chunk-ET7GCREP.js} +502 -46
- package/dist/chunk-ET7GCREP.js.map +1 -0
- package/dist/{chunk-2H5WTH4K.js → chunk-FQ23KG6G.js} +3 -3
- package/dist/{chunk-2H5WTH4K.js.map → chunk-FQ23KG6G.js.map} +1 -1
- package/dist/{chunk-4AVL6GQK.cjs → chunk-KXB2IZI2.cjs} +36 -9
- package/dist/chunk-KXB2IZI2.cjs.map +1 -0
- package/dist/{chunk-EX74SI67.js → chunk-LBE6GIBC.js} +36 -9
- package/dist/chunk-LBE6GIBC.js.map +1 -0
- package/dist/{chunk-NY6TZLST.cjs → chunk-URJH4H6G.cjs} +505 -49
- package/dist/chunk-URJH4H6G.cjs.map +1 -0
- package/dist/{chunk-FEABEF3J.cjs → chunk-VQDFS6VS.cjs} +374 -280
- package/dist/chunk-VQDFS6VS.cjs.map +1 -0
- package/dist/components/index.cjs +55 -55
- package/dist/components/index.d.cts +2 -2
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.js +2 -2
- package/dist/dashboard/index.cjs +36 -36
- package/dist/dashboard/index.d.cts +3 -3
- package/dist/dashboard/index.d.ts +3 -3
- package/dist/dashboard/index.js +4 -4
- package/dist/export/index.d.cts +1 -1
- package/dist/export/index.d.ts +1 -1
- package/dist/{index-C-Qcuu4Y.d.cts → index-CvKj3SWO.d.cts} +2 -2
- package/dist/{index-rPc7ijt8.d.ts → index-DXGLs1yY.d.ts} +2 -2
- package/dist/index.cjs +127 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -9
- package/dist/index.d.ts +30 -9
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/{types-WrCbOeAV.d.cts → types-j0kPJ9Hz.d.cts} +16 -1
- package/dist/{types-WrCbOeAV.d.ts → types-j0kPJ9Hz.d.ts} +16 -1
- package/dist/utils/index.cjs +15 -15
- package/dist/utils/index.d.cts +5 -21
- package/dist/utils/index.d.ts +5 -21
- package/dist/utils/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-4AVL6GQK.cjs.map +0 -1
- package/dist/chunk-EX74SI67.js.map +0 -1
- package/dist/chunk-FEABEF3J.cjs.map +0 -1
- package/dist/chunk-MOAEEF5P.js.map +0 -1
- package/dist/chunk-NY6TZLST.cjs.map +0 -1
- package/dist/chunk-UPYINBZU.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTheme } from './chunk-T6STUE7E.js';
|
|
2
|
-
import { useFocusTrap, parseColumnRef } from './chunk-
|
|
2
|
+
import { useFocusTrap, parseColumnRef } from './chunk-LBE6GIBC.js';
|
|
3
3
|
import { forwardRef, useState, useRef, useCallback, useEffect, isValidElement, cloneElement, createContext, useContext, useLayoutEffect, Component, useMemo } from 'react';
|
|
4
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
@@ -2325,6 +2325,9 @@ var PrismiqClient = class {
|
|
|
2325
2325
|
}
|
|
2326
2326
|
/**
|
|
2327
2327
|
* Make an authenticated request to the API.
|
|
2328
|
+
*
|
|
2329
|
+
* @param path - API path (starting with /)
|
|
2330
|
+
* @param options - Fetch options including signal for cancellation
|
|
2328
2331
|
*/
|
|
2329
2332
|
async request(path, options = {}) {
|
|
2330
2333
|
const url = `${this.endpoint}${path}`;
|
|
@@ -2470,6 +2473,17 @@ var PrismiqClient = class {
|
|
|
2470
2473
|
const result = await this.request(path);
|
|
2471
2474
|
return result.values;
|
|
2472
2475
|
}
|
|
2476
|
+
/**
|
|
2477
|
+
* Get data source metadata including display names and descriptions.
|
|
2478
|
+
*
|
|
2479
|
+
* Returns metadata for all exposed tables/views that can be used
|
|
2480
|
+
* to show user-friendly names in the UI instead of raw table names.
|
|
2481
|
+
*
|
|
2482
|
+
* @returns Array of data source metadata.
|
|
2483
|
+
*/
|
|
2484
|
+
async getDataSources() {
|
|
2485
|
+
return this.request("/data-sources");
|
|
2486
|
+
}
|
|
2473
2487
|
// ============================================================================
|
|
2474
2488
|
// Query Methods
|
|
2475
2489
|
// ============================================================================
|
|
@@ -2503,12 +2517,14 @@ var PrismiqClient = class {
|
|
|
2503
2517
|
*
|
|
2504
2518
|
* @param query - The query definition to execute.
|
|
2505
2519
|
* @param bypassCache - If true, bypass cache and re-execute query.
|
|
2520
|
+
* @param signal - Optional AbortSignal for cancellation.
|
|
2506
2521
|
* @returns The query result with all rows and cache metadata.
|
|
2507
2522
|
*/
|
|
2508
|
-
async executeQuery(query, bypassCache = false) {
|
|
2523
|
+
async executeQuery(query, bypassCache = false, signal) {
|
|
2509
2524
|
return this.request("/query/execute", {
|
|
2510
2525
|
method: "POST",
|
|
2511
|
-
body: JSON.stringify({ query, bypass_cache: bypassCache })
|
|
2526
|
+
body: JSON.stringify({ query, bypass_cache: bypassCache }),
|
|
2527
|
+
signal
|
|
2512
2528
|
});
|
|
2513
2529
|
}
|
|
2514
2530
|
/**
|
|
@@ -2861,6 +2877,7 @@ function AnalyticsProvider({
|
|
|
2861
2877
|
}
|
|
2862
2878
|
const client = clientRef.current;
|
|
2863
2879
|
const [schema, setSchema] = useState(null);
|
|
2880
|
+
const [dataSources, setDataSources] = useState([]);
|
|
2864
2881
|
const [isLoading, setIsLoading] = useState(true);
|
|
2865
2882
|
const [error, setError] = useState(null);
|
|
2866
2883
|
const hasFetchedSchemaRef = useRef(false);
|
|
@@ -2878,8 +2895,13 @@ function AnalyticsProvider({
|
|
|
2878
2895
|
setIsLoading(true);
|
|
2879
2896
|
setError(null);
|
|
2880
2897
|
try {
|
|
2881
|
-
const fetchedSchema = await
|
|
2898
|
+
const [fetchedSchema, fetchedDataSources] = await Promise.all([
|
|
2899
|
+
client.getSchema(),
|
|
2900
|
+
client.getDataSources().catch(() => [])
|
|
2901
|
+
// Non-critical, fallback to empty
|
|
2902
|
+
]);
|
|
2882
2903
|
setSchema(fetchedSchema);
|
|
2904
|
+
setDataSources(fetchedDataSources);
|
|
2883
2905
|
onSchemaLoadRef.current?.(fetchedSchema);
|
|
2884
2906
|
} catch (err) {
|
|
2885
2907
|
const schemaError = err instanceof Error ? err : new Error(String(err));
|
|
@@ -2901,6 +2923,7 @@ function AnalyticsProvider({
|
|
|
2901
2923
|
() => ({
|
|
2902
2924
|
client,
|
|
2903
2925
|
schema,
|
|
2926
|
+
dataSources,
|
|
2904
2927
|
isLoading,
|
|
2905
2928
|
error,
|
|
2906
2929
|
refetchSchema,
|
|
@@ -2908,7 +2931,7 @@ function AnalyticsProvider({
|
|
|
2908
2931
|
userId,
|
|
2909
2932
|
schemaName
|
|
2910
2933
|
}),
|
|
2911
|
-
[client, schema, isLoading, error, refetchSchema, tenantId, userId, schemaName]
|
|
2934
|
+
[client, schema, dataSources, isLoading, error, refetchSchema, tenantId, userId, schemaName]
|
|
2912
2935
|
);
|
|
2913
2936
|
const callbacks = useMemo(
|
|
2914
2937
|
() => ({
|
|
@@ -2929,22 +2952,44 @@ function useAnalytics() {
|
|
|
2929
2952
|
return context;
|
|
2930
2953
|
}
|
|
2931
2954
|
function useSchema() {
|
|
2932
|
-
const { schema, isLoading, error } = useAnalytics();
|
|
2955
|
+
const { schema, dataSources, isLoading, error } = useAnalytics();
|
|
2933
2956
|
const tables = useMemo(() => schema?.tables ?? [], [schema]);
|
|
2934
2957
|
const relationships = useMemo(() => schema?.relationships ?? [], [schema]);
|
|
2958
|
+
const dataSourceMap = useMemo(() => {
|
|
2959
|
+
const map = /* @__PURE__ */ new Map();
|
|
2960
|
+
for (const ds of dataSources) {
|
|
2961
|
+
map.set(ds.table, ds);
|
|
2962
|
+
}
|
|
2963
|
+
return map;
|
|
2964
|
+
}, [dataSources]);
|
|
2935
2965
|
const getTable = useCallback(
|
|
2936
2966
|
(name) => {
|
|
2937
2967
|
return tables.find((table) => table.name === name);
|
|
2938
2968
|
},
|
|
2939
2969
|
[tables]
|
|
2940
2970
|
);
|
|
2971
|
+
const getDisplayName = useCallback(
|
|
2972
|
+
(tableName) => {
|
|
2973
|
+
return dataSourceMap.get(tableName)?.title ?? tableName;
|
|
2974
|
+
},
|
|
2975
|
+
[dataSourceMap]
|
|
2976
|
+
);
|
|
2977
|
+
const getDescription = useCallback(
|
|
2978
|
+
(tableName) => {
|
|
2979
|
+
return dataSourceMap.get(tableName)?.subtitle ?? "";
|
|
2980
|
+
},
|
|
2981
|
+
[dataSourceMap]
|
|
2982
|
+
);
|
|
2941
2983
|
return {
|
|
2942
2984
|
schema,
|
|
2943
2985
|
tables,
|
|
2944
2986
|
relationships,
|
|
2987
|
+
dataSources,
|
|
2945
2988
|
isLoading,
|
|
2946
2989
|
error,
|
|
2947
|
-
getTable
|
|
2990
|
+
getTable,
|
|
2991
|
+
getDisplayName,
|
|
2992
|
+
getDescription
|
|
2948
2993
|
};
|
|
2949
2994
|
}
|
|
2950
2995
|
function queryEquals(a, b) {
|
|
@@ -4833,6 +4878,29 @@ var containerStyles7 = {
|
|
|
4833
4878
|
gap: "var(--prismiq-spacing-xs)",
|
|
4834
4879
|
flex: 1
|
|
4835
4880
|
};
|
|
4881
|
+
var comboboxContainerStyles = {
|
|
4882
|
+
position: "relative",
|
|
4883
|
+
flex: 1
|
|
4884
|
+
};
|
|
4885
|
+
var dropdownStyles2 = {
|
|
4886
|
+
position: "fixed",
|
|
4887
|
+
backgroundColor: "var(--prismiq-color-background)",
|
|
4888
|
+
border: "1px solid var(--prismiq-color-border)",
|
|
4889
|
+
borderRadius: "var(--prismiq-radius-md)",
|
|
4890
|
+
boxShadow: "var(--prismiq-shadow-md)",
|
|
4891
|
+
zIndex: 1e3,
|
|
4892
|
+
maxHeight: "200px",
|
|
4893
|
+
overflow: "auto"
|
|
4894
|
+
};
|
|
4895
|
+
var optionStyles2 = {
|
|
4896
|
+
padding: "var(--prismiq-spacing-sm) var(--prismiq-spacing-md)",
|
|
4897
|
+
cursor: "pointer",
|
|
4898
|
+
fontSize: "var(--prismiq-font-size-sm)",
|
|
4899
|
+
transition: "background-color 0.1s"
|
|
4900
|
+
};
|
|
4901
|
+
var optionHoverStyles2 = {
|
|
4902
|
+
backgroundColor: "var(--prismiq-color-surface-hover)"
|
|
4903
|
+
};
|
|
4836
4904
|
function parseValue(value, dataType) {
|
|
4837
4905
|
if (!value) return void 0;
|
|
4838
4906
|
const type = dataType?.toLowerCase() ?? "";
|
|
@@ -4863,15 +4931,270 @@ function getInputType(dataType) {
|
|
|
4863
4931
|
}
|
|
4864
4932
|
return "text";
|
|
4865
4933
|
}
|
|
4934
|
+
function isMultiValueOperator(op) {
|
|
4935
|
+
return op === "in_" || op === "not_in" || op === "in_or_null";
|
|
4936
|
+
}
|
|
4937
|
+
var tagContainerStyles = {
|
|
4938
|
+
display: "flex",
|
|
4939
|
+
flexWrap: "wrap",
|
|
4940
|
+
alignItems: "center",
|
|
4941
|
+
gap: "4px",
|
|
4942
|
+
padding: "4px 8px",
|
|
4943
|
+
border: "1px solid var(--prismiq-color-border)",
|
|
4944
|
+
borderRadius: "var(--prismiq-radius-sm)",
|
|
4945
|
+
backgroundColor: "var(--prismiq-color-background)",
|
|
4946
|
+
minHeight: "32px",
|
|
4947
|
+
cursor: "text",
|
|
4948
|
+
flex: 1
|
|
4949
|
+
};
|
|
4950
|
+
var tagStyles = {
|
|
4951
|
+
display: "inline-flex",
|
|
4952
|
+
alignItems: "center",
|
|
4953
|
+
gap: "4px",
|
|
4954
|
+
padding: "1px 6px",
|
|
4955
|
+
backgroundColor: "var(--prismiq-color-surface)",
|
|
4956
|
+
border: "1px solid var(--prismiq-color-border)",
|
|
4957
|
+
borderRadius: "var(--prismiq-radius-sm)",
|
|
4958
|
+
fontSize: "var(--prismiq-font-size-sm)",
|
|
4959
|
+
lineHeight: "20px",
|
|
4960
|
+
whiteSpace: "nowrap"
|
|
4961
|
+
};
|
|
4962
|
+
var tagRemoveStyles = {
|
|
4963
|
+
display: "inline-flex",
|
|
4964
|
+
alignItems: "center",
|
|
4965
|
+
justifyContent: "center",
|
|
4966
|
+
width: "14px",
|
|
4967
|
+
height: "14px",
|
|
4968
|
+
border: "none",
|
|
4969
|
+
background: "none",
|
|
4970
|
+
cursor: "pointer",
|
|
4971
|
+
padding: 0,
|
|
4972
|
+
fontSize: "12px",
|
|
4973
|
+
lineHeight: 1,
|
|
4974
|
+
color: "var(--prismiq-color-text-muted)",
|
|
4975
|
+
borderRadius: "50%"
|
|
4976
|
+
};
|
|
4977
|
+
var tagInputStyles = {
|
|
4978
|
+
border: "none",
|
|
4979
|
+
outline: "none",
|
|
4980
|
+
background: "none",
|
|
4981
|
+
flex: 1,
|
|
4982
|
+
minWidth: "80px",
|
|
4983
|
+
fontSize: "var(--prismiq-font-size-sm)",
|
|
4984
|
+
padding: "2px 0",
|
|
4985
|
+
color: "var(--prismiq-color-text)"
|
|
4986
|
+
};
|
|
4987
|
+
var multiOptionCheckStyles = {
|
|
4988
|
+
marginRight: "6px",
|
|
4989
|
+
color: "var(--prismiq-color-primary)",
|
|
4990
|
+
fontWeight: 700,
|
|
4991
|
+
fontSize: "12px"
|
|
4992
|
+
};
|
|
4866
4993
|
function FilterValueInput({
|
|
4867
4994
|
operator,
|
|
4868
4995
|
value,
|
|
4869
4996
|
onChange,
|
|
4870
4997
|
dataType,
|
|
4871
4998
|
disabled = false,
|
|
4872
|
-
className
|
|
4999
|
+
className,
|
|
5000
|
+
tableName,
|
|
5001
|
+
columnName
|
|
4873
5002
|
}) {
|
|
5003
|
+
const { client } = useAnalytics();
|
|
4874
5004
|
const inputType = getInputType(dataType);
|
|
5005
|
+
const isMulti = isMultiValueOperator(operator);
|
|
5006
|
+
const [sampleValues, setSampleValues] = useState([]);
|
|
5007
|
+
const [isLoadingValues, setIsLoadingValues] = useState(false);
|
|
5008
|
+
const fetchedRef = useRef(null);
|
|
5009
|
+
const fetchSeqRef = useRef(0);
|
|
5010
|
+
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
5011
|
+
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
|
5012
|
+
const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0, width: 0 });
|
|
5013
|
+
const inputRef = useRef(null);
|
|
5014
|
+
const dropdownRef = useRef(null);
|
|
5015
|
+
const containerRef = useRef(null);
|
|
5016
|
+
const [multiInputText, setMultiInputText] = useState("");
|
|
5017
|
+
useEffect(() => {
|
|
5018
|
+
setMultiInputText("");
|
|
5019
|
+
}, [operator]);
|
|
5020
|
+
useEffect(() => {
|
|
5021
|
+
if (!tableName || !columnName || !client) {
|
|
5022
|
+
setSampleValues([]);
|
|
5023
|
+
setIsLoadingValues(false);
|
|
5024
|
+
fetchedRef.current = null;
|
|
5025
|
+
return;
|
|
5026
|
+
}
|
|
5027
|
+
const fetchKey = `${tableName}.${columnName}`;
|
|
5028
|
+
if (fetchedRef.current === fetchKey) return;
|
|
5029
|
+
const fetchSeq = ++fetchSeqRef.current;
|
|
5030
|
+
const fetchSamples = async () => {
|
|
5031
|
+
setIsLoadingValues(true);
|
|
5032
|
+
try {
|
|
5033
|
+
const values = await client.getColumnSample(tableName, columnName, 100);
|
|
5034
|
+
const stringValues = values.filter((v) => v !== null && v !== void 0).map((v) => String(v));
|
|
5035
|
+
if (fetchSeqRef.current !== fetchSeq) return;
|
|
5036
|
+
setSampleValues(stringValues);
|
|
5037
|
+
fetchedRef.current = fetchKey;
|
|
5038
|
+
} catch (err) {
|
|
5039
|
+
if (fetchSeqRef.current !== fetchSeq) return;
|
|
5040
|
+
console.error("Failed to fetch sample values:", err);
|
|
5041
|
+
setSampleValues([]);
|
|
5042
|
+
fetchedRef.current = null;
|
|
5043
|
+
} finally {
|
|
5044
|
+
if (fetchSeqRef.current === fetchSeq) {
|
|
5045
|
+
setIsLoadingValues(false);
|
|
5046
|
+
}
|
|
5047
|
+
}
|
|
5048
|
+
};
|
|
5049
|
+
fetchSamples();
|
|
5050
|
+
}, [client, tableName, columnName]);
|
|
5051
|
+
const selectedValues = isMulti && Array.isArray(value) ? value.filter((v) => v !== null && v !== void 0).map((v) => String(v)) : [];
|
|
5052
|
+
const currentValueStr = isMulti ? multiInputText : formatValue(value);
|
|
5053
|
+
const filteredOptions = isMulti ? sampleValues.filter(
|
|
5054
|
+
(v) => v.toLowerCase().includes(multiInputText.toLowerCase()) && !selectedValues.includes(v)
|
|
5055
|
+
) : sampleValues.filter(
|
|
5056
|
+
(v) => v.toLowerCase().includes(currentValueStr.toLowerCase())
|
|
5057
|
+
);
|
|
5058
|
+
const updateDropdownPosition = useCallback(() => {
|
|
5059
|
+
const el = isMulti ? containerRef.current : inputRef.current;
|
|
5060
|
+
if (el) {
|
|
5061
|
+
const rect = el.getBoundingClientRect();
|
|
5062
|
+
setDropdownPosition({
|
|
5063
|
+
top: rect.bottom + 4,
|
|
5064
|
+
left: rect.left,
|
|
5065
|
+
width: rect.width
|
|
5066
|
+
});
|
|
5067
|
+
}
|
|
5068
|
+
}, [isMulti]);
|
|
5069
|
+
useEffect(() => {
|
|
5070
|
+
const handleClickOutside = (event) => {
|
|
5071
|
+
const target = event.target;
|
|
5072
|
+
const isInsideContainer = containerRef.current?.contains(target);
|
|
5073
|
+
const isInsideDropdown = dropdownRef.current?.contains(target);
|
|
5074
|
+
if (!isInsideContainer && !isInsideDropdown) {
|
|
5075
|
+
setIsDropdownOpen(false);
|
|
5076
|
+
}
|
|
5077
|
+
};
|
|
5078
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
5079
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
5080
|
+
}, []);
|
|
5081
|
+
const handleInputFocus = useCallback(() => {
|
|
5082
|
+
if (sampleValues.length > 0) {
|
|
5083
|
+
updateDropdownPosition();
|
|
5084
|
+
setIsDropdownOpen(true);
|
|
5085
|
+
setHighlightedIndex(-1);
|
|
5086
|
+
}
|
|
5087
|
+
}, [sampleValues.length, updateDropdownPosition]);
|
|
5088
|
+
const handleOptionSelect = useCallback(
|
|
5089
|
+
(optionValue) => {
|
|
5090
|
+
onChange(parseValue(optionValue, dataType));
|
|
5091
|
+
setIsDropdownOpen(false);
|
|
5092
|
+
inputRef.current?.blur();
|
|
5093
|
+
},
|
|
5094
|
+
[onChange, dataType]
|
|
5095
|
+
);
|
|
5096
|
+
const addMultiValue = useCallback(
|
|
5097
|
+
(val) => {
|
|
5098
|
+
const trimmed = val.trim();
|
|
5099
|
+
if (!trimmed) return;
|
|
5100
|
+
if (selectedValues.includes(trimmed)) return;
|
|
5101
|
+
const newValues = [...selectedValues, trimmed].map((v) => parseValue(v, dataType));
|
|
5102
|
+
onChange(newValues);
|
|
5103
|
+
setMultiInputText("");
|
|
5104
|
+
},
|
|
5105
|
+
[selectedValues, onChange, dataType]
|
|
5106
|
+
);
|
|
5107
|
+
const removeMultiValue = useCallback(
|
|
5108
|
+
(val) => {
|
|
5109
|
+
const newValues = selectedValues.filter((v) => v !== val).map((v) => parseValue(v, dataType));
|
|
5110
|
+
onChange(newValues.length > 0 ? newValues : []);
|
|
5111
|
+
},
|
|
5112
|
+
[selectedValues, onChange, dataType]
|
|
5113
|
+
);
|
|
5114
|
+
const handleMultiOptionSelect = useCallback(
|
|
5115
|
+
(optionValue) => {
|
|
5116
|
+
if (selectedValues.includes(optionValue)) {
|
|
5117
|
+
removeMultiValue(optionValue);
|
|
5118
|
+
} else {
|
|
5119
|
+
addMultiValue(optionValue);
|
|
5120
|
+
}
|
|
5121
|
+
setMultiInputText("");
|
|
5122
|
+
updateDropdownPosition();
|
|
5123
|
+
inputRef.current?.focus();
|
|
5124
|
+
},
|
|
5125
|
+
[selectedValues, addMultiValue, removeMultiValue, updateDropdownPosition]
|
|
5126
|
+
);
|
|
5127
|
+
const handleMultiInputKeyDown = useCallback(
|
|
5128
|
+
(e) => {
|
|
5129
|
+
if (e.key === "Backspace" && multiInputText === "" && selectedValues.length > 0) {
|
|
5130
|
+
const lastVal = selectedValues[selectedValues.length - 1];
|
|
5131
|
+
if (lastVal !== void 0) removeMultiValue(lastVal);
|
|
5132
|
+
return;
|
|
5133
|
+
}
|
|
5134
|
+
if (isDropdownOpen && filteredOptions.length > 0) {
|
|
5135
|
+
switch (e.key) {
|
|
5136
|
+
case "ArrowDown":
|
|
5137
|
+
e.preventDefault();
|
|
5138
|
+
setHighlightedIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));
|
|
5139
|
+
return;
|
|
5140
|
+
case "ArrowUp":
|
|
5141
|
+
e.preventDefault();
|
|
5142
|
+
setHighlightedIndex((prev) => Math.max(prev - 1, 0));
|
|
5143
|
+
return;
|
|
5144
|
+
case "Enter":
|
|
5145
|
+
e.preventDefault();
|
|
5146
|
+
if (highlightedIndex >= 0 && filteredOptions[highlightedIndex]) {
|
|
5147
|
+
handleMultiOptionSelect(filteredOptions[highlightedIndex]);
|
|
5148
|
+
} else if (multiInputText.trim()) {
|
|
5149
|
+
addMultiValue(multiInputText);
|
|
5150
|
+
}
|
|
5151
|
+
return;
|
|
5152
|
+
case "Escape":
|
|
5153
|
+
setIsDropdownOpen(false);
|
|
5154
|
+
return;
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5157
|
+
if (e.key === "," || e.key === "Enter") {
|
|
5158
|
+
e.preventDefault();
|
|
5159
|
+
addMultiValue(multiInputText);
|
|
5160
|
+
}
|
|
5161
|
+
},
|
|
5162
|
+
[
|
|
5163
|
+
multiInputText,
|
|
5164
|
+
selectedValues,
|
|
5165
|
+
isDropdownOpen,
|
|
5166
|
+
filteredOptions,
|
|
5167
|
+
highlightedIndex,
|
|
5168
|
+
addMultiValue,
|
|
5169
|
+
removeMultiValue,
|
|
5170
|
+
handleMultiOptionSelect
|
|
5171
|
+
]
|
|
5172
|
+
);
|
|
5173
|
+
const handleSingleKeyDown = useCallback(
|
|
5174
|
+
(e) => {
|
|
5175
|
+
if (!isDropdownOpen || filteredOptions.length === 0) return;
|
|
5176
|
+
switch (e.key) {
|
|
5177
|
+
case "ArrowDown":
|
|
5178
|
+
e.preventDefault();
|
|
5179
|
+
setHighlightedIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));
|
|
5180
|
+
break;
|
|
5181
|
+
case "ArrowUp":
|
|
5182
|
+
e.preventDefault();
|
|
5183
|
+
setHighlightedIndex((prev) => Math.max(prev - 1, 0));
|
|
5184
|
+
break;
|
|
5185
|
+
case "Enter":
|
|
5186
|
+
e.preventDefault();
|
|
5187
|
+
if (highlightedIndex >= 0 && filteredOptions[highlightedIndex]) {
|
|
5188
|
+
handleOptionSelect(filteredOptions[highlightedIndex]);
|
|
5189
|
+
}
|
|
5190
|
+
break;
|
|
5191
|
+
case "Escape":
|
|
5192
|
+
setIsDropdownOpen(false);
|
|
5193
|
+
break;
|
|
5194
|
+
}
|
|
5195
|
+
},
|
|
5196
|
+
[isDropdownOpen, filteredOptions, highlightedIndex, handleOptionSelect]
|
|
5197
|
+
);
|
|
4875
5198
|
if (operator === "is_null" || operator === "is_not_null") {
|
|
4876
5199
|
return /* @__PURE__ */ jsx(Fragment, {});
|
|
4877
5200
|
}
|
|
@@ -4911,36 +5234,163 @@ function FilterValueInput({
|
|
|
4911
5234
|
)
|
|
4912
5235
|
] });
|
|
4913
5236
|
}
|
|
4914
|
-
if (
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
5237
|
+
if (isMulti) {
|
|
5238
|
+
return /* @__PURE__ */ jsx("div", { className, style: containerStyles7, children: /* @__PURE__ */ jsxs("div", { ref: containerRef, style: comboboxContainerStyles, children: [
|
|
5239
|
+
/* @__PURE__ */ jsxs(
|
|
5240
|
+
"div",
|
|
5241
|
+
{
|
|
5242
|
+
"data-testid": "filter-tag-container",
|
|
5243
|
+
style: tagContainerStyles,
|
|
5244
|
+
onClick: () => inputRef.current?.focus(),
|
|
5245
|
+
children: [
|
|
5246
|
+
selectedValues.map((val) => /* @__PURE__ */ jsxs("span", { "data-testid": `filter-tag-${val}`, style: tagStyles, children: [
|
|
5247
|
+
val,
|
|
5248
|
+
/* @__PURE__ */ jsx(
|
|
5249
|
+
"button",
|
|
5250
|
+
{
|
|
5251
|
+
type: "button",
|
|
5252
|
+
"data-testid": `filter-tag-remove-${val}`,
|
|
5253
|
+
style: tagRemoveStyles,
|
|
5254
|
+
onClick: (e) => {
|
|
5255
|
+
e.stopPropagation();
|
|
5256
|
+
removeMultiValue(val);
|
|
5257
|
+
},
|
|
5258
|
+
tabIndex: -1,
|
|
5259
|
+
children: "\xD7"
|
|
5260
|
+
}
|
|
5261
|
+
)
|
|
5262
|
+
] }, val)),
|
|
5263
|
+
/* @__PURE__ */ jsx(
|
|
5264
|
+
"input",
|
|
5265
|
+
{
|
|
5266
|
+
ref: inputRef,
|
|
5267
|
+
"data-testid": "filter-multi-input",
|
|
5268
|
+
type: "text",
|
|
5269
|
+
placeholder: selectedValues.length === 0 ? isLoadingValues ? "Loading..." : "Type or select values" : "",
|
|
5270
|
+
value: multiInputText,
|
|
5271
|
+
disabled: disabled || isLoadingValues,
|
|
5272
|
+
onChange: (e) => {
|
|
5273
|
+
setMultiInputText(e.target.value);
|
|
5274
|
+
if (sampleValues.length > 0) {
|
|
5275
|
+
updateDropdownPosition();
|
|
5276
|
+
setIsDropdownOpen(true);
|
|
5277
|
+
setHighlightedIndex(-1);
|
|
5278
|
+
}
|
|
5279
|
+
},
|
|
5280
|
+
onFocus: handleInputFocus,
|
|
5281
|
+
onKeyDown: handleMultiInputKeyDown,
|
|
5282
|
+
style: tagInputStyles
|
|
5283
|
+
}
|
|
5284
|
+
)
|
|
5285
|
+
]
|
|
5286
|
+
}
|
|
5287
|
+
),
|
|
5288
|
+
selectedValues.length === 0 && !multiInputText && /* @__PURE__ */ jsxs("div", { "data-testid": "filter-multi-hint", style: {
|
|
5289
|
+
fontSize: "11px",
|
|
5290
|
+
color: "var(--prismiq-color-text-muted)",
|
|
5291
|
+
marginTop: "2px",
|
|
5292
|
+
paddingLeft: "2px"
|
|
5293
|
+
}, children: [
|
|
5294
|
+
"Press ",
|
|
5295
|
+
/* @__PURE__ */ jsx("kbd", { style: { padding: "0 3px", border: "1px solid var(--prismiq-color-border)", borderRadius: "3px", fontSize: "10px" }, children: "," }),
|
|
5296
|
+
" or ",
|
|
5297
|
+
/* @__PURE__ */ jsx("kbd", { style: { padding: "0 3px", border: "1px solid var(--prismiq-color-border)", borderRadius: "3px", fontSize: "10px" }, children: "Enter" }),
|
|
5298
|
+
" to add values"
|
|
5299
|
+
] }),
|
|
5300
|
+
isDropdownOpen && filteredOptions.length > 0 && typeof document !== "undefined" && createPortal(
|
|
5301
|
+
/* @__PURE__ */ jsx(
|
|
5302
|
+
"div",
|
|
5303
|
+
{
|
|
5304
|
+
ref: dropdownRef,
|
|
5305
|
+
"data-testid": "filter-dropdown",
|
|
5306
|
+
style: {
|
|
5307
|
+
...dropdownStyles2,
|
|
5308
|
+
top: dropdownPosition.top,
|
|
5309
|
+
left: dropdownPosition.left,
|
|
5310
|
+
width: dropdownPosition.width
|
|
5311
|
+
},
|
|
5312
|
+
children: filteredOptions.map((optionValue, index) => {
|
|
5313
|
+
const isSelected = selectedValues.includes(optionValue);
|
|
5314
|
+
return /* @__PURE__ */ jsxs(
|
|
5315
|
+
"div",
|
|
5316
|
+
{
|
|
5317
|
+
"data-testid": `filter-option-${index}`,
|
|
5318
|
+
onClick: () => handleMultiOptionSelect(optionValue),
|
|
5319
|
+
onMouseEnter: () => setHighlightedIndex(index),
|
|
5320
|
+
style: {
|
|
5321
|
+
...optionStyles2,
|
|
5322
|
+
...index === highlightedIndex ? optionHoverStyles2 : {},
|
|
5323
|
+
...isSelected ? { backgroundColor: "var(--prismiq-color-surface)", fontWeight: 500 } : {}
|
|
5324
|
+
},
|
|
5325
|
+
children: [
|
|
5326
|
+
/* @__PURE__ */ jsx("span", { style: multiOptionCheckStyles, children: isSelected ? "\u2713" : "\u2003" }),
|
|
5327
|
+
optionValue
|
|
5328
|
+
]
|
|
5329
|
+
},
|
|
5330
|
+
`${optionValue}-${index}`
|
|
5331
|
+
);
|
|
5332
|
+
})
|
|
5333
|
+
}
|
|
5334
|
+
),
|
|
5335
|
+
document.body
|
|
5336
|
+
)
|
|
5337
|
+
] }) });
|
|
5338
|
+
}
|
|
5339
|
+
return /* @__PURE__ */ jsx("div", { className, style: containerStyles7, children: /* @__PURE__ */ jsxs("div", { ref: containerRef, style: comboboxContainerStyles, children: [
|
|
5340
|
+
/* @__PURE__ */ jsx(
|
|
4920
5341
|
Input,
|
|
4921
5342
|
{
|
|
5343
|
+
ref: inputRef,
|
|
5344
|
+
"data-testid": "filter-single-input",
|
|
4922
5345
|
inputSize: "sm",
|
|
4923
|
-
type:
|
|
4924
|
-
placeholder:
|
|
4925
|
-
value:
|
|
4926
|
-
disabled,
|
|
4927
|
-
onChange:
|
|
4928
|
-
|
|
5346
|
+
type: inputType,
|
|
5347
|
+
placeholder: isLoadingValues ? "Loading..." : "Type or select value",
|
|
5348
|
+
value: currentValueStr,
|
|
5349
|
+
disabled: disabled || isLoadingValues,
|
|
5350
|
+
onChange: (e) => {
|
|
5351
|
+
onChange(parseValue(e.target.value, dataType));
|
|
5352
|
+
if (sampleValues.length > 0) {
|
|
5353
|
+
updateDropdownPosition();
|
|
5354
|
+
setIsDropdownOpen(true);
|
|
5355
|
+
}
|
|
5356
|
+
},
|
|
5357
|
+
onFocus: handleInputFocus,
|
|
5358
|
+
onKeyDown: handleSingleKeyDown,
|
|
5359
|
+
style: { width: "100%" }
|
|
4929
5360
|
}
|
|
4930
|
-
)
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
5361
|
+
),
|
|
5362
|
+
isDropdownOpen && filteredOptions.length > 0 && typeof document !== "undefined" && createPortal(
|
|
5363
|
+
/* @__PURE__ */ jsx(
|
|
5364
|
+
"div",
|
|
5365
|
+
{
|
|
5366
|
+
ref: dropdownRef,
|
|
5367
|
+
"data-testid": "filter-dropdown",
|
|
5368
|
+
style: {
|
|
5369
|
+
...dropdownStyles2,
|
|
5370
|
+
top: dropdownPosition.top,
|
|
5371
|
+
left: dropdownPosition.left,
|
|
5372
|
+
width: dropdownPosition.width
|
|
5373
|
+
},
|
|
5374
|
+
children: filteredOptions.map((optionValue, index) => /* @__PURE__ */ jsx(
|
|
5375
|
+
"div",
|
|
5376
|
+
{
|
|
5377
|
+
"data-testid": `filter-option-${index}`,
|
|
5378
|
+
onClick: () => handleOptionSelect(optionValue),
|
|
5379
|
+
onMouseEnter: () => setHighlightedIndex(index),
|
|
5380
|
+
style: {
|
|
5381
|
+
...optionStyles2,
|
|
5382
|
+
...index === highlightedIndex ? optionHoverStyles2 : {},
|
|
5383
|
+
...optionValue === currentValueStr ? { backgroundColor: "var(--prismiq-color-surface)", fontWeight: 500 } : {}
|
|
5384
|
+
},
|
|
5385
|
+
children: optionValue
|
|
5386
|
+
},
|
|
5387
|
+
`${optionValue}-${index}`
|
|
5388
|
+
))
|
|
5389
|
+
}
|
|
5390
|
+
),
|
|
5391
|
+
document.body
|
|
5392
|
+
)
|
|
5393
|
+
] }) });
|
|
4944
5394
|
}
|
|
4945
5395
|
var rowStyles = {
|
|
4946
5396
|
display: "flex",
|
|
@@ -5033,13 +5483,16 @@ function FilterRow({
|
|
|
5033
5483
|
});
|
|
5034
5484
|
return options;
|
|
5035
5485
|
}, [tables, schema]);
|
|
5486
|
+
const currentTable = useMemo(
|
|
5487
|
+
() => tables.find((t) => t.id === filter.table_id),
|
|
5488
|
+
[tables, filter.table_id]
|
|
5489
|
+
);
|
|
5036
5490
|
const currentColumnSchema = useMemo(() => {
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
const tableSchema = schema.tables.find((t) => t.name === table.name);
|
|
5491
|
+
if (!currentTable) return void 0;
|
|
5492
|
+
const tableSchema = schema.tables.find((t) => t.name === currentTable.name);
|
|
5040
5493
|
if (!tableSchema) return void 0;
|
|
5041
5494
|
return tableSchema.columns.find((c) => c.name === filter.column);
|
|
5042
|
-
}, [
|
|
5495
|
+
}, [currentTable, schema, filter.column]);
|
|
5043
5496
|
const operatorOptions = useMemo(
|
|
5044
5497
|
() => getOperatorsForType(currentColumnSchema?.data_type),
|
|
5045
5498
|
[currentColumnSchema]
|
|
@@ -5100,7 +5553,9 @@ function FilterRow({
|
|
|
5100
5553
|
operator: filter.operator,
|
|
5101
5554
|
value: filter.value,
|
|
5102
5555
|
onChange: handleValueChange,
|
|
5103
|
-
dataType: currentColumnSchema?.data_type
|
|
5556
|
+
dataType: currentColumnSchema?.data_type,
|
|
5557
|
+
tableName: currentTable?.name,
|
|
5558
|
+
columnName: filter.column
|
|
5104
5559
|
}
|
|
5105
5560
|
) }),
|
|
5106
5561
|
/* @__PURE__ */ jsx(
|
|
@@ -8541,13 +8996,14 @@ function TableSelector({
|
|
|
8541
8996
|
className
|
|
8542
8997
|
}) {
|
|
8543
8998
|
const { theme } = useTheme();
|
|
8999
|
+
const { getDisplayName } = useSchema();
|
|
8544
9000
|
const availableTableOptions = useMemo(() => {
|
|
8545
9001
|
const selectedNames = new Set(tables.map((t) => t.name));
|
|
8546
9002
|
return schema.tables.filter((t) => !selectedNames.has(t.name)).map((t) => ({
|
|
8547
9003
|
value: t.name,
|
|
8548
|
-
label:
|
|
9004
|
+
label: getDisplayName(t.name)
|
|
8549
9005
|
}));
|
|
8550
|
-
}, [schema.tables, tables]);
|
|
9006
|
+
}, [schema.tables, tables, getDisplayName]);
|
|
8551
9007
|
const suggestedTables = useMemo(() => {
|
|
8552
9008
|
if (!showRelationships || tables.length === 0) return [];
|
|
8553
9009
|
const selectedNames = new Set(tables.map((t) => t.name));
|
|
@@ -8649,7 +9105,7 @@ function TableSelector({
|
|
|
8649
9105
|
return /* @__PURE__ */ jsxs("div", { className, style: containerStyle, children: [
|
|
8650
9106
|
tables.length > 0 && /* @__PURE__ */ jsx("div", { style: selectedTablesStyle, children: tables.map((table, index) => /* @__PURE__ */ jsxs("div", { style: tableChipStyle, children: [
|
|
8651
9107
|
/* @__PURE__ */ jsx(Icon, { name: "table", size: 14 }),
|
|
8652
|
-
/* @__PURE__ */ jsx("span", { children: table.name }),
|
|
9108
|
+
/* @__PURE__ */ jsx("span", { children: getDisplayName(table.name) }),
|
|
8653
9109
|
index === 0 && /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "default", children: "primary" }),
|
|
8654
9110
|
tables.length > 1 && /* @__PURE__ */ jsx(
|
|
8655
9111
|
"button",
|
|
@@ -8657,7 +9113,7 @@ function TableSelector({
|
|
|
8657
9113
|
type: "button",
|
|
8658
9114
|
style: removeButtonStyle,
|
|
8659
9115
|
onClick: () => handleRemoveTable(table.id),
|
|
8660
|
-
"aria-label": `Remove ${table.name}`,
|
|
9116
|
+
"aria-label": `Remove ${getDisplayName(table.name)}`,
|
|
8661
9117
|
children: /* @__PURE__ */ jsx(Icon, { name: "x", size: 12 })
|
|
8662
9118
|
}
|
|
8663
9119
|
)
|
|
@@ -8691,7 +9147,7 @@ function TableSelector({
|
|
|
8691
9147
|
title: suggestion.relationship,
|
|
8692
9148
|
children: [
|
|
8693
9149
|
/* @__PURE__ */ jsx(Icon, { name: "plus", size: 10 }),
|
|
8694
|
-
suggestion.table
|
|
9150
|
+
getDisplayName(suggestion.table)
|
|
8695
9151
|
]
|
|
8696
9152
|
},
|
|
8697
9153
|
suggestion.table
|
|
@@ -8702,5 +9158,5 @@ function TableSelector({
|
|
|
8702
9158
|
}
|
|
8703
9159
|
|
|
8704
9160
|
export { AggregationPicker, AnalyticsProvider, AutoSaveIndicator, Badge, Button, CalculatedFieldBuilder, Checkbox, CollapsibleSection, ColorPaletteSelector, ColumnNode, ColumnSelector, CrossFilterProvider, CustomSQLEditor, Dialog, DialogFooter, DialogHeader, Dropdown, DropdownItem, DropdownSeparator, EmptyDashboard, EmptyState, ErrorBoundary, ErrorFallback, ExpressionEditor, FilterBuilder, FilterRow, FilterValueInput, Icon, Input, JoinBuilder, JoinRow, NoData, NoResults, Pagination, PrismiqClient, PrismiqError, QueryBuilder, QueryBuilderToolbar, QueryPreview, ResultsTable, SavedQueryPicker, SchemaExplorer, Select, SelectedColumn, Skeleton, SkeletonChart, SkeletonMetricCard, SkeletonTable, SkeletonText, SortBuilder, SortRow, TableCell, TableHeader, TableNode, TableRow, TableSelector, TimeSeriesConfig, Tooltip, WidgetErrorBoundary, useAnalytics, useAnalyticsCallbacks, useChartData, useCrossFilterOptional, useCustomSQL, useDashboard, useDashboardMutations, useDashboardPinStatus, useDashboards, useDebouncedLayoutSave, usePinMutations, usePinnedDashboards, useQuery, useSavedQueries, useSchema };
|
|
8705
|
-
//# sourceMappingURL=chunk-
|
|
8706
|
-
//# sourceMappingURL=chunk-
|
|
9161
|
+
//# sourceMappingURL=chunk-ET7GCREP.js.map
|
|
9162
|
+
//# sourceMappingURL=chunk-ET7GCREP.js.map
|