@seed-ship/mcp-ui-solid 2.0.1 → 2.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/components/AutocompleteDropdown.cjs +201 -0
- package/dist/components/AutocompleteDropdown.cjs.map +1 -0
- package/dist/components/AutocompleteDropdown.d.ts +71 -0
- package/dist/components/AutocompleteDropdown.d.ts.map +1 -0
- package/dist/components/AutocompleteDropdown.js +201 -0
- package/dist/components/AutocompleteDropdown.js.map +1 -0
- package/dist/components/AutocompleteFormField.cjs +289 -0
- package/dist/components/AutocompleteFormField.cjs.map +1 -0
- package/dist/components/AutocompleteFormField.d.ts +52 -0
- package/dist/components/AutocompleteFormField.d.ts.map +1 -0
- package/dist/components/AutocompleteFormField.js +289 -0
- package/dist/components/AutocompleteFormField.js.map +1 -0
- package/dist/components/DraggableGridItem.cjs +133 -0
- package/dist/components/DraggableGridItem.cjs.map +1 -0
- package/dist/components/DraggableGridItem.d.ts +95 -0
- package/dist/components/DraggableGridItem.d.ts.map +1 -0
- package/dist/components/DraggableGridItem.js +133 -0
- package/dist/components/DraggableGridItem.js.map +1 -0
- package/dist/components/EditableUIResourceRenderer.cjs +199 -0
- package/dist/components/EditableUIResourceRenderer.cjs.map +1 -0
- package/dist/components/EditableUIResourceRenderer.d.ts +43 -0
- package/dist/components/EditableUIResourceRenderer.d.ts.map +1 -0
- package/dist/components/EditableUIResourceRenderer.js +199 -0
- package/dist/components/EditableUIResourceRenderer.js.map +1 -0
- package/dist/components/GhostText.cjs +105 -0
- package/dist/components/GhostText.cjs.map +1 -0
- package/dist/components/GhostText.d.ts +113 -0
- package/dist/components/GhostText.d.ts.map +1 -0
- package/dist/components/GhostText.js +105 -0
- package/dist/components/GhostText.js.map +1 -0
- package/dist/components/ResizeHandle.cjs +177 -0
- package/dist/components/ResizeHandle.cjs.map +1 -0
- package/dist/components/ResizeHandle.d.ts +50 -0
- package/dist/components/ResizeHandle.d.ts.map +1 -0
- package/dist/components/ResizeHandle.js +177 -0
- package/dist/components/ResizeHandle.js.map +1 -0
- package/dist/context/AutocompleteContext.cjs +158 -0
- package/dist/context/AutocompleteContext.cjs.map +1 -0
- package/dist/context/AutocompleteContext.d.ts +77 -0
- package/dist/context/AutocompleteContext.d.ts.map +1 -0
- package/dist/context/AutocompleteContext.js +158 -0
- package/dist/context/AutocompleteContext.js.map +1 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useAutocomplete.cjs +242 -0
- package/dist/hooks/useAutocomplete.cjs.map +1 -0
- package/dist/hooks/useAutocomplete.d.ts +119 -0
- package/dist/hooks/useAutocomplete.d.ts.map +1 -0
- package/dist/hooks/useAutocomplete.js +242 -0
- package/dist/hooks/useAutocomplete.js.map +1 -0
- package/dist/hooks/useDragDrop.cjs +170 -0
- package/dist/hooks/useDragDrop.cjs.map +1 -0
- package/dist/hooks/useDragDrop.d.ts +100 -0
- package/dist/hooks/useDragDrop.d.ts.map +1 -0
- package/dist/hooks/useDragDrop.js +170 -0
- package/dist/hooks/useDragDrop.js.map +1 -0
- package/dist/hooks/useResize.cjs +209 -0
- package/dist/hooks/useResize.cjs.map +1 -0
- package/dist/hooks/useResize.d.ts +87 -0
- package/dist/hooks/useResize.d.ts.map +1 -0
- package/dist/hooks/useResize.js +209 -0
- package/dist/hooks/useResize.js.map +1 -0
- package/dist/hooks.cjs +6 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +6 -0
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.js +6 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +29 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/duckdb.cjs +192 -0
- package/dist/plugins/duckdb.cjs.map +1 -0
- package/dist/plugins/duckdb.d.ts +20 -0
- package/dist/plugins/duckdb.d.ts.map +1 -0
- package/dist/plugins/duckdb.js +170 -0
- package/dist/plugins/duckdb.js.map +1 -0
- package/dist/plugins/groq.cjs +97 -0
- package/dist/plugins/groq.cjs.map +1 -0
- package/dist/plugins/groq.d.ts +13 -0
- package/dist/plugins/groq.d.ts.map +1 -0
- package/dist/plugins/groq.js +97 -0
- package/dist/plugins/groq.js.map +1 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/rest.cjs +92 -0
- package/dist/plugins/rest.cjs.map +1 -0
- package/dist/plugins/rest.d.ts +13 -0
- package/dist/plugins/rest.d.ts.map +1 -0
- package/dist/plugins/rest.js +92 -0
- package/dist/plugins/rest.js.map +1 -0
- package/dist/plugins/supabase.cjs +79 -0
- package/dist/plugins/supabase.cjs.map +1 -0
- package/dist/plugins/supabase.d.ts +13 -0
- package/dist/plugins/supabase.d.ts.map +1 -0
- package/dist/plugins/supabase.js +79 -0
- package/dist/plugins/supabase.js.map +1 -0
- package/dist/types/index.d.ts +430 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types.d.cts +430 -0
- package/dist/types.d.ts +430 -0
- package/esbuild-why-Full bundle (with deps).html +51 -0
- package/esbuild-why-Hooks only.html +51 -0
- package/esbuild-why-Streaming renderer.html +51 -0
- package/package.json +16 -1
- package/src/components/AutocompleteDropdown.tsx +329 -0
- package/src/components/AutocompleteFormField.tsx +288 -0
- package/src/components/DraggableGridItem.tsx +274 -0
- package/src/components/EditableUIResourceRenderer.tsx +268 -0
- package/src/components/GhostText.tsx +262 -0
- package/src/components/ResizeHandle.tsx +267 -0
- package/src/context/AutocompleteContext.tsx +317 -0
- package/src/hooks/index.ts +23 -0
- package/src/hooks/useAutocomplete.test.ts +334 -0
- package/src/hooks/useAutocomplete.ts +482 -0
- package/src/hooks/useDragDrop.test.ts +355 -0
- package/src/hooks/useDragDrop.ts +379 -0
- package/src/hooks/useResize.test.ts +313 -0
- package/src/hooks/useResize.ts +372 -0
- package/src/index.ts +71 -0
- package/src/plugins/duckdb.ts +269 -0
- package/src/plugins/groq.ts +137 -0
- package/src/plugins/index.ts +14 -0
- package/src/plugins/rest.ts +147 -0
- package/src/plugins/supabase.ts +120 -0
- package/src/styles/autocomplete.css +356 -0
- package/src/styles/drag-drop.css +297 -0
- package/src/styles/index.css +7 -0
- package/src/types/index.ts +529 -0
- package/src/vite-env.d.ts +18 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vite.config.ts +2 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const web = require("solid-js/web");
|
|
4
|
+
const solidJs = require("solid-js");
|
|
5
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<strong class=mcp-autocomplete-highlight>`), _tmpl$2 = /* @__PURE__ */ web.template(`<span class=mcp-autocomplete-option-icon>`), _tmpl$3 = /* @__PURE__ */ web.template(`<span class=mcp-autocomplete-option-description>`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-option-content><!$><!/><div class=mcp-autocomplete-option-text><span class=mcp-autocomplete-option-label></span><!$><!/>`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-loading style="padding:12px 16px;color:#6b7280;font-size:0.875rem;display:flex;align-items:center;gap:8px"><span style="display:inline-block;width:14px;height:14px;border:2px solid #e5e7eb;border-top-color:#3b82f6;border-radius:50%;animation:mcp-spin 0.6s linear infinite"></span><!$><!/>`), _tmpl$6 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-empty style="padding:12px 16px;color:#9ca3af;font-size:0.875rem;text-align:center">`), _tmpl$7 = /* @__PURE__ */ web.template(`<ul class=mcp-autocomplete-options style="margin:0;padding:4px 0;list-style:none">`), _tmpl$8 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-footer style="padding:6px 12px;border-top:1px solid #e5e7eb;background-color:#f9fafb;font-size:0.75rem;color:#6b7280"><kbd style="background-color:#e5e7eb;padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">↑</kbd> <kbd style="background-color:#e5e7eb;padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">↓</kbd> to navigate, <kbd style="background-color:#e5e7eb;padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">Enter</kbd> to select, <kbd style="background-color:#e5e7eb;padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">Esc</kbd> to dismiss`), _tmpl$9 = /* @__PURE__ */ web.template(`<div role=listbox aria-label=Suggestions><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$0 = /* @__PURE__ */ web.template(`<li role=option style="padding:8px 16px;font-size:0.875rem;transition:background-color 150ms ease">`);
|
|
6
|
+
function highlightText(text, match) {
|
|
7
|
+
if (!match || !text) {
|
|
8
|
+
return text;
|
|
9
|
+
}
|
|
10
|
+
const lowerText = text.toLowerCase();
|
|
11
|
+
const lowerMatch = match.toLowerCase();
|
|
12
|
+
const startIndex = lowerText.indexOf(lowerMatch);
|
|
13
|
+
if (startIndex === -1) {
|
|
14
|
+
return text;
|
|
15
|
+
}
|
|
16
|
+
const before = text.slice(0, startIndex);
|
|
17
|
+
const matched = text.slice(startIndex, startIndex + match.length);
|
|
18
|
+
const after = text.slice(startIndex + match.length);
|
|
19
|
+
return [before, (() => {
|
|
20
|
+
var _el$ = web.getNextElement(_tmpl$);
|
|
21
|
+
web.insert(_el$, matched);
|
|
22
|
+
return _el$;
|
|
23
|
+
})(), after];
|
|
24
|
+
}
|
|
25
|
+
const DefaultOptionRenderer = (props) => {
|
|
26
|
+
const displayLabel = solidJs.createMemo(() => props.option.label || props.option.value);
|
|
27
|
+
return (() => {
|
|
28
|
+
var _el$2 = web.getNextElement(_tmpl$4), _el$9 = _el$2.firstChild, [_el$0, _co$2] = web.getNextMarker(_el$9.nextSibling), _el$4 = _el$0.nextSibling, _el$5 = _el$4.firstChild, _el$7 = _el$5.nextSibling, [_el$8, _co$] = web.getNextMarker(_el$7.nextSibling);
|
|
29
|
+
web.insert(_el$2, web.createComponent(solidJs.Show, {
|
|
30
|
+
get when() {
|
|
31
|
+
return props.option.icon;
|
|
32
|
+
},
|
|
33
|
+
get children() {
|
|
34
|
+
var _el$3 = web.getNextElement(_tmpl$2);
|
|
35
|
+
web.insert(_el$3, () => props.option.icon);
|
|
36
|
+
return _el$3;
|
|
37
|
+
}
|
|
38
|
+
}), _el$0, _co$2);
|
|
39
|
+
web.insert(_el$5, () => highlightText(displayLabel(), props.highlightMatch));
|
|
40
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
41
|
+
get when() {
|
|
42
|
+
return props.option.description;
|
|
43
|
+
},
|
|
44
|
+
get children() {
|
|
45
|
+
var _el$6 = web.getNextElement(_tmpl$3);
|
|
46
|
+
web.insert(_el$6, () => props.option.description);
|
|
47
|
+
return _el$6;
|
|
48
|
+
}
|
|
49
|
+
}), _el$8, _co$);
|
|
50
|
+
return _el$2;
|
|
51
|
+
})();
|
|
52
|
+
};
|
|
53
|
+
const AutocompleteDropdown = (props) => {
|
|
54
|
+
const positionStyles = solidJs.createMemo(() => {
|
|
55
|
+
if (props.position === "top") {
|
|
56
|
+
return {
|
|
57
|
+
bottom: "100%",
|
|
58
|
+
"margin-bottom": "4px"
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
top: "100%",
|
|
63
|
+
"margin-top": "4px"
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
const containerStyles = solidJs.createMemo(() => ({
|
|
67
|
+
position: "absolute",
|
|
68
|
+
left: "0",
|
|
69
|
+
right: "0",
|
|
70
|
+
"z-index": "50",
|
|
71
|
+
"background-color": "#ffffff",
|
|
72
|
+
border: "1px solid #e5e7eb",
|
|
73
|
+
"border-radius": "6px",
|
|
74
|
+
"box-shadow": "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
75
|
+
"max-height": props.maxHeight || "240px",
|
|
76
|
+
overflow: "auto",
|
|
77
|
+
...positionStyles()
|
|
78
|
+
}));
|
|
79
|
+
return web.createComponent(solidJs.Show, {
|
|
80
|
+
get when() {
|
|
81
|
+
return props.isOpen;
|
|
82
|
+
},
|
|
83
|
+
get children() {
|
|
84
|
+
var _el$1 = web.getNextElement(_tmpl$9), _el$24 = _el$1.firstChild, [_el$25, _co$4] = web.getNextMarker(_el$24.nextSibling), _el$26 = _el$25.nextSibling, [_el$27, _co$5] = web.getNextMarker(_el$26.nextSibling), _el$28 = _el$27.nextSibling, [_el$29, _co$6] = web.getNextMarker(_el$28.nextSibling), _el$30 = _el$29.nextSibling, [_el$31, _co$7] = web.getNextMarker(_el$30.nextSibling);
|
|
85
|
+
web.insert(_el$1, web.createComponent(solidJs.Show, {
|
|
86
|
+
get when() {
|
|
87
|
+
return props.isLoading;
|
|
88
|
+
},
|
|
89
|
+
get children() {
|
|
90
|
+
var _el$10 = web.getNextElement(_tmpl$5), _el$11 = _el$10.firstChild, _el$12 = _el$11.nextSibling, [_el$13, _co$3] = web.getNextMarker(_el$12.nextSibling);
|
|
91
|
+
web.insert(_el$10, () => props.loadingMessage || "Loading...", _el$13, _co$3);
|
|
92
|
+
return _el$10;
|
|
93
|
+
}
|
|
94
|
+
}), _el$25, _co$4);
|
|
95
|
+
web.insert(_el$1, web.createComponent(solidJs.Show, {
|
|
96
|
+
get when() {
|
|
97
|
+
return web.memo(() => !!!props.isLoading)() && props.options.length === 0;
|
|
98
|
+
},
|
|
99
|
+
get children() {
|
|
100
|
+
var _el$14 = web.getNextElement(_tmpl$6);
|
|
101
|
+
web.insert(_el$14, () => props.emptyMessage || "No suggestions found");
|
|
102
|
+
return _el$14;
|
|
103
|
+
}
|
|
104
|
+
}), _el$27, _co$5);
|
|
105
|
+
web.insert(_el$1, web.createComponent(solidJs.Show, {
|
|
106
|
+
get when() {
|
|
107
|
+
return web.memo(() => !!!props.isLoading)() && props.options.length > 0;
|
|
108
|
+
},
|
|
109
|
+
get children() {
|
|
110
|
+
var _el$15 = web.getNextElement(_tmpl$7);
|
|
111
|
+
web.insert(_el$15, web.createComponent(solidJs.For, {
|
|
112
|
+
get each() {
|
|
113
|
+
return props.options;
|
|
114
|
+
},
|
|
115
|
+
children: (option, index) => {
|
|
116
|
+
const isSelected = () => index() === props.selectedIndex;
|
|
117
|
+
const isDisabled = () => option.disabled;
|
|
118
|
+
return (() => {
|
|
119
|
+
var _el$32 = web.getNextElement(_tmpl$0);
|
|
120
|
+
_el$32.addEventListener("mouseenter", () => {
|
|
121
|
+
var _a;
|
|
122
|
+
if (!isDisabled()) {
|
|
123
|
+
(_a = props.onHover) == null ? void 0 : _a.call(props, index());
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
_el$32.$$click = () => {
|
|
127
|
+
if (!isDisabled()) {
|
|
128
|
+
props.onSelect(option);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
web.insert(_el$32, web.createComponent(solidJs.Show, {
|
|
132
|
+
get when() {
|
|
133
|
+
return props.renderOption;
|
|
134
|
+
},
|
|
135
|
+
get fallback() {
|
|
136
|
+
return web.createComponent(DefaultOptionRenderer, {
|
|
137
|
+
option,
|
|
138
|
+
get isSelected() {
|
|
139
|
+
return isSelected();
|
|
140
|
+
},
|
|
141
|
+
get highlightMatch() {
|
|
142
|
+
return props.highlightMatch;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
get children() {
|
|
147
|
+
return props.renderOption(option, isSelected());
|
|
148
|
+
}
|
|
149
|
+
}));
|
|
150
|
+
web.effect((_p$) => {
|
|
151
|
+
var _v$3 = isSelected(), _v$4 = isDisabled(), _v$5 = `mcp-autocomplete-option ${isSelected() ? "mcp-autocomplete-option-selected" : ""} ${isDisabled() ? "mcp-autocomplete-option-disabled" : ""}`, _v$6 = isDisabled() ? "not-allowed" : "pointer", _v$7 = isSelected() ? "#eff6ff" : "transparent", _v$8 = isDisabled() ? "#9ca3af" : "#374151";
|
|
152
|
+
_v$3 !== _p$.e && web.setAttribute(_el$32, "aria-selected", _p$.e = _v$3);
|
|
153
|
+
_v$4 !== _p$.t && web.setAttribute(_el$32, "aria-disabled", _p$.t = _v$4);
|
|
154
|
+
_v$5 !== _p$.a && web.className(_el$32, _p$.a = _v$5);
|
|
155
|
+
_v$6 !== _p$.o && web.setStyleProperty(_el$32, "cursor", _p$.o = _v$6);
|
|
156
|
+
_v$7 !== _p$.i && web.setStyleProperty(_el$32, "background-color", _p$.i = _v$7);
|
|
157
|
+
_v$8 !== _p$.n && web.setStyleProperty(_el$32, "color", _p$.n = _v$8);
|
|
158
|
+
return _p$;
|
|
159
|
+
}, {
|
|
160
|
+
e: void 0,
|
|
161
|
+
t: void 0,
|
|
162
|
+
a: void 0,
|
|
163
|
+
o: void 0,
|
|
164
|
+
i: void 0,
|
|
165
|
+
n: void 0
|
|
166
|
+
});
|
|
167
|
+
web.runHydrationEvents();
|
|
168
|
+
return _el$32;
|
|
169
|
+
})();
|
|
170
|
+
}
|
|
171
|
+
}));
|
|
172
|
+
return _el$15;
|
|
173
|
+
}
|
|
174
|
+
}), _el$29, _co$6);
|
|
175
|
+
web.insert(_el$1, web.createComponent(solidJs.Show, {
|
|
176
|
+
get when() {
|
|
177
|
+
return web.memo(() => !!!props.isLoading)() && props.options.length > 0;
|
|
178
|
+
},
|
|
179
|
+
get children() {
|
|
180
|
+
var _el$16 = web.getNextElement(_tmpl$8), _el$17 = _el$16.firstChild, _el$18 = _el$17.nextSibling, _el$19 = _el$18.nextSibling, _el$20 = _el$19.nextSibling, _el$21 = _el$20.nextSibling, _el$22 = _el$21.nextSibling;
|
|
181
|
+
_el$22.nextSibling;
|
|
182
|
+
return _el$16;
|
|
183
|
+
}
|
|
184
|
+
}), _el$31, _co$7);
|
|
185
|
+
web.effect((_p$) => {
|
|
186
|
+
var _v$ = `mcp-autocomplete-dropdown ${props.class || ""}`, _v$2 = containerStyles();
|
|
187
|
+
_v$ !== _p$.e && web.className(_el$1, _p$.e = _v$);
|
|
188
|
+
_p$.t = web.style(_el$1, _v$2, _p$.t);
|
|
189
|
+
return _p$;
|
|
190
|
+
}, {
|
|
191
|
+
e: void 0,
|
|
192
|
+
t: void 0
|
|
193
|
+
});
|
|
194
|
+
return _el$1;
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
web.delegateEvents(["click"]);
|
|
199
|
+
exports.AutocompleteDropdown = AutocompleteDropdown;
|
|
200
|
+
exports.default = AutocompleteDropdown;
|
|
201
|
+
//# sourceMappingURL=AutocompleteDropdown.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutocompleteDropdown.cjs","sources":["../../src/components/AutocompleteDropdown.tsx"],"sourcesContent":["/**\n * AutocompleteDropdown Component\n * Displays data-driven dropdown suggestions\n *\n * Sprint Autocomplete Feature\n */\n\nimport { Component, For, Show, createMemo, JSX } from 'solid-js'\nimport type { AutocompleteOption } from '../types'\n\n/**\n * Props for AutocompleteDropdown\n */\nexport interface AutocompleteDropdownProps {\n /**\n * Options to display\n */\n options: AutocompleteOption[]\n\n /**\n * Currently selected index\n */\n selectedIndex: number\n\n /**\n * Whether dropdown is visible\n */\n isOpen: boolean\n\n /**\n * Callback when option is selected\n */\n onSelect: (option: AutocompleteOption) => void\n\n /**\n * Callback when option is hovered\n */\n onHover?: (index: number) => void\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n\n /**\n * Custom class\n */\n class?: string\n\n /**\n * Max height\n */\n maxHeight?: string\n\n /**\n * Empty state message\n */\n emptyMessage?: string\n\n /**\n * Loading message\n */\n loadingMessage?: string\n\n /**\n * Highlight matching text in options\n */\n highlightMatch?: string\n\n /**\n * Position (default: 'bottom')\n */\n position?: 'top' | 'bottom'\n\n /**\n * Custom option renderer\n */\n renderOption?: (option: AutocompleteOption, isSelected: boolean) => JSX.Element\n}\n\n/**\n * Highlight matching text\n */\nfunction highlightText(text: string, match?: string): JSX.Element {\n if (!match || !text) {\n return <>{text}</>\n }\n\n const lowerText = text.toLowerCase()\n const lowerMatch = match.toLowerCase()\n const startIndex = lowerText.indexOf(lowerMatch)\n\n if (startIndex === -1) {\n return <>{text}</>\n }\n\n const before = text.slice(0, startIndex)\n const matched = text.slice(startIndex, startIndex + match.length)\n const after = text.slice(startIndex + match.length)\n\n return (\n <>\n {before}\n <strong class=\"mcp-autocomplete-highlight\">{matched}</strong>\n {after}\n </>\n )\n}\n\n/**\n * Default option renderer\n */\nconst DefaultOptionRenderer: Component<{\n option: AutocompleteOption\n isSelected: boolean\n highlightMatch?: string\n}> = (props) => {\n const displayLabel = createMemo(() =>\n props.option.label || props.option.value\n )\n\n return (\n <div class=\"mcp-autocomplete-option-content\">\n <Show when={props.option.icon}>\n <span class=\"mcp-autocomplete-option-icon\">{props.option.icon}</span>\n </Show>\n <div class=\"mcp-autocomplete-option-text\">\n <span class=\"mcp-autocomplete-option-label\">\n {highlightText(displayLabel(), props.highlightMatch)}\n </span>\n <Show when={props.option.description}>\n <span class=\"mcp-autocomplete-option-description\">\n {props.option.description}\n </span>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * AutocompleteDropdown Component\n */\nexport const AutocompleteDropdown: Component<AutocompleteDropdownProps> = (props) => {\n const positionStyles = createMemo((): JSX.CSSProperties => {\n if (props.position === 'top') {\n return {\n bottom: '100%',\n 'margin-bottom': '4px'\n }\n }\n return {\n top: '100%',\n 'margin-top': '4px'\n }\n })\n\n const containerStyles = createMemo((): JSX.CSSProperties => ({\n position: 'absolute',\n left: '0',\n right: '0',\n 'z-index': '50',\n 'background-color': '#ffffff',\n border: '1px solid #e5e7eb',\n 'border-radius': '6px',\n 'box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n 'max-height': props.maxHeight || '240px',\n overflow: 'auto',\n ...positionStyles()\n }))\n\n return (\n <Show when={props.isOpen}>\n <div\n class={`mcp-autocomplete-dropdown ${props.class || ''}`}\n style={containerStyles()}\n role=\"listbox\"\n aria-label=\"Suggestions\"\n >\n {/* Loading state */}\n <Show when={props.isLoading}>\n <div\n class=\"mcp-autocomplete-loading\"\n style={{\n padding: '12px 16px',\n color: '#6b7280',\n 'font-size': '0.875rem',\n display: 'flex',\n 'align-items': 'center',\n gap: '8px'\n }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '14px',\n height: '14px',\n border: '2px solid #e5e7eb',\n 'border-top-color': '#3b82f6',\n 'border-radius': '50%',\n animation: 'mcp-spin 0.6s linear infinite'\n }}\n />\n {props.loadingMessage || 'Loading...'}\n </div>\n </Show>\n\n {/* Empty state */}\n <Show when={!props.isLoading && props.options.length === 0}>\n <div\n class=\"mcp-autocomplete-empty\"\n style={{\n padding: '12px 16px',\n color: '#9ca3af',\n 'font-size': '0.875rem',\n 'text-align': 'center'\n }}\n >\n {props.emptyMessage || 'No suggestions found'}\n </div>\n </Show>\n\n {/* Options list */}\n <Show when={!props.isLoading && props.options.length > 0}>\n <ul\n class=\"mcp-autocomplete-options\"\n style={{ margin: '0', padding: '4px 0', 'list-style': 'none' }}\n >\n <For each={props.options}>\n {(option, index) => {\n const isSelected = () => index() === props.selectedIndex\n const isDisabled = () => option.disabled\n\n return (\n <li\n role=\"option\"\n aria-selected={isSelected()}\n aria-disabled={isDisabled()}\n class={`mcp-autocomplete-option ${isSelected() ? 'mcp-autocomplete-option-selected' : ''} ${isDisabled() ? 'mcp-autocomplete-option-disabled' : ''}`}\n style={{\n padding: '8px 16px',\n cursor: isDisabled() ? 'not-allowed' : 'pointer',\n 'background-color': isSelected() ? '#eff6ff' : 'transparent',\n color: isDisabled() ? '#9ca3af' : '#374151',\n 'font-size': '0.875rem',\n transition: 'background-color 150ms ease'\n }}\n onClick={() => {\n if (!isDisabled()) {\n props.onSelect(option)\n }\n }}\n onMouseEnter={() => {\n if (!isDisabled()) {\n props.onHover?.(index())\n }\n }}\n >\n <Show\n when={props.renderOption}\n fallback={\n <DefaultOptionRenderer\n option={option}\n isSelected={isSelected()}\n highlightMatch={props.highlightMatch}\n />\n }\n >\n {props.renderOption!(option, isSelected())}\n </Show>\n </li>\n )\n }}\n </For>\n </ul>\n </Show>\n\n {/* Footer hint */}\n <Show when={!props.isLoading && props.options.length > 0}>\n <div\n class=\"mcp-autocomplete-footer\"\n style={{\n padding: '6px 12px',\n 'border-top': '1px solid #e5e7eb',\n 'background-color': '#f9fafb',\n 'font-size': '0.75rem',\n color: '#6b7280'\n }}\n >\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>↑</kbd>\n {' '}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>↓</kbd>\n {' to navigate, '}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>Enter</kbd>\n {' to select, '}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>Esc</kbd>\n {' to dismiss'}\n </div>\n </Show>\n </div>\n </Show>\n )\n}\n\nexport default AutocompleteDropdown\n"],"names":["highlightText","text","match","lowerText","toLowerCase","lowerMatch","startIndex","indexOf","before","slice","matched","length","after","_el$","_$getNextElement","_tmpl$","_$insert","DefaultOptionRenderer","props","displayLabel","createMemo","option","label","value","_el$2","_tmpl$4","_el$9","firstChild","_el$0","_co$2","_$getNextMarker","nextSibling","_el$4","_el$5","_el$7","_el$8","_co$","_$createComponent","Show","when","icon","children","_el$3","_tmpl$2","highlightMatch","description","_el$6","_tmpl$3","AutocompleteDropdown","positionStyles","position","bottom","top","containerStyles","left","right","border","maxHeight","overflow","isOpen","_el$1","_tmpl$9","_el$24","_el$25","_co$4","_el$26","_el$27","_co$5","_el$28","_el$29","_co$6","_el$30","_el$31","_co$7","isLoading","_el$10","_tmpl$5","_el$11","_el$12","_el$13","_co$3","loadingMessage","_$memo","options","_el$14","_tmpl$6","emptyMessage","_el$15","_tmpl$7","For","each","index","isSelected","selectedIndex","isDisabled","disabled","_el$32","_tmpl$0","addEventListener","onHover","$$click","onSelect","renderOption","fallback","_$effect","_p$","_v$3","_v$4","_v$5","_v$6","_v$7","_v$8","e","_$setAttribute","t","a","_$className","o","_$setStyleProperty","i","n","undefined","_$runHydrationEvents","_el$16","_tmpl$8","_el$17","_el$18","_el$19","_el$20","_el$21","_el$22","_v$","class","_v$2","_$style","_$delegateEvents"],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AutocompleteDropdown Component
|
|
3
|
+
* Displays data-driven dropdown suggestions
|
|
4
|
+
*
|
|
5
|
+
* Sprint Autocomplete Feature
|
|
6
|
+
*/
|
|
7
|
+
import { Component, JSX } from 'solid-js';
|
|
8
|
+
import type { AutocompleteOption } from '../types';
|
|
9
|
+
/**
|
|
10
|
+
* Props for AutocompleteDropdown
|
|
11
|
+
*/
|
|
12
|
+
export interface AutocompleteDropdownProps {
|
|
13
|
+
/**
|
|
14
|
+
* Options to display
|
|
15
|
+
*/
|
|
16
|
+
options: AutocompleteOption[];
|
|
17
|
+
/**
|
|
18
|
+
* Currently selected index
|
|
19
|
+
*/
|
|
20
|
+
selectedIndex: number;
|
|
21
|
+
/**
|
|
22
|
+
* Whether dropdown is visible
|
|
23
|
+
*/
|
|
24
|
+
isOpen: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Callback when option is selected
|
|
27
|
+
*/
|
|
28
|
+
onSelect: (option: AutocompleteOption) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Callback when option is hovered
|
|
31
|
+
*/
|
|
32
|
+
onHover?: (index: number) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Whether loading
|
|
35
|
+
*/
|
|
36
|
+
isLoading?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Custom class
|
|
39
|
+
*/
|
|
40
|
+
class?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Max height
|
|
43
|
+
*/
|
|
44
|
+
maxHeight?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Empty state message
|
|
47
|
+
*/
|
|
48
|
+
emptyMessage?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Loading message
|
|
51
|
+
*/
|
|
52
|
+
loadingMessage?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Highlight matching text in options
|
|
55
|
+
*/
|
|
56
|
+
highlightMatch?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Position (default: 'bottom')
|
|
59
|
+
*/
|
|
60
|
+
position?: 'top' | 'bottom';
|
|
61
|
+
/**
|
|
62
|
+
* Custom option renderer
|
|
63
|
+
*/
|
|
64
|
+
renderOption?: (option: AutocompleteOption, isSelected: boolean) => JSX.Element;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* AutocompleteDropdown Component
|
|
68
|
+
*/
|
|
69
|
+
export declare const AutocompleteDropdown: Component<AutocompleteDropdownProps>;
|
|
70
|
+
export default AutocompleteDropdown;
|
|
71
|
+
//# sourceMappingURL=AutocompleteDropdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutocompleteDropdown.d.ts","sourceRoot":"","sources":["../../src/components/AutocompleteDropdown.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAyB,GAAG,EAAE,MAAM,UAAU,CAAA;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAElD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,OAAO,EAAE,kBAAkB,EAAE,CAAA;IAE7B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;IAEf;;OAEG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAE9C;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAEjC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAA;IAE3B;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,KAAK,GAAG,CAAC,OAAO,CAAA;CAChF;AA8DD;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,CAAC,yBAAyB,CAuLrE,CAAA;AAED,eAAe,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { delegateEvents, createComponent, getNextElement, template, getNextMarker, insert, memo, effect, setAttribute, className, setStyleProperty, runHydrationEvents, style } from "solid-js/web";
|
|
2
|
+
import { createMemo, Show, For } from "solid-js";
|
|
3
|
+
var _tmpl$ = /* @__PURE__ */ template(`<strong class=mcp-autocomplete-highlight>`), _tmpl$2 = /* @__PURE__ */ template(`<span class=mcp-autocomplete-option-icon>`), _tmpl$3 = /* @__PURE__ */ template(`<span class=mcp-autocomplete-option-description>`), _tmpl$4 = /* @__PURE__ */ template(`<div class=mcp-autocomplete-option-content><!$><!/><div class=mcp-autocomplete-option-text><span class=mcp-autocomplete-option-label></span><!$><!/>`), _tmpl$5 = /* @__PURE__ */ template(`<div class=mcp-autocomplete-loading style="padding:12px 16px;color:#6b7280;font-size:0.875rem;display:flex;align-items:center;gap:8px"><span style="display:inline-block;width:14px;height:14px;border:2px solid #e5e7eb;border-top-color:#3b82f6;border-radius:50%;animation:mcp-spin 0.6s linear infinite"></span><!$><!/>`), _tmpl$6 = /* @__PURE__ */ template(`<div class=mcp-autocomplete-empty style="padding:12px 16px;color:#9ca3af;font-size:0.875rem;text-align:center">`), _tmpl$7 = /* @__PURE__ */ template(`<ul class=mcp-autocomplete-options style="margin:0;padding:4px 0;list-style:none">`), _tmpl$8 = /* @__PURE__ */ template(`<div class=mcp-autocomplete-footer style="padding:6px 12px;border-top:1px solid #e5e7eb;background-color:#f9fafb;font-size:0.75rem;color:#6b7280"><kbd style="background-color:#e5e7eb;padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">↑</kbd> <kbd style="background-color:#e5e7eb;padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">↓</kbd> to navigate, <kbd style="background-color:#e5e7eb;padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">Enter</kbd> to select, <kbd style="background-color:#e5e7eb;padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">Esc</kbd> to dismiss`), _tmpl$9 = /* @__PURE__ */ template(`<div role=listbox aria-label=Suggestions><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$0 = /* @__PURE__ */ template(`<li role=option style="padding:8px 16px;font-size:0.875rem;transition:background-color 150ms ease">`);
|
|
4
|
+
function highlightText(text, match) {
|
|
5
|
+
if (!match || !text) {
|
|
6
|
+
return text;
|
|
7
|
+
}
|
|
8
|
+
const lowerText = text.toLowerCase();
|
|
9
|
+
const lowerMatch = match.toLowerCase();
|
|
10
|
+
const startIndex = lowerText.indexOf(lowerMatch);
|
|
11
|
+
if (startIndex === -1) {
|
|
12
|
+
return text;
|
|
13
|
+
}
|
|
14
|
+
const before = text.slice(0, startIndex);
|
|
15
|
+
const matched = text.slice(startIndex, startIndex + match.length);
|
|
16
|
+
const after = text.slice(startIndex + match.length);
|
|
17
|
+
return [before, (() => {
|
|
18
|
+
var _el$ = getNextElement(_tmpl$);
|
|
19
|
+
insert(_el$, matched);
|
|
20
|
+
return _el$;
|
|
21
|
+
})(), after];
|
|
22
|
+
}
|
|
23
|
+
const DefaultOptionRenderer = (props) => {
|
|
24
|
+
const displayLabel = createMemo(() => props.option.label || props.option.value);
|
|
25
|
+
return (() => {
|
|
26
|
+
var _el$2 = getNextElement(_tmpl$4), _el$9 = _el$2.firstChild, [_el$0, _co$2] = getNextMarker(_el$9.nextSibling), _el$4 = _el$0.nextSibling, _el$5 = _el$4.firstChild, _el$7 = _el$5.nextSibling, [_el$8, _co$] = getNextMarker(_el$7.nextSibling);
|
|
27
|
+
insert(_el$2, createComponent(Show, {
|
|
28
|
+
get when() {
|
|
29
|
+
return props.option.icon;
|
|
30
|
+
},
|
|
31
|
+
get children() {
|
|
32
|
+
var _el$3 = getNextElement(_tmpl$2);
|
|
33
|
+
insert(_el$3, () => props.option.icon);
|
|
34
|
+
return _el$3;
|
|
35
|
+
}
|
|
36
|
+
}), _el$0, _co$2);
|
|
37
|
+
insert(_el$5, () => highlightText(displayLabel(), props.highlightMatch));
|
|
38
|
+
insert(_el$4, createComponent(Show, {
|
|
39
|
+
get when() {
|
|
40
|
+
return props.option.description;
|
|
41
|
+
},
|
|
42
|
+
get children() {
|
|
43
|
+
var _el$6 = getNextElement(_tmpl$3);
|
|
44
|
+
insert(_el$6, () => props.option.description);
|
|
45
|
+
return _el$6;
|
|
46
|
+
}
|
|
47
|
+
}), _el$8, _co$);
|
|
48
|
+
return _el$2;
|
|
49
|
+
})();
|
|
50
|
+
};
|
|
51
|
+
const AutocompleteDropdown = (props) => {
|
|
52
|
+
const positionStyles = createMemo(() => {
|
|
53
|
+
if (props.position === "top") {
|
|
54
|
+
return {
|
|
55
|
+
bottom: "100%",
|
|
56
|
+
"margin-bottom": "4px"
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
top: "100%",
|
|
61
|
+
"margin-top": "4px"
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
const containerStyles = createMemo(() => ({
|
|
65
|
+
position: "absolute",
|
|
66
|
+
left: "0",
|
|
67
|
+
right: "0",
|
|
68
|
+
"z-index": "50",
|
|
69
|
+
"background-color": "#ffffff",
|
|
70
|
+
border: "1px solid #e5e7eb",
|
|
71
|
+
"border-radius": "6px",
|
|
72
|
+
"box-shadow": "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
73
|
+
"max-height": props.maxHeight || "240px",
|
|
74
|
+
overflow: "auto",
|
|
75
|
+
...positionStyles()
|
|
76
|
+
}));
|
|
77
|
+
return createComponent(Show, {
|
|
78
|
+
get when() {
|
|
79
|
+
return props.isOpen;
|
|
80
|
+
},
|
|
81
|
+
get children() {
|
|
82
|
+
var _el$1 = getNextElement(_tmpl$9), _el$24 = _el$1.firstChild, [_el$25, _co$4] = getNextMarker(_el$24.nextSibling), _el$26 = _el$25.nextSibling, [_el$27, _co$5] = getNextMarker(_el$26.nextSibling), _el$28 = _el$27.nextSibling, [_el$29, _co$6] = getNextMarker(_el$28.nextSibling), _el$30 = _el$29.nextSibling, [_el$31, _co$7] = getNextMarker(_el$30.nextSibling);
|
|
83
|
+
insert(_el$1, createComponent(Show, {
|
|
84
|
+
get when() {
|
|
85
|
+
return props.isLoading;
|
|
86
|
+
},
|
|
87
|
+
get children() {
|
|
88
|
+
var _el$10 = getNextElement(_tmpl$5), _el$11 = _el$10.firstChild, _el$12 = _el$11.nextSibling, [_el$13, _co$3] = getNextMarker(_el$12.nextSibling);
|
|
89
|
+
insert(_el$10, () => props.loadingMessage || "Loading...", _el$13, _co$3);
|
|
90
|
+
return _el$10;
|
|
91
|
+
}
|
|
92
|
+
}), _el$25, _co$4);
|
|
93
|
+
insert(_el$1, createComponent(Show, {
|
|
94
|
+
get when() {
|
|
95
|
+
return memo(() => !!!props.isLoading)() && props.options.length === 0;
|
|
96
|
+
},
|
|
97
|
+
get children() {
|
|
98
|
+
var _el$14 = getNextElement(_tmpl$6);
|
|
99
|
+
insert(_el$14, () => props.emptyMessage || "No suggestions found");
|
|
100
|
+
return _el$14;
|
|
101
|
+
}
|
|
102
|
+
}), _el$27, _co$5);
|
|
103
|
+
insert(_el$1, createComponent(Show, {
|
|
104
|
+
get when() {
|
|
105
|
+
return memo(() => !!!props.isLoading)() && props.options.length > 0;
|
|
106
|
+
},
|
|
107
|
+
get children() {
|
|
108
|
+
var _el$15 = getNextElement(_tmpl$7);
|
|
109
|
+
insert(_el$15, createComponent(For, {
|
|
110
|
+
get each() {
|
|
111
|
+
return props.options;
|
|
112
|
+
},
|
|
113
|
+
children: (option, index) => {
|
|
114
|
+
const isSelected = () => index() === props.selectedIndex;
|
|
115
|
+
const isDisabled = () => option.disabled;
|
|
116
|
+
return (() => {
|
|
117
|
+
var _el$32 = getNextElement(_tmpl$0);
|
|
118
|
+
_el$32.addEventListener("mouseenter", () => {
|
|
119
|
+
var _a;
|
|
120
|
+
if (!isDisabled()) {
|
|
121
|
+
(_a = props.onHover) == null ? void 0 : _a.call(props, index());
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
_el$32.$$click = () => {
|
|
125
|
+
if (!isDisabled()) {
|
|
126
|
+
props.onSelect(option);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
insert(_el$32, createComponent(Show, {
|
|
130
|
+
get when() {
|
|
131
|
+
return props.renderOption;
|
|
132
|
+
},
|
|
133
|
+
get fallback() {
|
|
134
|
+
return createComponent(DefaultOptionRenderer, {
|
|
135
|
+
option,
|
|
136
|
+
get isSelected() {
|
|
137
|
+
return isSelected();
|
|
138
|
+
},
|
|
139
|
+
get highlightMatch() {
|
|
140
|
+
return props.highlightMatch;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
},
|
|
144
|
+
get children() {
|
|
145
|
+
return props.renderOption(option, isSelected());
|
|
146
|
+
}
|
|
147
|
+
}));
|
|
148
|
+
effect((_p$) => {
|
|
149
|
+
var _v$3 = isSelected(), _v$4 = isDisabled(), _v$5 = `mcp-autocomplete-option ${isSelected() ? "mcp-autocomplete-option-selected" : ""} ${isDisabled() ? "mcp-autocomplete-option-disabled" : ""}`, _v$6 = isDisabled() ? "not-allowed" : "pointer", _v$7 = isSelected() ? "#eff6ff" : "transparent", _v$8 = isDisabled() ? "#9ca3af" : "#374151";
|
|
150
|
+
_v$3 !== _p$.e && setAttribute(_el$32, "aria-selected", _p$.e = _v$3);
|
|
151
|
+
_v$4 !== _p$.t && setAttribute(_el$32, "aria-disabled", _p$.t = _v$4);
|
|
152
|
+
_v$5 !== _p$.a && className(_el$32, _p$.a = _v$5);
|
|
153
|
+
_v$6 !== _p$.o && setStyleProperty(_el$32, "cursor", _p$.o = _v$6);
|
|
154
|
+
_v$7 !== _p$.i && setStyleProperty(_el$32, "background-color", _p$.i = _v$7);
|
|
155
|
+
_v$8 !== _p$.n && setStyleProperty(_el$32, "color", _p$.n = _v$8);
|
|
156
|
+
return _p$;
|
|
157
|
+
}, {
|
|
158
|
+
e: void 0,
|
|
159
|
+
t: void 0,
|
|
160
|
+
a: void 0,
|
|
161
|
+
o: void 0,
|
|
162
|
+
i: void 0,
|
|
163
|
+
n: void 0
|
|
164
|
+
});
|
|
165
|
+
runHydrationEvents();
|
|
166
|
+
return _el$32;
|
|
167
|
+
})();
|
|
168
|
+
}
|
|
169
|
+
}));
|
|
170
|
+
return _el$15;
|
|
171
|
+
}
|
|
172
|
+
}), _el$29, _co$6);
|
|
173
|
+
insert(_el$1, createComponent(Show, {
|
|
174
|
+
get when() {
|
|
175
|
+
return memo(() => !!!props.isLoading)() && props.options.length > 0;
|
|
176
|
+
},
|
|
177
|
+
get children() {
|
|
178
|
+
var _el$16 = getNextElement(_tmpl$8), _el$17 = _el$16.firstChild, _el$18 = _el$17.nextSibling, _el$19 = _el$18.nextSibling, _el$20 = _el$19.nextSibling, _el$21 = _el$20.nextSibling, _el$22 = _el$21.nextSibling;
|
|
179
|
+
_el$22.nextSibling;
|
|
180
|
+
return _el$16;
|
|
181
|
+
}
|
|
182
|
+
}), _el$31, _co$7);
|
|
183
|
+
effect((_p$) => {
|
|
184
|
+
var _v$ = `mcp-autocomplete-dropdown ${props.class || ""}`, _v$2 = containerStyles();
|
|
185
|
+
_v$ !== _p$.e && className(_el$1, _p$.e = _v$);
|
|
186
|
+
_p$.t = style(_el$1, _v$2, _p$.t);
|
|
187
|
+
return _p$;
|
|
188
|
+
}, {
|
|
189
|
+
e: void 0,
|
|
190
|
+
t: void 0
|
|
191
|
+
});
|
|
192
|
+
return _el$1;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
delegateEvents(["click"]);
|
|
197
|
+
export {
|
|
198
|
+
AutocompleteDropdown,
|
|
199
|
+
AutocompleteDropdown as default
|
|
200
|
+
};
|
|
201
|
+
//# sourceMappingURL=AutocompleteDropdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutocompleteDropdown.js","sources":["../../src/components/AutocompleteDropdown.tsx"],"sourcesContent":["/**\n * AutocompleteDropdown Component\n * Displays data-driven dropdown suggestions\n *\n * Sprint Autocomplete Feature\n */\n\nimport { Component, For, Show, createMemo, JSX } from 'solid-js'\nimport type { AutocompleteOption } from '../types'\n\n/**\n * Props for AutocompleteDropdown\n */\nexport interface AutocompleteDropdownProps {\n /**\n * Options to display\n */\n options: AutocompleteOption[]\n\n /**\n * Currently selected index\n */\n selectedIndex: number\n\n /**\n * Whether dropdown is visible\n */\n isOpen: boolean\n\n /**\n * Callback when option is selected\n */\n onSelect: (option: AutocompleteOption) => void\n\n /**\n * Callback when option is hovered\n */\n onHover?: (index: number) => void\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n\n /**\n * Custom class\n */\n class?: string\n\n /**\n * Max height\n */\n maxHeight?: string\n\n /**\n * Empty state message\n */\n emptyMessage?: string\n\n /**\n * Loading message\n */\n loadingMessage?: string\n\n /**\n * Highlight matching text in options\n */\n highlightMatch?: string\n\n /**\n * Position (default: 'bottom')\n */\n position?: 'top' | 'bottom'\n\n /**\n * Custom option renderer\n */\n renderOption?: (option: AutocompleteOption, isSelected: boolean) => JSX.Element\n}\n\n/**\n * Highlight matching text\n */\nfunction highlightText(text: string, match?: string): JSX.Element {\n if (!match || !text) {\n return <>{text}</>\n }\n\n const lowerText = text.toLowerCase()\n const lowerMatch = match.toLowerCase()\n const startIndex = lowerText.indexOf(lowerMatch)\n\n if (startIndex === -1) {\n return <>{text}</>\n }\n\n const before = text.slice(0, startIndex)\n const matched = text.slice(startIndex, startIndex + match.length)\n const after = text.slice(startIndex + match.length)\n\n return (\n <>\n {before}\n <strong class=\"mcp-autocomplete-highlight\">{matched}</strong>\n {after}\n </>\n )\n}\n\n/**\n * Default option renderer\n */\nconst DefaultOptionRenderer: Component<{\n option: AutocompleteOption\n isSelected: boolean\n highlightMatch?: string\n}> = (props) => {\n const displayLabel = createMemo(() =>\n props.option.label || props.option.value\n )\n\n return (\n <div class=\"mcp-autocomplete-option-content\">\n <Show when={props.option.icon}>\n <span class=\"mcp-autocomplete-option-icon\">{props.option.icon}</span>\n </Show>\n <div class=\"mcp-autocomplete-option-text\">\n <span class=\"mcp-autocomplete-option-label\">\n {highlightText(displayLabel(), props.highlightMatch)}\n </span>\n <Show when={props.option.description}>\n <span class=\"mcp-autocomplete-option-description\">\n {props.option.description}\n </span>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * AutocompleteDropdown Component\n */\nexport const AutocompleteDropdown: Component<AutocompleteDropdownProps> = (props) => {\n const positionStyles = createMemo((): JSX.CSSProperties => {\n if (props.position === 'top') {\n return {\n bottom: '100%',\n 'margin-bottom': '4px'\n }\n }\n return {\n top: '100%',\n 'margin-top': '4px'\n }\n })\n\n const containerStyles = createMemo((): JSX.CSSProperties => ({\n position: 'absolute',\n left: '0',\n right: '0',\n 'z-index': '50',\n 'background-color': '#ffffff',\n border: '1px solid #e5e7eb',\n 'border-radius': '6px',\n 'box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n 'max-height': props.maxHeight || '240px',\n overflow: 'auto',\n ...positionStyles()\n }))\n\n return (\n <Show when={props.isOpen}>\n <div\n class={`mcp-autocomplete-dropdown ${props.class || ''}`}\n style={containerStyles()}\n role=\"listbox\"\n aria-label=\"Suggestions\"\n >\n {/* Loading state */}\n <Show when={props.isLoading}>\n <div\n class=\"mcp-autocomplete-loading\"\n style={{\n padding: '12px 16px',\n color: '#6b7280',\n 'font-size': '0.875rem',\n display: 'flex',\n 'align-items': 'center',\n gap: '8px'\n }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '14px',\n height: '14px',\n border: '2px solid #e5e7eb',\n 'border-top-color': '#3b82f6',\n 'border-radius': '50%',\n animation: 'mcp-spin 0.6s linear infinite'\n }}\n />\n {props.loadingMessage || 'Loading...'}\n </div>\n </Show>\n\n {/* Empty state */}\n <Show when={!props.isLoading && props.options.length === 0}>\n <div\n class=\"mcp-autocomplete-empty\"\n style={{\n padding: '12px 16px',\n color: '#9ca3af',\n 'font-size': '0.875rem',\n 'text-align': 'center'\n }}\n >\n {props.emptyMessage || 'No suggestions found'}\n </div>\n </Show>\n\n {/* Options list */}\n <Show when={!props.isLoading && props.options.length > 0}>\n <ul\n class=\"mcp-autocomplete-options\"\n style={{ margin: '0', padding: '4px 0', 'list-style': 'none' }}\n >\n <For each={props.options}>\n {(option, index) => {\n const isSelected = () => index() === props.selectedIndex\n const isDisabled = () => option.disabled\n\n return (\n <li\n role=\"option\"\n aria-selected={isSelected()}\n aria-disabled={isDisabled()}\n class={`mcp-autocomplete-option ${isSelected() ? 'mcp-autocomplete-option-selected' : ''} ${isDisabled() ? 'mcp-autocomplete-option-disabled' : ''}`}\n style={{\n padding: '8px 16px',\n cursor: isDisabled() ? 'not-allowed' : 'pointer',\n 'background-color': isSelected() ? '#eff6ff' : 'transparent',\n color: isDisabled() ? '#9ca3af' : '#374151',\n 'font-size': '0.875rem',\n transition: 'background-color 150ms ease'\n }}\n onClick={() => {\n if (!isDisabled()) {\n props.onSelect(option)\n }\n }}\n onMouseEnter={() => {\n if (!isDisabled()) {\n props.onHover?.(index())\n }\n }}\n >\n <Show\n when={props.renderOption}\n fallback={\n <DefaultOptionRenderer\n option={option}\n isSelected={isSelected()}\n highlightMatch={props.highlightMatch}\n />\n }\n >\n {props.renderOption!(option, isSelected())}\n </Show>\n </li>\n )\n }}\n </For>\n </ul>\n </Show>\n\n {/* Footer hint */}\n <Show when={!props.isLoading && props.options.length > 0}>\n <div\n class=\"mcp-autocomplete-footer\"\n style={{\n padding: '6px 12px',\n 'border-top': '1px solid #e5e7eb',\n 'background-color': '#f9fafb',\n 'font-size': '0.75rem',\n color: '#6b7280'\n }}\n >\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>↑</kbd>\n {' '}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>↓</kbd>\n {' to navigate, '}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>Enter</kbd>\n {' to select, '}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>Esc</kbd>\n {' to dismiss'}\n </div>\n </Show>\n </div>\n </Show>\n )\n}\n\nexport default AutocompleteDropdown\n"],"names":["highlightText","text","match","lowerText","toLowerCase","lowerMatch","startIndex","indexOf","before","slice","matched","length","after","_el$","_$getNextElement","_tmpl$","_$insert","DefaultOptionRenderer","props","displayLabel","createMemo","option","label","value","_el$2","_tmpl$4","_el$9","firstChild","_el$0","_co$2","_$getNextMarker","nextSibling","_el$4","_el$5","_el$7","_el$8","_co$","_$createComponent","Show","when","icon","children","_el$3","_tmpl$2","highlightMatch","description","_el$6","_tmpl$3","AutocompleteDropdown","positionStyles","position","bottom","top","containerStyles","left","right","border","maxHeight","overflow","isOpen","_el$1","_tmpl$9","_el$24","_el$25","_co$4","_el$26","_el$27","_co$5","_el$28","_el$29","_co$6","_el$30","_el$31","_co$7","isLoading","_el$10","_tmpl$5","_el$11","_el$12","_el$13","_co$3","loadingMessage","_$memo","options","_el$14","_tmpl$6","emptyMessage","_el$15","_tmpl$7","For","each","index","isSelected","selectedIndex","isDisabled","disabled","_el$32","_tmpl$0","addEventListener","onHover","$$click","onSelect","renderOption","fallback","_$effect","_p$","_v$3","_v$4","_v$5","_v$6","_v$7","_v$8","e","_$setAttribute","t","a","_$className","o","_$setStyleProperty","i","n","undefined","_$runHydrationEvents","_el$16","_tmpl$8","_el$17","_el$18","_el$19","_el$20","_el$21","_el$22","_v$","class","_v$2","_$style","_$delegateEvents"],"mappings":"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"}
|