@vuu-ui/vuu-filters 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +0 -0
  3. package/cjs/FilterModel.js +233 -0
  4. package/cjs/FilterModel.js.map +1 -0
  5. package/cjs/filter-bar/FilterBar.css.js +6 -0
  6. package/cjs/filter-bar/FilterBar.css.js.map +1 -0
  7. package/cjs/filter-bar/FilterBar.js +134 -0
  8. package/cjs/filter-bar/FilterBar.js.map +1 -0
  9. package/cjs/filter-bar/FilterBarMenu.js +12 -0
  10. package/cjs/filter-bar/FilterBarMenu.js.map +1 -0
  11. package/cjs/filter-bar/filterBarFocusManagement.js +35 -0
  12. package/cjs/filter-bar/filterBarFocusManagement.js.map +1 -0
  13. package/cjs/filter-bar/useApplyFilterOnChange.js +33 -0
  14. package/cjs/filter-bar/useApplyFilterOnChange.js.map +1 -0
  15. package/cjs/filter-bar/useFilterBar.js +250 -0
  16. package/cjs/filter-bar/useFilterBar.js.map +1 -0
  17. package/cjs/filter-bar/useFilterState.js +150 -0
  18. package/cjs/filter-bar/useFilterState.js.map +1 -0
  19. package/cjs/filter-clause/ExpandoCombobox.css.js +6 -0
  20. package/cjs/filter-clause/ExpandoCombobox.css.js.map +1 -0
  21. package/cjs/filter-clause/ExpandoCombobox.js +148 -0
  22. package/cjs/filter-clause/ExpandoCombobox.js.map +1 -0
  23. package/cjs/filter-clause/FilterClause.css.js +6 -0
  24. package/cjs/filter-clause/FilterClause.css.js.map +1 -0
  25. package/cjs/filter-clause/FilterClause.js +112 -0
  26. package/cjs/filter-clause/FilterClause.js.map +1 -0
  27. package/cjs/filter-clause/filterClauseFocusManagement.js +203 -0
  28. package/cjs/filter-clause/filterClauseFocusManagement.js.map +1 -0
  29. package/cjs/filter-clause/operator-utils.js +20 -0
  30. package/cjs/filter-clause/operator-utils.js.map +1 -0
  31. package/cjs/filter-clause/useFilterClause.js +142 -0
  32. package/cjs/filter-clause/useFilterClause.js.map +1 -0
  33. package/cjs/filter-clause/value-editors/FilterClauseValueEditor.js +77 -0
  34. package/cjs/filter-clause/value-editors/FilterClauseValueEditor.js.map +1 -0
  35. package/cjs/filter-clause/value-editors/FilterClauseValueEditorDate.js +75 -0
  36. package/cjs/filter-clause/value-editors/FilterClauseValueEditorDate.js.map +1 -0
  37. package/cjs/filter-clause/value-editors/FilterClauseValueEditorNumber.js +55 -0
  38. package/cjs/filter-clause/value-editors/FilterClauseValueEditorNumber.js.map +1 -0
  39. package/cjs/filter-clause/value-editors/FilterClauseValueEditorText.js +193 -0
  40. package/cjs/filter-clause/value-editors/FilterClauseValueEditorText.js.map +1 -0
  41. package/cjs/filter-editor/FilterClauseCombinator.css.js +6 -0
  42. package/cjs/filter-editor/FilterClauseCombinator.css.js.map +1 -0
  43. package/cjs/filter-editor/FilterClauseCombinator.js +42 -0
  44. package/cjs/filter-editor/FilterClauseCombinator.js.map +1 -0
  45. package/cjs/filter-editor/FilterEditor.css.js +6 -0
  46. package/cjs/filter-editor/FilterEditor.css.js.map +1 -0
  47. package/cjs/filter-editor/FilterEditor.js +97 -0
  48. package/cjs/filter-editor/FilterEditor.js.map +1 -0
  49. package/cjs/filter-editor/useFilterEditor.js +188 -0
  50. package/cjs/filter-editor/useFilterEditor.js.map +1 -0
  51. package/cjs/filter-input/FilterInput.css.js +6 -0
  52. package/cjs/filter-input/FilterInput.css.js.map +1 -0
  53. package/cjs/filter-input/FilterInput.js +52 -0
  54. package/cjs/filter-input/FilterInput.js.map +1 -0
  55. package/cjs/filter-input/FilterLanguage.js +24 -0
  56. package/cjs/filter-input/FilterLanguage.js.map +1 -0
  57. package/cjs/filter-input/filterInfo.js +17 -0
  58. package/cjs/filter-input/filterInfo.js.map +1 -0
  59. package/cjs/filter-input/highlighting.js +12 -0
  60. package/cjs/filter-input/highlighting.js.map +1 -0
  61. package/cjs/filter-input/theme.js +79 -0
  62. package/cjs/filter-input/theme.js.map +1 -0
  63. package/cjs/filter-input/useCodeMirrorEditor.js +136 -0
  64. package/cjs/filter-input/useCodeMirrorEditor.js.map +1 -0
  65. package/cjs/filter-input/useFilterAutoComplete.js +243 -0
  66. package/cjs/filter-input/useFilterAutoComplete.js.map +1 -0
  67. package/cjs/filter-input/useFilterSuggestionProvider.js +206 -0
  68. package/cjs/filter-input/useFilterSuggestionProvider.js.map +1 -0
  69. package/cjs/filter-pill/FilterPill.css.js +6 -0
  70. package/cjs/filter-pill/FilterPill.css.js.map +1 -0
  71. package/cjs/filter-pill/FilterPill.js +147 -0
  72. package/cjs/filter-pill/FilterPill.js.map +1 -0
  73. package/cjs/filter-pill/FilterPillMenuOptions.js +32 -0
  74. package/cjs/filter-pill/FilterPillMenuOptions.js.map +1 -0
  75. package/cjs/filter-pill/filterAsReactNode.js +27 -0
  76. package/cjs/filter-pill/filterAsReactNode.js.map +1 -0
  77. package/cjs/filter-pill/getFilterLabel.js +22 -0
  78. package/cjs/filter-pill/getFilterLabel.js.map +1 -0
  79. package/cjs/filter-pill/getFilterTooltipText.js +41 -0
  80. package/cjs/filter-pill/getFilterTooltipText.js.map +1 -0
  81. package/cjs/filter-utils.js +328 -0
  82. package/cjs/filter-utils.js.map +1 -0
  83. package/cjs/index.js +50 -0
  84. package/cjs/index.js.map +1 -0
  85. package/cjs/use-filter-config.js +39 -0
  86. package/cjs/use-filter-config.js.map +1 -0
  87. package/cjs/use-rest-config.js +63 -0
  88. package/cjs/use-rest-config.js.map +1 -0
  89. package/esm/FilterModel.js +230 -0
  90. package/esm/FilterModel.js.map +1 -0
  91. package/esm/filter-bar/FilterBar.css.js +4 -0
  92. package/esm/filter-bar/FilterBar.css.js.map +1 -0
  93. package/esm/filter-bar/FilterBar.js +132 -0
  94. package/esm/filter-bar/FilterBar.js.map +1 -0
  95. package/esm/filter-bar/FilterBarMenu.js +10 -0
  96. package/esm/filter-bar/FilterBarMenu.js.map +1 -0
  97. package/esm/filter-bar/filterBarFocusManagement.js +33 -0
  98. package/esm/filter-bar/filterBarFocusManagement.js.map +1 -0
  99. package/esm/filter-bar/useApplyFilterOnChange.js +31 -0
  100. package/esm/filter-bar/useApplyFilterOnChange.js.map +1 -0
  101. package/esm/filter-bar/useFilterBar.js +248 -0
  102. package/esm/filter-bar/useFilterBar.js.map +1 -0
  103. package/esm/filter-bar/useFilterState.js +148 -0
  104. package/esm/filter-bar/useFilterState.js.map +1 -0
  105. package/esm/filter-clause/ExpandoCombobox.css.js +4 -0
  106. package/esm/filter-clause/ExpandoCombobox.css.js.map +1 -0
  107. package/esm/filter-clause/ExpandoCombobox.js +146 -0
  108. package/esm/filter-clause/ExpandoCombobox.js.map +1 -0
  109. package/esm/filter-clause/FilterClause.css.js +4 -0
  110. package/esm/filter-clause/FilterClause.css.js.map +1 -0
  111. package/esm/filter-clause/FilterClause.js +110 -0
  112. package/esm/filter-clause/FilterClause.js.map +1 -0
  113. package/esm/filter-clause/filterClauseFocusManagement.js +189 -0
  114. package/esm/filter-clause/filterClauseFocusManagement.js.map +1 -0
  115. package/esm/filter-clause/operator-utils.js +16 -0
  116. package/esm/filter-clause/operator-utils.js.map +1 -0
  117. package/esm/filter-clause/useFilterClause.js +140 -0
  118. package/esm/filter-clause/useFilterClause.js.map +1 -0
  119. package/esm/filter-clause/value-editors/FilterClauseValueEditor.js +75 -0
  120. package/esm/filter-clause/value-editors/FilterClauseValueEditor.js.map +1 -0
  121. package/esm/filter-clause/value-editors/FilterClauseValueEditorDate.js +73 -0
  122. package/esm/filter-clause/value-editors/FilterClauseValueEditorDate.js.map +1 -0
  123. package/esm/filter-clause/value-editors/FilterClauseValueEditorNumber.js +53 -0
  124. package/esm/filter-clause/value-editors/FilterClauseValueEditorNumber.js.map +1 -0
  125. package/esm/filter-clause/value-editors/FilterClauseValueEditorText.js +191 -0
  126. package/esm/filter-clause/value-editors/FilterClauseValueEditorText.js.map +1 -0
  127. package/esm/filter-editor/FilterClauseCombinator.css.js +4 -0
  128. package/esm/filter-editor/FilterClauseCombinator.css.js.map +1 -0
  129. package/esm/filter-editor/FilterClauseCombinator.js +40 -0
  130. package/esm/filter-editor/FilterClauseCombinator.js.map +1 -0
  131. package/esm/filter-editor/FilterEditor.css.js +4 -0
  132. package/esm/filter-editor/FilterEditor.css.js.map +1 -0
  133. package/esm/filter-editor/FilterEditor.js +95 -0
  134. package/esm/filter-editor/FilterEditor.js.map +1 -0
  135. package/esm/filter-editor/useFilterEditor.js +186 -0
  136. package/esm/filter-editor/useFilterEditor.js.map +1 -0
  137. package/esm/filter-input/FilterInput.css.js +4 -0
  138. package/esm/filter-input/FilterInput.css.js.map +1 -0
  139. package/esm/filter-input/FilterInput.js +50 -0
  140. package/esm/filter-input/FilterInput.js.map +1 -0
  141. package/esm/filter-input/FilterLanguage.js +22 -0
  142. package/esm/filter-input/FilterLanguage.js.map +1 -0
  143. package/esm/filter-input/filterInfo.js +15 -0
  144. package/esm/filter-input/filterInfo.js.map +1 -0
  145. package/esm/filter-input/highlighting.js +10 -0
  146. package/esm/filter-input/highlighting.js.map +1 -0
  147. package/esm/filter-input/theme.js +77 -0
  148. package/esm/filter-input/theme.js.map +1 -0
  149. package/esm/filter-input/useCodeMirrorEditor.js +134 -0
  150. package/esm/filter-input/useCodeMirrorEditor.js.map +1 -0
  151. package/esm/filter-input/useFilterAutoComplete.js +241 -0
  152. package/esm/filter-input/useFilterAutoComplete.js.map +1 -0
  153. package/esm/filter-input/useFilterSuggestionProvider.js +204 -0
  154. package/esm/filter-input/useFilterSuggestionProvider.js.map +1 -0
  155. package/esm/filter-pill/FilterPill.css.js +4 -0
  156. package/esm/filter-pill/FilterPill.css.js.map +1 -0
  157. package/esm/filter-pill/FilterPill.js +145 -0
  158. package/esm/filter-pill/FilterPill.js.map +1 -0
  159. package/esm/filter-pill/FilterPillMenuOptions.js +27 -0
  160. package/esm/filter-pill/FilterPillMenuOptions.js.map +1 -0
  161. package/esm/filter-pill/filterAsReactNode.js +25 -0
  162. package/esm/filter-pill/filterAsReactNode.js.map +1 -0
  163. package/esm/filter-pill/getFilterLabel.js +20 -0
  164. package/esm/filter-pill/getFilterLabel.js.map +1 -0
  165. package/esm/filter-pill/getFilterTooltipText.js +39 -0
  166. package/esm/filter-pill/getFilterTooltipText.js.map +1 -0
  167. package/esm/filter-utils.js +307 -0
  168. package/esm/filter-utils.js.map +1 -0
  169. package/esm/index.js +13 -0
  170. package/esm/index.js.map +1 -0
  171. package/esm/use-filter-config.js +37 -0
  172. package/esm/use-filter-config.js.map +1 -0
  173. package/esm/use-rest-config.js +61 -0
  174. package/esm/use-rest-config.js.map +1 -0
  175. package/package.json +48 -0
  176. package/types/FilterModel.d.ts +43 -0
  177. package/types/column-filter/utils.d.ts +4 -0
  178. package/types/filter-bar/FilterBar.d.ts +22 -0
  179. package/types/filter-bar/FilterBarMenu.d.ts +2 -0
  180. package/types/filter-bar/filterBarFocusManagement.d.ts +1 -0
  181. package/types/filter-bar/index.d.ts +1 -0
  182. package/types/filter-bar/useApplyFilterOnChange.d.ts +10 -0
  183. package/types/filter-bar/useFilterBar.d.ts +30 -0
  184. package/types/filter-bar/useFilterState.d.ts +17 -0
  185. package/types/filter-clause/ExpandoCombobox.d.ts +10 -0
  186. package/types/filter-clause/FilterClause.d.ts +17 -0
  187. package/types/filter-clause/FilterMenu.d.ts +10 -0
  188. package/types/filter-clause/FilterMenuOptions.d.ts +6 -0
  189. package/types/filter-clause/filterClauseFocusManagement.d.ts +16 -0
  190. package/types/filter-clause/filterClauseTypes.d.ts +13 -0
  191. package/types/filter-clause/index.d.ts +3 -0
  192. package/types/filter-clause/operator-utils.d.ts +4 -0
  193. package/types/filter-clause/useFilterClause.d.ts +24 -0
  194. package/types/filter-clause/value-editors/FilterClauseValueEditor.d.ts +13 -0
  195. package/types/filter-clause/value-editors/FilterClauseValueEditorDate.d.ts +10 -0
  196. package/types/filter-clause/value-editors/FilterClauseValueEditorNumber.d.ts +10 -0
  197. package/types/filter-clause/value-editors/FilterClauseValueEditorText.d.ts +11 -0
  198. package/types/filter-editor/FilterClauseCombinator.d.ts +9 -0
  199. package/types/filter-editor/FilterEditor.d.ts +16 -0
  200. package/types/filter-editor/index.d.ts +1 -0
  201. package/types/filter-editor/useFilterEditor.d.ts +31 -0
  202. package/types/filter-input/FilterInput.d.ts +10 -0
  203. package/types/filter-input/FilterLanguage.d.ts +2 -0
  204. package/types/filter-input/filterInfo.d.ts +1 -0
  205. package/types/filter-input/highlighting.d.ts +1 -0
  206. package/types/filter-input/index.d.ts +3 -0
  207. package/types/filter-input/theme.d.ts +1 -0
  208. package/types/filter-input/useCodeMirrorEditor.d.ts +35 -0
  209. package/types/filter-input/useFilterAutoComplete.d.ts +9 -0
  210. package/types/filter-input/useFilterSuggestionProvider.d.ts +16 -0
  211. package/types/filter-pill/FilterPill.d.ts +17 -0
  212. package/types/filter-pill/FilterPillMenuOptions.d.ts +12 -0
  213. package/types/filter-pill/filterAsReactNode.d.ts +3 -0
  214. package/types/filter-pill/getFilterLabel.d.ts +2 -0
  215. package/types/filter-pill/getFilterTooltipText.d.ts +2 -0
  216. package/types/filter-pill/index.d.ts +1 -0
  217. package/types/filter-pill-menu/FilterPillMenu.d.ts +18 -0
  218. package/types/filter-pill-menu/FilterPillMenuOptions.d.ts +12 -0
  219. package/types/filter-pill-menu/index.d.ts +1 -0
  220. package/types/filter-utils.d.ts +48 -0
  221. package/types/index.d.ts +8 -0
  222. package/types/use-filter-config.d.ts +12 -0
  223. package/types/use-rest-config.d.ts +11 -0
@@ -0,0 +1,136 @@
1
+ 'use strict';
2
+
3
+ var vuuCodemirror = require('@vuu-ui/vuu-codemirror');
4
+ var vuuFilterParser = require('@vuu-ui/vuu-filter-parser');
5
+ var cx = require('clsx');
6
+ var react = require('react');
7
+ var FilterLanguage = require('./FilterLanguage.js');
8
+ var highlighting = require('./highlighting.js');
9
+ var theme = require('./theme.js');
10
+ var useFilterAutoComplete = require('./useFilterAutoComplete.js');
11
+
12
+ const getView = (ref) => {
13
+ if (ref.current == void 0) {
14
+ throw Error("EditorView not defined");
15
+ }
16
+ return ref.current;
17
+ };
18
+ const getOptionClass = (completion) => {
19
+ return cx("vuuSuggestion", {
20
+ vuuIllustration: completion.isIllustration
21
+ });
22
+ };
23
+ const stripName = (filterQuery) => {
24
+ const pos = filterQuery.lastIndexOf(" as ");
25
+ if (pos !== -1) {
26
+ return filterQuery.slice(0, pos);
27
+ } else {
28
+ return filterQuery;
29
+ }
30
+ };
31
+ const noop = () => console.log("noooop");
32
+ const useCodeMirrorEditor = ({
33
+ existingFilter,
34
+ onSubmitFilter,
35
+ suggestionProvider
36
+ }) => {
37
+ const editorRef = react.useRef(null);
38
+ const onSubmit = react.useRef(noop);
39
+ const viewRef = react.useRef();
40
+ const completionFn = useFilterAutoComplete.useAutoComplete(
41
+ suggestionProvider,
42
+ onSubmit,
43
+ existingFilter
44
+ );
45
+ const [createState, clearInput] = react.useMemo(() => {
46
+ const parseFilter = () => {
47
+ const view = getView(viewRef);
48
+ const source = view.state.doc.toString();
49
+ const tree = vuuCodemirror.ensureSyntaxTree(view.state, view.state.doc.length, 5e3);
50
+ if (tree) {
51
+ const filter = vuuFilterParser.walkTree(tree, source);
52
+ return [filter, stripName(source), filter.name];
53
+ } else {
54
+ return [void 0, "", void 0];
55
+ }
56
+ };
57
+ const clearInput2 = () => {
58
+ getView(viewRef).setState(createState2());
59
+ };
60
+ const submitFilterAndClearInput = (mode) => {
61
+ const [filter, filterQuery, filterName] = parseFilter();
62
+ onSubmitFilter?.(filter, filterQuery, mode, filterName);
63
+ clearInput2();
64
+ };
65
+ const submitFilter = (key) => {
66
+ return vuuCodemirror.keymap.of([
67
+ {
68
+ key,
69
+ run() {
70
+ submitFilterAndClearInput();
71
+ return true;
72
+ }
73
+ }
74
+ ]);
75
+ };
76
+ const showSuggestions = (key) => {
77
+ return vuuCodemirror.keymap.of([
78
+ {
79
+ key,
80
+ run() {
81
+ vuuCodemirror.startCompletion(getView(viewRef));
82
+ return true;
83
+ }
84
+ }
85
+ ]);
86
+ };
87
+ const createState2 = () => vuuCodemirror.EditorState.create({
88
+ doc: "",
89
+ extensions: [
90
+ vuuCodemirror.minimalSetup,
91
+ vuuCodemirror.autocompletion({
92
+ override: [completionFn],
93
+ optionClass: getOptionClass
94
+ }),
95
+ FilterLanguage.filterLanguageSupport(),
96
+ vuuCodemirror.keymap.of(vuuCodemirror.defaultKeymap),
97
+ submitFilter("Ctrl-Enter"),
98
+ showSuggestions("ArrowDown"),
99
+ vuuCodemirror.EditorView.updateListener.of((v) => {
100
+ const view = getView(viewRef);
101
+ if (v.docChanged) {
102
+ vuuCodemirror.startCompletion(view);
103
+ }
104
+ }),
105
+ vuuCodemirror.EditorState.transactionFilter.of(
106
+ (tr) => tr.newDoc.lines > 1 ? [] : tr
107
+ ),
108
+ theme.vuuTheme,
109
+ highlighting.vuuHighlighting
110
+ ]
111
+ });
112
+ onSubmit.current = (mode) => {
113
+ submitFilterAndClearInput(mode);
114
+ setTimeout(() => {
115
+ getView(viewRef).focus();
116
+ }, 100);
117
+ };
118
+ return [createState2, clearInput2];
119
+ }, [completionFn, onSubmitFilter]);
120
+ react.useEffect(() => {
121
+ if (!editorRef.current) {
122
+ throw Error("editor not in dom");
123
+ }
124
+ viewRef.current = new vuuCodemirror.EditorView({
125
+ state: createState(),
126
+ parent: editorRef.current
127
+ });
128
+ return () => {
129
+ viewRef.current?.destroy();
130
+ };
131
+ }, [completionFn, createState]);
132
+ return { editorRef, clearInput };
133
+ };
134
+
135
+ exports.useCodeMirrorEditor = useCodeMirrorEditor;
136
+ //# sourceMappingURL=useCodeMirrorEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCodeMirrorEditor.js","sources":["../../src/filter-input/useCodeMirrorEditor.ts"],"sourcesContent":["import {\n autocompletion,\n Completion,\n defaultKeymap,\n EditorState,\n EditorView,\n ensureSyntaxTree,\n keymap,\n minimalSetup,\n startCompletion,\n VuuCompletion,\n} from \"@vuu-ui/vuu-codemirror\";\nimport { walkTree } from \"@vuu-ui/vuu-filter-parser\";\nimport { Filter } from \"@vuu-ui/vuu-filter-types\";\nimport cx from \"clsx\";\nimport { MutableRefObject, useEffect, useMemo, useRef } from \"react\";\nimport { filterLanguageSupport } from \"./FilterLanguage\";\nimport { vuuHighlighting } from \"./highlighting\";\nimport { vuuTheme } from \"./theme\";\nimport {\n ApplyCompletion,\n FilterSubmissionMode,\n useAutoComplete,\n} from \"./useFilterAutoComplete\";\nimport { FilterSaveOptions } from \"./useFilterSuggestionProvider\";\n\nexport type SuggestionType =\n | \"column\"\n | \"columnValue\"\n | \"operator\"\n | \"save\"\n | \"name\";\n\nexport interface FilterSuggestionOptions {\n quoted?: boolean;\n columnName?: string;\n existingFilter?: Filter;\n filterName?: string;\n onSubmit?: () => void;\n operator?: string;\n startsWith?: string;\n selection?: string[];\n}\n\nexport type getFilterSuggestionsType = (\n suggestionType: SuggestionType,\n options?: FilterSuggestionOptions\n) => Promise<Completion[]>;\n\nexport interface IFilterSuggestionProvider {\n getSuggestions: getFilterSuggestionsType;\n isPartialMatch: (\n valueType: SuggestionType,\n columnName?: string,\n text?: string | undefined\n ) => Promise<boolean>;\n}\n\nexport interface SuggestionConsumer {\n suggestionProvider: IFilterSuggestionProvider;\n}\n\nconst getView = (ref: MutableRefObject<EditorView | undefined>): EditorView => {\n if (ref.current == undefined) {\n throw Error(\"EditorView not defined\");\n }\n return ref.current;\n};\n\nconst getOptionClass = (completion: VuuCompletion) => {\n return cx(\"vuuSuggestion\", {\n vuuIllustration: completion.isIllustration,\n });\n};\n\nconst stripName = (filterQuery: string) => {\n const pos = filterQuery.lastIndexOf(\" as \");\n if (pos !== -1) {\n return filterQuery.slice(0, pos);\n } else {\n return filterQuery;\n }\n};\n\nconst noop = () => console.log(\"noooop\");\n\nexport type filterSubmissionHandler = (\n filter: Filter | undefined,\n filterQuery: string,\n mode?: FilterSubmissionMode,\n filterName?: string\n) => void;\n\nexport interface CodeMirrorEditorProps {\n existingFilter?: Filter;\n onSubmitFilter?: filterSubmissionHandler;\n saveOptions?: FilterSaveOptions;\n suggestionProvider: IFilterSuggestionProvider;\n}\n\nexport const useCodeMirrorEditor = ({\n existingFilter,\n onSubmitFilter,\n suggestionProvider,\n}: CodeMirrorEditorProps) => {\n const editorRef = useRef<HTMLDivElement>(null);\n const onSubmit = useRef<ApplyCompletion>(noop);\n const viewRef = useRef<EditorView>();\n const completionFn = useAutoComplete(\n suggestionProvider,\n onSubmit,\n existingFilter\n );\n\n const [createState, clearInput] = useMemo(() => {\n const parseFilter = ():\n | [Filter, string, string | undefined]\n | [undefined, \"\", undefined] => {\n const view = getView(viewRef);\n const source = view.state.doc.toString();\n const tree = ensureSyntaxTree(view.state, view.state.doc.length, 5000);\n if (tree) {\n const filter = walkTree(tree, source) as Filter;\n return [filter, stripName(source), filter.name];\n } else {\n return [undefined, \"\", undefined];\n }\n };\n\n const clearInput = () => {\n getView(viewRef).setState(createState());\n };\n\n const submitFilterAndClearInput = (mode?: FilterSubmissionMode) => {\n const [filter, filterQuery, filterName] = parseFilter();\n onSubmitFilter?.(filter, filterQuery, mode, filterName);\n clearInput();\n };\n\n const submitFilter = (key: string) => {\n return keymap.of([\n {\n key,\n run() {\n submitFilterAndClearInput();\n return true;\n },\n },\n ]);\n };\n\n const showSuggestions = (key: string) => {\n return keymap.of([\n {\n key,\n run() {\n startCompletion(getView(viewRef));\n return true;\n },\n },\n ]);\n };\n\n const createState = (): EditorState =>\n EditorState.create({\n doc: \"\",\n extensions: [\n minimalSetup,\n autocompletion({\n override: [completionFn],\n optionClass: getOptionClass,\n }),\n filterLanguageSupport(),\n keymap.of(defaultKeymap),\n submitFilter(\"Ctrl-Enter\"),\n showSuggestions(\"ArrowDown\"),\n EditorView.updateListener.of((v) => {\n const view = getView(viewRef);\n if (v.docChanged) {\n startCompletion(view);\n }\n }),\n EditorState.transactionFilter.of((tr) =>\n tr.newDoc.lines > 1 ? [] : tr\n ),\n vuuTheme,\n vuuHighlighting,\n ],\n });\n\n onSubmit.current = (mode?: FilterSubmissionMode) => {\n submitFilterAndClearInput(mode);\n // TODO refocu sthe editor\n setTimeout(() => {\n getView(viewRef).focus();\n }, 100);\n };\n\n return [createState, clearInput];\n }, [completionFn, onSubmitFilter]);\n\n useEffect(() => {\n if (!editorRef.current) {\n throw Error(\"editor not in dom\");\n }\n\n viewRef.current = new EditorView({\n state: createState(),\n parent: editorRef.current,\n });\n\n return () => {\n viewRef.current?.destroy();\n };\n }, [completionFn, createState]);\n\n return { editorRef, clearInput };\n};\n"],"names":["useRef","useAutoComplete","useMemo","ensureSyntaxTree","walkTree","clearInput","createState","keymap","startCompletion","EditorState","minimalSetup","autocompletion","filterLanguageSupport","defaultKeymap","EditorView","vuuTheme","vuuHighlighting","useEffect"],"mappings":"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"}
@@ -0,0 +1,243 @@
1
+ 'use strict';
2
+
3
+ var vuuCodemirror = require('@vuu-ui/vuu-codemirror');
4
+ var react = require('react');
5
+
6
+ const getOperator = (node, state) => {
7
+ let maybeColumnNode = node.prevSibling || node.parent;
8
+ while (maybeColumnNode && !["Column", "Operator", "In"].includes(maybeColumnNode.name)) {
9
+ maybeColumnNode = maybeColumnNode.prevSibling || maybeColumnNode.parent;
10
+ }
11
+ if (maybeColumnNode?.name === "In" || maybeColumnNode?.name === "Operator") {
12
+ return vuuCodemirror.getValue(maybeColumnNode, state);
13
+ } else {
14
+ return void 0;
15
+ }
16
+ };
17
+ const getPartialOperator = (maybeOperatorNode, state, columnName) => {
18
+ const value = vuuCodemirror.getValue(maybeOperatorNode, state);
19
+ if (columnName === void 0 || value === columnName) {
20
+ return;
21
+ }
22
+ if (["contains", "ends", "starts"].some(
23
+ (val) => val.startsWith(value.toLowerCase())
24
+ )) {
25
+ return value;
26
+ } else {
27
+ return void 0;
28
+ }
29
+ };
30
+ const getClauseOperator = (node, state) => {
31
+ let maybeTargetNode = node.prevSibling || node.parent || node.lastChild;
32
+ while (maybeTargetNode && maybeTargetNode.name === "\u26A0")
33
+ maybeTargetNode = maybeTargetNode.prevSibling;
34
+ if (maybeTargetNode && ["As", "Or", "And"].includes(maybeTargetNode.name)) {
35
+ return vuuCodemirror.getValue(maybeTargetNode, state);
36
+ } else {
37
+ return void 0;
38
+ }
39
+ };
40
+ const getFilterName = (node, state) => {
41
+ if (node.name === "FilterName") {
42
+ return vuuCodemirror.getValue(node, state);
43
+ } else {
44
+ let maybeTargetNode = node.prevSibling || node.parent || node.lastChild;
45
+ while (maybeTargetNode && maybeTargetNode.name !== "FilterName")
46
+ maybeTargetNode = maybeTargetNode.prevSibling;
47
+ if (maybeTargetNode && maybeTargetNode.name === "FilterName") {
48
+ return vuuCodemirror.getValue(node, state);
49
+ }
50
+ }
51
+ };
52
+ const getColumnName = (node, state) => {
53
+ const prevNode = node.prevSibling;
54
+ if (prevNode?.name === "Column") {
55
+ return vuuCodemirror.getValue(prevNode, state);
56
+ } else if (prevNode?.name === "Operator") {
57
+ return getColumnName(prevNode, state);
58
+ }
59
+ };
60
+ const getSetValues = (node, state) => {
61
+ let maybeTargetNode = node.lastChild;
62
+ const values = [];
63
+ while (maybeTargetNode && maybeTargetNode.name !== "In") {
64
+ const value = vuuCodemirror.getValue(maybeTargetNode, state);
65
+ if (value) {
66
+ values.push(value);
67
+ } else {
68
+ break;
69
+ }
70
+ maybeTargetNode = maybeTargetNode.prevSibling;
71
+ }
72
+ return values;
73
+ };
74
+ const useAutoComplete = (suggestionProvider, onSubmit, existingFilter) => {
75
+ const makeSuggestions = react.useCallback(
76
+ async (context, suggestionType, optionalArgs = {}) => {
77
+ const { startsWith = "" } = optionalArgs;
78
+ const options = await suggestionProvider.getSuggestions(
79
+ suggestionType,
80
+ optionalArgs
81
+ );
82
+ return { from: context.pos - startsWith.length, options };
83
+ },
84
+ [suggestionProvider]
85
+ );
86
+ return react.useCallback(
87
+ async (context) => {
88
+ const { state, pos } = context;
89
+ const word = context.matchBefore(/\w*/) ?? {
90
+ from: 0,
91
+ to: 0,
92
+ text: void 0
93
+ };
94
+ const tree = vuuCodemirror.syntaxTree(state);
95
+ const nodeBefore = tree.resolveInner(pos, -1);
96
+ console.log({ nodeBeforeName: nodeBefore.name });
97
+ switch (nodeBefore.name) {
98
+ case "Filter":
99
+ if (context.pos === 0) {
100
+ return makeSuggestions(context, "column");
101
+ } else {
102
+ const clauseOperator = getClauseOperator(nodeBefore, state);
103
+ if (clauseOperator === "as") {
104
+ return makeSuggestions(context, "name");
105
+ } else {
106
+ const filterName = getFilterName(nodeBefore, state);
107
+ return makeSuggestions(context, "save", {
108
+ onSubmit: onSubmit.current,
109
+ existingFilter,
110
+ filterName
111
+ });
112
+ }
113
+ }
114
+ case "String":
115
+ {
116
+ const operator = getOperator(nodeBefore, state);
117
+ const columnName = getColumnName(nodeBefore, state);
118
+ const { from, to } = nodeBefore;
119
+ if (to - from === 2 && context.pos === from + 1) {
120
+ if (columnName && operator) {
121
+ return makeSuggestions(context, "columnValue", {
122
+ columnName,
123
+ operator,
124
+ quoted: true,
125
+ startsWith: word.text
126
+ });
127
+ }
128
+ } else {
129
+ console.log(
130
+ `we have a string, column is ${columnName} ${from} ${to}`
131
+ );
132
+ }
133
+ }
134
+ break;
135
+ case "As":
136
+ return makeSuggestions(context, "name");
137
+ case "FilterName":
138
+ return makeSuggestions(context, "save", {
139
+ onSubmit: onSubmit.current,
140
+ existingFilter,
141
+ filterName: getFilterName(nodeBefore, state)
142
+ });
143
+ case "Column": {
144
+ const columnName = vuuCodemirror.getValue(nodeBefore, state);
145
+ const isPartialMatch = await suggestionProvider.isPartialMatch(
146
+ "column",
147
+ void 0,
148
+ columnName
149
+ );
150
+ if (isPartialMatch) {
151
+ return makeSuggestions(context, "column", {
152
+ startsWith: columnName
153
+ });
154
+ } else {
155
+ return makeSuggestions(context, "operator", { columnName });
156
+ }
157
+ }
158
+ case "\u26A0": {
159
+ const columnName = vuuCodemirror.getNodeByName(nodeBefore, state);
160
+ const operator = getOperator(nodeBefore, state);
161
+ const partialOperator = operator ? void 0 : getPartialOperator(nodeBefore, state, columnName);
162
+ if (partialOperator) {
163
+ return makeSuggestions(context, "operator", {
164
+ columnName,
165
+ startsWith: partialOperator
166
+ });
167
+ } else {
168
+ return makeSuggestions(context, "columnValue", {
169
+ columnName,
170
+ operator,
171
+ startsWith: word.text
172
+ });
173
+ }
174
+ }
175
+ case "Identifier":
176
+ {
177
+ const clauseOperator = getClauseOperator(nodeBefore, state);
178
+ if (clauseOperator === "as") {
179
+ return {
180
+ from: context.pos,
181
+ options: [
182
+ {
183
+ label: "press ENTER to apply filter and save",
184
+ apply: () => onSubmit.current(),
185
+ boost: 5
186
+ }
187
+ ]
188
+ };
189
+ }
190
+ }
191
+ break;
192
+ case "ColumnSetExpression":
193
+ case "Values": {
194
+ const columnName = vuuCodemirror.getNodeByName(nodeBefore, state);
195
+ const selection = getSetValues(nodeBefore, state);
196
+ return makeSuggestions(context, "columnValue", {
197
+ columnName,
198
+ selection
199
+ });
200
+ }
201
+ case "Comma":
202
+ case "LBrack": {
203
+ const columnName = vuuCodemirror.getNodeByName(nodeBefore, state);
204
+ return makeSuggestions(context, "columnValue", { columnName });
205
+ }
206
+ case "ColumnValueExpression":
207
+ {
208
+ const lastToken = nodeBefore.lastChild?.prevSibling;
209
+ if (lastToken?.name === "Column") {
210
+ return makeSuggestions(context, "operator", {
211
+ columnName: vuuCodemirror.getNodeByName(nodeBefore, state)
212
+ });
213
+ } else if (lastToken?.name === "Operator") {
214
+ return makeSuggestions(context, "columnValue", {
215
+ columnName: vuuCodemirror.getNodeByName(lastToken, state),
216
+ operator: vuuCodemirror.getValue(lastToken, state)
217
+ });
218
+ }
219
+ }
220
+ break;
221
+ case "In": {
222
+ return {
223
+ from: context.pos,
224
+ options: [{ label: "[", apply: " [", type: "text" }]
225
+ };
226
+ }
227
+ case "Eq": {
228
+ return makeSuggestions(context, "columnValue", {
229
+ columnName: vuuCodemirror.getNodeByName(nodeBefore, state)
230
+ });
231
+ }
232
+ case "AndExpression":
233
+ case "OrExpression": {
234
+ return makeSuggestions(context, "column");
235
+ }
236
+ }
237
+ },
238
+ [existingFilter, makeSuggestions, onSubmit, suggestionProvider]
239
+ );
240
+ };
241
+
242
+ exports.useAutoComplete = useAutoComplete;
243
+ //# sourceMappingURL=useFilterAutoComplete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFilterAutoComplete.js","sources":["../../src/filter-input/useFilterAutoComplete.ts"],"sourcesContent":["import {\n CompletionContext,\n CompletionSource,\n EditorState,\n getNodeByName,\n getValue,\n SyntaxNode,\n syntaxTree,\n} from \"@vuu-ui/vuu-codemirror\";\nimport { Filter } from \"@vuu-ui/vuu-filter-types\";\nimport { MutableRefObject, useCallback } from \"react\";\nimport {\n IFilterSuggestionProvider,\n SuggestionType,\n} from \"./useCodeMirrorEditor\";\n\nexport type FilterSubmissionMode = \"and\" | \"or\" | \"replace\" | \"tab\";\n\nexport type ApplyCompletion = (mode?: FilterSubmissionMode) => void;\n\nconst getOperator = (node: SyntaxNode, state: EditorState) => {\n let maybeColumnNode = node.prevSibling || node.parent;\n while (\n maybeColumnNode &&\n ![\"Column\", \"Operator\", \"In\"].includes(maybeColumnNode.name)\n ) {\n maybeColumnNode = maybeColumnNode.prevSibling || maybeColumnNode.parent;\n }\n if (maybeColumnNode?.name === \"In\" || maybeColumnNode?.name === \"Operator\") {\n return getValue(maybeColumnNode, state);\n } else {\n return undefined;\n }\n};\n\n// Operators that are more than a single character in length may incur partial matches\n// TODO need to check that previous token is a column\nconst getPartialOperator = (\n maybeOperatorNode: SyntaxNode,\n state: EditorState,\n columnName?: string\n) => {\n const value = getValue(maybeOperatorNode, state);\n if (columnName === undefined || value === columnName) {\n return;\n }\n if (\n [\"contains\", \"ends\", \"starts\"].some((val) =>\n val.startsWith(value.toLowerCase())\n )\n ) {\n return value;\n } else {\n return undefined;\n }\n};\n\nconst getClauseOperator = (node: SyntaxNode, state: EditorState) => {\n let maybeTargetNode = node.prevSibling || node.parent || node.lastChild;\n while (maybeTargetNode && maybeTargetNode.name === \"⚠\")\n maybeTargetNode = maybeTargetNode.prevSibling;\n if (maybeTargetNode && [\"As\", \"Or\", \"And\"].includes(maybeTargetNode.name)) {\n return getValue(maybeTargetNode, state);\n } else {\n return undefined;\n }\n};\n\nconst getFilterName = (node: SyntaxNode, state: EditorState) => {\n if (node.name === \"FilterName\") {\n return getValue(node, state);\n } else {\n let maybeTargetNode = node.prevSibling || node.parent || node.lastChild;\n while (maybeTargetNode && maybeTargetNode.name !== \"FilterName\")\n maybeTargetNode = maybeTargetNode.prevSibling;\n if (maybeTargetNode && maybeTargetNode.name === \"FilterName\") {\n return getValue(node, state);\n }\n }\n};\n\nconst getColumnName = (\n node: SyntaxNode,\n state: EditorState\n): string | undefined => {\n const prevNode = node.prevSibling;\n if (prevNode?.name === \"Column\") {\n return getValue(prevNode, state);\n } else if (prevNode?.name === \"Operator\") {\n return getColumnName(prevNode, state);\n }\n};\n\nconst getSetValues = (node: SyntaxNode, state: EditorState): string[] => {\n let maybeTargetNode = node.lastChild;\n const values: string[] = [];\n while (maybeTargetNode && maybeTargetNode.name !== \"In\") {\n const value = getValue(maybeTargetNode, state);\n if (value) {\n values.push(value);\n } else {\n break;\n }\n maybeTargetNode = maybeTargetNode.prevSibling;\n }\n return values;\n};\nexport const FilterlNamedTerms: readonly string[] = [\n \"Filter\",\n \"ParenthesizedExpression\",\n \"AndExpression\",\n \"OrExpression\",\n \"ColumnValueExpression\",\n \"ColumnSetExpression\",\n \"FilterName\",\n \"Column\",\n \"Operator\",\n \"Values\",\n \"Number\",\n \"String\",\n];\nexport const lastNamedChild = (node: SyntaxNode): SyntaxNode | null => {\n let { lastChild } = node;\n while (lastChild && !FilterlNamedTerms.includes(lastChild.name)) {\n lastChild = lastChild.prevSibling;\n console.log(lastChild?.name);\n }\n return lastChild;\n};\n\nexport const useAutoComplete = (\n suggestionProvider: IFilterSuggestionProvider,\n onSubmit: MutableRefObject<ApplyCompletion>,\n existingFilter?: Filter\n) => {\n const makeSuggestions = useCallback(\n async (\n context: CompletionContext,\n suggestionType: SuggestionType,\n optionalArgs: {\n columnName?: string;\n existingFilter?: Filter;\n filterName?: string;\n operator?: string;\n quoted?: boolean;\n onSubmit?: () => void;\n selection?: string[];\n startsWith?: string;\n } = {}\n ) => {\n const { startsWith = \"\" } = optionalArgs;\n const options = await suggestionProvider.getSuggestions(\n suggestionType,\n optionalArgs\n );\n return { from: context.pos - startsWith.length, options };\n },\n [suggestionProvider]\n );\n\n return useCallback(\n async (context: CompletionContext) => {\n const { state, pos } = context;\n const word = context.matchBefore(/\\w*/) ?? {\n from: 0,\n to: 0,\n text: undefined,\n };\n\n const tree = syntaxTree(state);\n const nodeBefore = tree.resolveInner(pos, -1);\n console.log({ nodeBeforeName: nodeBefore.name });\n\n switch (nodeBefore.name) {\n case \"Filter\":\n if (context.pos === 0) {\n return makeSuggestions(context, \"column\");\n } else {\n const clauseOperator = getClauseOperator(nodeBefore, state);\n if (clauseOperator === \"as\") {\n return makeSuggestions(context, \"name\");\n } else {\n const filterName = getFilterName(nodeBefore, state);\n return makeSuggestions(context, \"save\", {\n onSubmit: onSubmit.current,\n existingFilter,\n filterName,\n });\n }\n }\n\n case \"String\":\n {\n // we only encounter a string as the right hand operand of a conditional expression\n const operator = getOperator(nodeBefore, state);\n const columnName = getColumnName(nodeBefore, state);\n // are we inside the string or immediately after it\n const { from, to } = nodeBefore;\n if (to - from === 2 && context.pos === from + 1) {\n // We are in an empty string, i.e between two quotes\n if (columnName && operator) {\n return makeSuggestions(context, \"columnValue\", {\n columnName,\n operator,\n quoted: true,\n startsWith: word.text,\n });\n }\n } else {\n console.log(\n `we have a string, column is ${columnName} ${from} ${to}`\n );\n }\n }\n break;\n\n case \"As\":\n return makeSuggestions(context, \"name\");\n\n case \"FilterName\":\n return makeSuggestions(context, \"save\", {\n onSubmit: onSubmit.current,\n existingFilter,\n filterName: getFilterName(nodeBefore, state),\n });\n\n case \"Column\": {\n const columnName = getValue(nodeBefore, state);\n const isPartialMatch = await suggestionProvider.isPartialMatch(\n \"column\",\n undefined,\n columnName\n );\n if (isPartialMatch) {\n return makeSuggestions(context, \"column\", {\n startsWith: columnName,\n });\n } else {\n return makeSuggestions(context, \"operator\", { columnName });\n }\n }\n\n case \"⚠\": {\n const columnName = getNodeByName(nodeBefore, state);\n const operator = getOperator(nodeBefore, state);\n // TODO check if we're mnatching a partial jojn operator\n const partialOperator = operator\n ? undefined\n : getPartialOperator(nodeBefore, state, columnName);\n\n if (partialOperator) {\n return makeSuggestions(context, \"operator\", {\n columnName,\n startsWith: partialOperator,\n });\n } else {\n return makeSuggestions(context, \"columnValue\", {\n columnName,\n operator,\n startsWith: word.text,\n });\n }\n }\n\n case \"Identifier\":\n {\n const clauseOperator = getClauseOperator(nodeBefore, state);\n if (clauseOperator === \"as\") {\n return {\n from: context.pos,\n options: [\n {\n label: \"press ENTER to apply filter and save\",\n apply: () => onSubmit.current(),\n boost: 5,\n },\n ],\n };\n }\n }\n break;\n case \"ColumnSetExpression\":\n case \"Values\": {\n const columnName = getNodeByName(nodeBefore, state);\n const selection = getSetValues(nodeBefore, state);\n return makeSuggestions(context, \"columnValue\", {\n columnName,\n selection,\n });\n }\n case \"Comma\":\n case \"LBrack\": {\n const columnName = getNodeByName(nodeBefore, state) as string;\n return makeSuggestions(context, \"columnValue\", { columnName });\n }\n\n case \"ColumnValueExpression\":\n {\n const lastToken = nodeBefore.lastChild?.prevSibling;\n if (lastToken?.name === \"Column\") {\n return makeSuggestions(context, \"operator\", {\n columnName: getNodeByName(nodeBefore, state),\n });\n } else if (lastToken?.name === \"Operator\") {\n return makeSuggestions(context, \"columnValue\", {\n columnName: getNodeByName(lastToken, state),\n operator: getValue(lastToken, state),\n });\n }\n }\n break;\n\n case \"In\": {\n return {\n from: context.pos,\n options: [{ label: \"[\", apply: \" [\", type: \"text\" }],\n };\n }\n\n case \"Eq\": {\n return makeSuggestions(context, \"columnValue\", {\n columnName: getNodeByName(nodeBefore, state),\n });\n }\n\n case \"AndExpression\":\n case \"OrExpression\": {\n return makeSuggestions(context, \"column\");\n }\n\n default:\n }\n },\n [existingFilter, makeSuggestions, onSubmit, suggestionProvider]\n ) as CompletionSource;\n};\n"],"names":["getValue","useCallback","syntaxTree","getNodeByName"],"mappings":"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"}
@@ -0,0 +1,206 @@
1
+ 'use strict';
2
+
3
+ var vuuCodemirror = require('@vuu-ui/vuu-codemirror');
4
+ var vuuDataReact = require('@vuu-ui/vuu-data-react');
5
+ var react = require('react');
6
+ var filterInfo = require('./filterInfo.js');
7
+
8
+ const NO_NAMED_FILTERS = [];
9
+ const NONE = {};
10
+ const saveAsTab = (onSubmit) => [
11
+ {
12
+ label: "Press ENTER to create TAB",
13
+ apply: () => onSubmit("tab"),
14
+ boost: 6
15
+ }
16
+ ];
17
+ const makeSaveOrExtendSuggestions = (onSubmit, existingFilter, withJoinSuggestions = true) => {
18
+ const result = existingFilter ? [
19
+ {
20
+ label: "REPLACE existing filter",
21
+ apply: () => onSubmit("replace"),
22
+ boost: 8
23
+ },
24
+ {
25
+ label: "AND existing filter",
26
+ apply: () => onSubmit("and"),
27
+ boost: 7
28
+ },
29
+ {
30
+ label: "OR existing filter",
31
+ apply: () => onSubmit("or"),
32
+ boost: 7
33
+ }
34
+ ] : [
35
+ {
36
+ label: "Press ENTER to submit",
37
+ apply: () => onSubmit(),
38
+ boost: 6
39
+ }
40
+ ];
41
+ return withJoinSuggestions ? result.concat(vuuCodemirror.booleanJoinSuggestions).concat(vuuCodemirror.asNameSuggestion) : result;
42
+ };
43
+ const promptToSaveOrExtend = (onSubmit, existingFilter) => makeSaveOrExtendSuggestions(onSubmit, existingFilter, true);
44
+ const promptToSave = (onSubmit) => makeSaveOrExtendSuggestions(onSubmit, void 0);
45
+ const getSaveSuggestions = ({
46
+ existingFilter,
47
+ filterName,
48
+ onSubmit,
49
+ saveOptions
50
+ }) => {
51
+ const includeTabSuggestion = filterName && saveOptions.allowSaveAsTab;
52
+ const result = existingFilter ? promptToSaveOrExtend(onSubmit, existingFilter) : promptToSave(onSubmit);
53
+ if (includeTabSuggestion) {
54
+ return result.concat(saveAsTab(onSubmit));
55
+ } else {
56
+ return result;
57
+ }
58
+ };
59
+ const suggestColumns = (columns) => columns.map((column) => ({
60
+ boost: 5,
61
+ label: column.name
62
+ }));
63
+ const suggestNamedFilters = (namedFilters) => namedFilters ? Array.from(namedFilters.entries()).map(([filterName, filterQuery]) => ({
64
+ info: () => filterInfo.filterInfo(filterName, filterQuery),
65
+ label: filterName,
66
+ type: "filter"
67
+ })) : NO_NAMED_FILTERS;
68
+ const doneCommand = {
69
+ label: "Done",
70
+ apply: "] ",
71
+ type: "keyword",
72
+ boost: 10
73
+ };
74
+ const withApplySpace = (suggestions, startsWith = "") => suggestions.filter((sugg) => startsWith === "" || sugg.label.startsWith(startsWith)).map((suggestion) => ({
75
+ ...suggestion,
76
+ apply: suggestion.label + " "
77
+ }));
78
+ const defaultSaveOptions = {
79
+ allowReplace: true
80
+ };
81
+ const useFilterSuggestionProvider = ({
82
+ columns,
83
+ namedFilters,
84
+ saveOptions = defaultSaveOptions,
85
+ table,
86
+ typeaheadHook: useTypeahead = vuuDataReact.useTypeaheadSuggestions
87
+ }) => {
88
+ const latestSuggestionsRef = react.useRef();
89
+ const getTypeaheadSuggestions = useTypeahead();
90
+ const getSuggestions = react.useCallback(
91
+ async (suggestionType, options = NONE) => {
92
+ const {
93
+ columnName,
94
+ existingFilter,
95
+ filterName,
96
+ operator,
97
+ quoted: autoQuoted,
98
+ onSubmit,
99
+ startsWith,
100
+ selection
101
+ } = options;
102
+ switch (suggestionType) {
103
+ case "operator":
104
+ {
105
+ const column = columns.find((col) => col.name === columnName);
106
+ if (column) {
107
+ switch (column.serverDataType) {
108
+ case "string":
109
+ case "char":
110
+ return withApplySpace(vuuCodemirror.stringOperators, startsWith);
111
+ case "int":
112
+ case "long":
113
+ case "double":
114
+ return withApplySpace(vuuCodemirror.numericOperators);
115
+ }
116
+ } else {
117
+ console.warn(`'${columnName}' does not match any column name`);
118
+ }
119
+ }
120
+ break;
121
+ case "column": {
122
+ const columnSuggestions = await suggestColumns(columns);
123
+ const filterSuggestions = await suggestNamedFilters(namedFilters);
124
+ return (latestSuggestionsRef.current = withApplySpace(columnSuggestions)).concat(
125
+ withApplySpace(filterSuggestions)
126
+ );
127
+ }
128
+ case "columnValue":
129
+ {
130
+ if (columnName) {
131
+ const column = columns.find((col) => col.name === columnName);
132
+ if (!column) {
133
+ throw Error(
134
+ `useFilterSUggestionProvider no column ${columnName}`
135
+ );
136
+ }
137
+ const prefix = Array.isArray(selection) ? selection.length === 0 ? "[" : "," : "";
138
+ const params = vuuDataReact.getTypeaheadParams(
139
+ table,
140
+ columnName,
141
+ startsWith
142
+ );
143
+ const suggestions = await getTypeaheadSuggestions(params);
144
+ const isIllustration = operator === "starts";
145
+ latestSuggestionsRef.current = vuuCodemirror.toSuggestions(suggestions, {
146
+ moveCursorToEnd: autoQuoted,
147
+ quoted: column?.serverDataType === "string" && !autoQuoted,
148
+ suffix: autoQuoted ? "" : " ",
149
+ prefix: isIllustration ? startsWith : prefix,
150
+ isIllustration
151
+ });
152
+ if (Array.isArray(selection) && selection?.length > 1) {
153
+ return [doneCommand, ...latestSuggestionsRef.current];
154
+ }
155
+ return latestSuggestionsRef.current;
156
+ }
157
+ }
158
+ break;
159
+ case "save": {
160
+ if (typeof onSubmit !== "function") {
161
+ throw Error(
162
+ "useFilterSuggestionProvider, onSubmit must be supplied for 'save' suggestions"
163
+ );
164
+ }
165
+ return await getSaveSuggestions({
166
+ existingFilter,
167
+ filterName,
168
+ onSubmit,
169
+ saveOptions
170
+ });
171
+ }
172
+ case "name":
173
+ return await vuuCodemirror.getNamePrompt("filter");
174
+ }
175
+ return [];
176
+ },
177
+ [columns, getTypeaheadSuggestions, namedFilters, saveOptions, table]
178
+ );
179
+ const isPartialMatch = react.useCallback(
180
+ async (valueType, columnName, pattern) => {
181
+ const suggestions = (
182
+ // latestSuggestions && latestSuggestions.length > 0
183
+ // ? latestSuggestions
184
+ await getSuggestions(valueType, { columnName })
185
+ );
186
+ if (pattern && suggestions) {
187
+ for (const option of suggestions) {
188
+ if (option.label === pattern) {
189
+ return false;
190
+ } else if (option.label.startsWith(pattern)) {
191
+ return true;
192
+ }
193
+ }
194
+ }
195
+ return false;
196
+ },
197
+ [getSuggestions]
198
+ );
199
+ return {
200
+ getSuggestions,
201
+ isPartialMatch
202
+ };
203
+ };
204
+
205
+ exports.useFilterSuggestionProvider = useFilterSuggestionProvider;
206
+ //# sourceMappingURL=useFilterSuggestionProvider.js.map