pixelize-design-library 2.4.2-beta.64 → 2.4.2-beta.65
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/CHANGELOG.md +83 -8
- package/COMPONENT-GOTCHAS.md +37 -4
- package/DESIGN-GUIDE.md +7 -3
- package/dist/Components/CopyButton/CopyButton.d.ts +3 -1
- package/dist/Components/CopyButton/CopyButton.js +2 -2
- package/dist/Components/Drawer/Drawer.d.ts +1 -1
- package/dist/Components/Drawer/Drawer.js +6 -2
- package/dist/Components/Drawer/DrawerProps.d.ts +4 -0
- package/dist/Components/FormDrawer/FormDrawer.d.ts +1 -1
- package/dist/Components/FormDrawer/FormDrawer.js +3 -3
- package/dist/Components/FormDrawer/FormDrawerProps.d.ts +2 -0
- package/dist/Components/Modal/dialogNaming.d.ts +8 -0
- package/dist/Components/Modal/dialogNaming.js +21 -0
- package/dist/Components/NavLauncher/LauncherTabs.js +2 -2
- package/dist/Components/NavLauncher/NavLauncher.d.ts +1 -1
- package/dist/Components/NavLauncher/NavLauncher.js +257 -47
- package/dist/Components/NavLauncher/NavLauncherProps.d.ts +79 -3
- package/dist/Components/NavLauncher/ScopeBar.d.ts +14 -0
- package/dist/Components/NavLauncher/ScopeBar.js +137 -0
- package/dist/Components/NavLauncher/engine/distance.d.ts +4 -0
- package/dist/Components/NavLauncher/engine/distance.js +41 -0
- package/dist/Components/NavLauncher/engine/engine.d.ts +84 -0
- package/dist/Components/NavLauncher/engine/engine.js +471 -0
- package/dist/Components/NavLauncher/engine/fold.d.ts +15 -0
- package/dist/Components/NavLauncher/engine/fold.js +83 -0
- package/dist/Components/NavLauncher/engine/index.d.ts +21 -0
- package/dist/Components/NavLauncher/engine/index.js +17 -0
- package/dist/Components/NavLauncher/launcherParts.d.ts +2 -0
- package/dist/Components/NavLauncher/launcherParts.js +11 -7
- package/dist/Components/NavLauncher/match.d.ts +13 -2
- package/dist/Components/NavLauncher/match.js +26 -12
- package/dist/Components/NavLauncher/searchLayout.d.ts +60 -0
- package/dist/Components/NavLauncher/searchLayout.js +108 -0
- package/dist/Components/NavLauncher/spotlight.d.ts +39 -0
- package/dist/Components/NavLauncher/spotlight.js +202 -0
- package/dist/Components/NavLauncher/spotlightParts.d.ts +49 -0
- package/dist/Components/NavLauncher/spotlightParts.js +108 -0
- package/dist/Components/Table/components/TableHeader.js +3 -1
- package/dist/Components/Table/components/TableLoading.js +8 -2
- package/dist/Components/WizardDialog/WizardDialog.d.ts +1 -1
- package/dist/Components/WizardDialog/WizardDialog.js +15 -3
- package/dist/Components/WizardDialog/WizardDialogProps.d.ts +5 -3
- package/dist/Components/WorkspaceWindow/WorkspaceWindow.js +3 -2
- package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.d.ts +2 -8
- package/dist/Theme/chakra/ringShadow.d.ts +3 -0
- package/dist/Theme/chakra/ringShadow.js +7 -0
- package/dist/Theme/tokens/builders/buildDarkPalette.d.ts +1 -1
- package/dist/Theme/tokens/builders/buildDarkPalette.js +5 -5
- package/dist/esm/Components/CopyButton/CopyButton.js +2 -2
- package/dist/esm/Components/Drawer/Drawer.js +6 -2
- package/dist/esm/Components/FormDrawer/FormDrawer.js +3 -3
- package/dist/esm/Components/Modal/dialogNaming.js +18 -0
- package/dist/esm/Components/NavLauncher/LauncherTabs.js +2 -2
- package/dist/esm/Components/NavLauncher/NavLauncher.js +259 -49
- package/dist/esm/Components/NavLauncher/ScopeBar.js +134 -0
- package/dist/esm/Components/NavLauncher/engine/distance.js +37 -0
- package/dist/esm/Components/NavLauncher/engine/engine.js +458 -0
- package/dist/esm/Components/NavLauncher/engine/fold.js +74 -0
- package/dist/esm/Components/NavLauncher/engine/index.js +14 -0
- package/dist/esm/Components/NavLauncher/launcherParts.js +10 -6
- package/dist/esm/Components/NavLauncher/match.js +25 -12
- package/dist/esm/Components/NavLauncher/searchLayout.js +100 -0
- package/dist/esm/Components/NavLauncher/spotlight.js +194 -0
- package/dist/esm/Components/NavLauncher/spotlightParts.js +95 -0
- package/dist/esm/Components/Table/components/TableHeader.js +4 -2
- package/dist/esm/Components/Table/components/TableLoading.js +6 -3
- package/dist/esm/Components/WizardDialog/WizardDialog.js +15 -3
- package/dist/esm/Components/WorkspaceWindow/WorkspaceWindow.js +4 -3
- package/dist/esm/Theme/chakra/ringShadow.js +3 -0
- package/dist/esm/Theme/tokens/builders/buildDarkPalette.js +5 -5
- package/dist/esm/index.js +2 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.useRowHover = exports.stretchedLink = exports.useRowFocus = exports.titleInset = exports.activeRowSurface = exports.activeRowStyle = exports.ROW_CONTAINER = exports.WIDE_ROW = exports.isPlainClick = exports.useTouchDensity = exports.TouchDensity = exports.ITEM_SELECTOR = void 0;
|
|
6
|
+
exports.HighlightOptionsProvider = exports.useRowHover = exports.stretchedLink = exports.useRowFocus = exports.titleInset = exports.activeRowSurface = exports.activeRowStyle = exports.ROW_CONTAINER = exports.WIDE_ROW = exports.isPlainClick = exports.useTouchDensity = exports.TouchDensity = exports.ITEM_SELECTOR = void 0;
|
|
7
7
|
exports.CountBadge = CountBadge;
|
|
8
8
|
exports.NewTag = NewTag;
|
|
9
9
|
exports.SectionHeader = SectionHeader;
|
|
@@ -21,6 +21,7 @@ const react_1 = require("@chakra-ui/react");
|
|
|
21
21
|
const lucide_react_1 = require("lucide-react");
|
|
22
22
|
const react_2 = require("react");
|
|
23
23
|
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
24
|
+
const ringShadow_1 = require("../../Theme/chakra/ringShadow");
|
|
24
25
|
const filledSurface_1 = require("../../Theme/tokens/builders/filledSurface");
|
|
25
26
|
const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
26
27
|
const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
|
|
@@ -62,7 +63,7 @@ const activeRowSurface = (colors) => {
|
|
|
62
63
|
const { edge, fill } = (0, exports.activeRowStyle)(colors);
|
|
63
64
|
return {
|
|
64
65
|
backgroundColor: fill,
|
|
65
|
-
boxShadow:
|
|
66
|
+
boxShadow: (0, ringShadow_1.insetRingShadow)(edge),
|
|
66
67
|
outline: "2px solid transparent",
|
|
67
68
|
outlineOffset: "-2px",
|
|
68
69
|
};
|
|
@@ -136,9 +137,12 @@ function RowIcon({ icon: Icon, size, stroke = 1.75, mt }) {
|
|
|
136
137
|
return null;
|
|
137
138
|
return ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", color: colors.textMuted, display: "inline-flex", flexShrink: 0, mt: mt, transition: (0, motion_1.transitionFor)(["color"]), _groupHover: { color: colors.accentText }, _groupFocusWithin: { color: colors.accentText }, sx: { "[data-reveal=true] &": { color: colors.accentText } }, children: (0, jsx_runtime_1.jsx)(Icon, { size: size, strokeWidth: stroke, "aria-hidden": true }) }));
|
|
138
139
|
}
|
|
140
|
+
const HighlightOptionsContext = (0, react_2.createContext)(undefined);
|
|
141
|
+
exports.HighlightOptionsProvider = HighlightOptionsContext.Provider;
|
|
139
142
|
function Highlight({ text, query }) {
|
|
140
143
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
141
|
-
|
|
144
|
+
const options = (0, react_2.useContext)(HighlightOptionsContext);
|
|
145
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, match_1.highlightSegments)(text, query, options).map((segment, i) => segment.isMatch ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "mark", bg: "transparent", color: "inherit", fontWeight: 650, textDecoration: "underline", textDecorationColor: colors.primary.opacity[48], textDecorationThickness: "1.5px", textUnderlineOffset: "2px", children: segment.text }, i)) : ((0, jsx_runtime_1.jsx)(react_2.Fragment, { children: segment.text }, i))) }));
|
|
142
146
|
}
|
|
143
147
|
function RowActions({ children }) {
|
|
144
148
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -155,7 +159,7 @@ function RowActions({ children }) {
|
|
|
155
159
|
}
|
|
156
160
|
function RowTip({ text }) {
|
|
157
161
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
158
|
-
return ((0, jsx_runtime_1.jsx)(react_1.Box, { role: "tooltip", position: "absolute", right: "20px", top: "-26px", zIndex: 2, px: "8px", py: "3px", borderRadius: "6px", fontSize: "
|
|
162
|
+
return ((0, jsx_runtime_1.jsx)(react_1.Box, { role: "tooltip", position: "absolute", right: "20px", top: "-26px", zIndex: 2, px: "8px", py: "3px", borderRadius: "6px", fontSize: "xs-minus", fontWeight: 600, whiteSpace: "nowrap", bg: colors.text[900], color: colors.surfaceRaised, visibility: "hidden", pointerEvents: "none", _groupHover: { visibility: "visible" }, children: text }));
|
|
159
163
|
}
|
|
160
164
|
function ModuleRow({ module, keyScreens, isPinned, onTogglePin, pinId, labels, link, }) {
|
|
161
165
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -176,11 +180,11 @@ function RailRow({ screen, module, link, isStrong = false, trailing, pinId, }) {
|
|
|
176
180
|
const hover = (0, exports.useRowHover)();
|
|
177
181
|
const focus = (0, exports.useRowFocus)();
|
|
178
182
|
const isTouch = (0, exports.useTouchDensity)();
|
|
179
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, position: "relative", align: "center", gap: "10px", h: isTouch ? "44px" : "32px", pl: "8px", pr: "4px", borderRadius: "8px", transition: (0, motion_1.transitionFor)(["background-color"]), _hover: hover._hover, _focusWithin: hover._focusWithin, sx: focus.sx, children: [(0, jsx_runtime_1.jsx)(RowIcon, { icon: (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon, size: 15 }), (0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: screen.label, placement: "top-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, ...focus.primary, "data-pin-id": pinId, onClick: link.onPlainClick, flex: 1, minW: 0, fontSize: "
|
|
183
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, position: "relative", align: "center", gap: "10px", h: isTouch ? "44px" : "32px", pl: "8px", pr: "4px", borderRadius: "8px", transition: (0, motion_1.transitionFor)(["background-color"]), _hover: hover._hover, _focusWithin: hover._focusWithin, sx: focus.sx, children: [(0, jsx_runtime_1.jsx)(RowIcon, { icon: (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon, size: 15 }), (0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: screen.label, placement: "top-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, ...focus.primary, "data-pin-id": pinId, onClick: link.onPlainClick, flex: 1, minW: 0, fontSize: "xs-plus", fontWeight: isStrong ? 500 : 400, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: (0, exports.stretchedLink)("8px"), children: screen.label }) }), (0, jsx_runtime_1.jsx)(react_1.Flex, { position: "relative", zIndex: 1, align: "center", gap: "2px", children: trailing })] }));
|
|
180
184
|
}
|
|
181
185
|
function PinTextButton({ label, text, onToggle }) {
|
|
182
186
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
183
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Box, { as: "button", type: "button", "aria-label": label, flexShrink: 0, h: "22px", px: "7px", display: "inline-flex", alignItems: "center", gap: "4px", borderRadius: "6px", borderWidth: "1px", borderColor: colors.boxborder[200], bg: colors.surfaceRaised, color: colors.text[700], fontSize: "
|
|
187
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Box, { as: "button", type: "button", "aria-label": label, flexShrink: 0, h: "22px", px: "7px", display: "inline-flex", alignItems: "center", gap: "4px", borderRadius: "6px", borderWidth: "1px", borderColor: colors.boxborder[200], bg: colors.surfaceRaised, color: colors.text[700], fontSize: "xs-minus", fontWeight: 600, cursor: "pointer", opacity: 0, transition: (0, motion_1.transitionFor)(["opacity", "background-color"]), sx: { ...(0, revealStyles_1.revealStyles)(colors), "@media (hover: none)": { opacity: 1 } }, onClick: (event) => {
|
|
184
188
|
event.preventDefault();
|
|
185
189
|
event.stopPropagation();
|
|
186
190
|
onToggle();
|
|
@@ -192,7 +196,7 @@ function PinnedTile({ screen, module, link, labels, onTogglePin, }) {
|
|
|
192
196
|
const Icon = (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon;
|
|
193
197
|
const focus = (0, exports.useRowFocus)(true);
|
|
194
198
|
const isTouch = (0, exports.useTouchDensity)();
|
|
195
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, "data-nav-cell": true, position: "relative", align: "center", gap: "8px", h: isTouch ? "44px" : "36px", pl: "9px", pr: "4px", borderRadius: "9px", borderWidth: "1px", borderColor: colors.boxborder[200], bg: colors.surfaceRaised, transition: (0, motion_1.transitionFor)(["border-color", "background-color"]), _hover: { borderColor: colors.gray[300] }, sx: focus.sx, children: [Icon ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", display: "inline-flex", flexShrink: 0, color: colors.accentText, children: (0, jsx_runtime_1.jsx)(Icon, { size: 15, strokeWidth: 1.8, "aria-hidden": true }) })) : null, (0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: screen.label, placement: "top-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, ...focus.primary, "data-pin-id": onTogglePin ? screen.id : undefined, onClick: link.onPlainClick, flex: 1, minW: 0, fontSize: "
|
|
199
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, "data-nav-cell": true, position: "relative", align: "center", gap: "8px", h: isTouch ? "44px" : "36px", pl: "9px", pr: "4px", borderRadius: "9px", borderWidth: "1px", borderColor: colors.boxborder[200], bg: colors.surfaceRaised, transition: (0, motion_1.transitionFor)(["border-color", "background-color"]), _hover: { borderColor: colors.gray[300] }, sx: focus.sx, children: [Icon ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", display: "inline-flex", flexShrink: 0, color: colors.accentText, children: (0, jsx_runtime_1.jsx)(Icon, { size: 15, strokeWidth: 1.8, "aria-hidden": true }) })) : null, (0, jsx_runtime_1.jsx)(OverflowToolTip_1.default, { label: screen.label, placement: "top-start", children: (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, ...focus.primary, "data-pin-id": onTogglePin ? screen.id : undefined, onClick: link.onPlainClick, flex: 1, minW: 0, fontSize: "xs-plus", fontWeight: 500, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: (0, exports.stretchedLink)("9px"), children: screen.label }) }), (0, jsx_runtime_1.jsx)(CountBadge, { value: screen.badge, size: "tile" }), onTogglePin ? ((0, jsx_runtime_1.jsx)(react_1.Box, { position: "relative", zIndex: 1, flexShrink: 0, w: "0", overflow: "hidden", transition: (0, motion_1.transitionFor)(["width"]), _groupHover: { w: "22px" }, _groupFocusWithin: { w: "22px" }, children: (0, jsx_runtime_1.jsx)(PinToggle_1.default, { isPinned: true, size: 12, label: labels.unpin(screen.label), title: labels.unpinTip, onToggle: onTogglePin }) })) : null] }));
|
|
196
200
|
}
|
|
197
201
|
function AppsSection({ apps, hues, currentAppId, heading, hideHeading = false, onSelect, }) {
|
|
198
202
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type LauncherSynonyms } from "./engine/engine";
|
|
2
|
+
import type { LauncherAnswer, LauncherFact, LauncherIcon, LauncherResultGroup, LauncherSearchItem, LauncherSection } from "./NavLauncherProps";
|
|
2
3
|
export type LauncherResult = {
|
|
3
4
|
id: string;
|
|
4
5
|
label: string;
|
|
@@ -14,13 +15,18 @@ export type LauncherResult = {
|
|
|
14
15
|
/** Keyword that matched a module or screen whose own name did not. */
|
|
15
16
|
keywordHint?: string;
|
|
16
17
|
isNew?: boolean;
|
|
18
|
+
facts?: readonly LauncherFact[];
|
|
19
|
+
answer?: LauncherAnswer;
|
|
20
|
+
score?: number;
|
|
17
21
|
};
|
|
18
22
|
export type LauncherResultView = {
|
|
19
23
|
id: string;
|
|
20
24
|
label: string;
|
|
21
25
|
items: LauncherResult[];
|
|
22
26
|
};
|
|
27
|
+
export declare function filterItems(items: readonly LauncherSearchItem[], query: string): LauncherSearchItem[];
|
|
23
28
|
export declare function flattenScreens(sections: readonly LauncherSection[]): LauncherResult[];
|
|
29
|
+
/** @deprecated Legacy flat search; NavLauncher uses searchLauncherSections (classic) or the spotlight engine. */
|
|
24
30
|
export declare function searchLauncher(input: {
|
|
25
31
|
query: string;
|
|
26
32
|
sections: readonly LauncherSection[];
|
|
@@ -49,5 +55,10 @@ export type HighlightSegment = {
|
|
|
49
55
|
text: string;
|
|
50
56
|
isMatch: boolean;
|
|
51
57
|
};
|
|
58
|
+
/** Highlight options; `fuzzy` also marks prefix, typo, initial and accent-folded matches. */
|
|
59
|
+
export type HighlightOptions = {
|
|
60
|
+
fuzzy?: boolean;
|
|
61
|
+
synonyms?: LauncherSynonyms;
|
|
62
|
+
};
|
|
52
63
|
/** Splits `text` so every case-insensitive occurrence of a query token is its own matched segment. */
|
|
53
|
-
export declare function highlightSegments(text: string, query: string): HighlightSegment[];
|
|
64
|
+
export declare function highlightSegments(text: string, query: string, options?: HighlightOptions): HighlightSegment[];
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.filterItems = filterItems;
|
|
3
4
|
exports.flattenScreens = flattenScreens;
|
|
4
5
|
exports.searchLauncher = searchLauncher;
|
|
5
6
|
exports.searchLauncherSections = searchLauncherSections;
|
|
6
7
|
exports.highlightSegments = highlightSegments;
|
|
8
|
+
const engine_1 = require("./engine/engine");
|
|
7
9
|
const normalize = (text) => text.toLocaleLowerCase().normalize("NFKD");
|
|
8
10
|
function score(label, haystack, tokens) {
|
|
9
11
|
if (!tokens.every((t) => haystack.includes(t)))
|
|
@@ -29,6 +31,12 @@ function rank(rows, text, tokens) {
|
|
|
29
31
|
.sort((a, b) => a.s - b.s || a.index - b.index)
|
|
30
32
|
.map((r) => r.row);
|
|
31
33
|
}
|
|
34
|
+
function filterItems(items, query) {
|
|
35
|
+
const tokens = normalize(query).split(/\s+/).filter(Boolean);
|
|
36
|
+
if (tokens.length === 0)
|
|
37
|
+
return [];
|
|
38
|
+
return rank([...items], (a) => { var _a, _b; return `${a.label} ${(_a = a.context) !== null && _a !== void 0 ? _a : ""} ${(_b = a.keywords) !== null && _b !== void 0 ? _b : ""}`; }, tokens);
|
|
39
|
+
}
|
|
32
40
|
function flattenScreens(sections) {
|
|
33
41
|
var _a, _b, _c;
|
|
34
42
|
const seen = new Set();
|
|
@@ -54,6 +62,7 @@ function flattenScreens(sections) {
|
|
|
54
62
|
}
|
|
55
63
|
return out;
|
|
56
64
|
}
|
|
65
|
+
/** @deprecated Legacy flat search; NavLauncher uses searchLauncherSections (classic) or the spotlight engine. */
|
|
57
66
|
function searchLauncher(input) {
|
|
58
67
|
var _a, _b;
|
|
59
68
|
const tokens = normalize(input.query).split(/\s+/).filter(Boolean);
|
|
@@ -143,8 +152,23 @@ function searchLauncherSections(input) {
|
|
|
143
152
|
].filter((g) => g.items.length > 0);
|
|
144
153
|
return { sections, groups };
|
|
145
154
|
}
|
|
155
|
+
const toSegments = (text, ranges) => {
|
|
156
|
+
const out = [];
|
|
157
|
+
let cursor = 0;
|
|
158
|
+
for (const [start, end] of ranges) {
|
|
159
|
+
if (start > cursor)
|
|
160
|
+
out.push({ text: text.slice(cursor, start), isMatch: false });
|
|
161
|
+
out.push({ text: text.slice(start, end), isMatch: true });
|
|
162
|
+
cursor = end;
|
|
163
|
+
}
|
|
164
|
+
if (cursor < text.length)
|
|
165
|
+
out.push({ text: text.slice(cursor), isMatch: false });
|
|
166
|
+
return out.length ? out : [{ text, isMatch: false }];
|
|
167
|
+
};
|
|
146
168
|
/** Splits `text` so every case-insensitive occurrence of a query token is its own matched segment. */
|
|
147
|
-
function highlightSegments(text, query) {
|
|
169
|
+
function highlightSegments(text, query, options) {
|
|
170
|
+
if (options === null || options === void 0 ? void 0 : options.fuzzy)
|
|
171
|
+
return toSegments(text, (0, engine_1.highlightRanges)(text, query, { synonyms: options.synonyms }));
|
|
148
172
|
const lower = text.toLocaleLowerCase();
|
|
149
173
|
const tokens = query.toLocaleLowerCase().split(/\s+/).filter(Boolean);
|
|
150
174
|
if (tokens.length === 0 || lower.length !== text.length)
|
|
@@ -164,15 +188,5 @@ function highlightSegments(text, query) {
|
|
|
164
188
|
else
|
|
165
189
|
merged.push([...range]);
|
|
166
190
|
}
|
|
167
|
-
|
|
168
|
-
let cursor = 0;
|
|
169
|
-
for (const [start, end] of merged) {
|
|
170
|
-
if (start > cursor)
|
|
171
|
-
out.push({ text: text.slice(cursor, start), isMatch: false });
|
|
172
|
-
out.push({ text: text.slice(start, end), isMatch: true });
|
|
173
|
-
cursor = end;
|
|
174
|
-
}
|
|
175
|
-
if (cursor < text.length)
|
|
176
|
-
out.push({ text: text.slice(cursor), isMatch: false });
|
|
177
|
-
return out.length ? out : [{ text, isMatch: false }];
|
|
191
|
+
return toSegments(text, merged);
|
|
178
192
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { LauncherResult } from "./match";
|
|
2
|
+
import type { LauncherResultGroup, LauncherSearchItem } from "./NavLauncherProps";
|
|
3
|
+
import { type SearchGroup } from "./spotlight";
|
|
4
|
+
export type SearchEntry = {
|
|
5
|
+
type: "answer" | "top";
|
|
6
|
+
item: LauncherResult;
|
|
7
|
+
} | {
|
|
8
|
+
type: "row";
|
|
9
|
+
item: LauncherResult;
|
|
10
|
+
groupId: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: "more";
|
|
13
|
+
groupId: string;
|
|
14
|
+
count: number;
|
|
15
|
+
};
|
|
16
|
+
export type SearchBlock = {
|
|
17
|
+
type: "answers";
|
|
18
|
+
start: number;
|
|
19
|
+
items: LauncherResult[];
|
|
20
|
+
} | {
|
|
21
|
+
type: "top";
|
|
22
|
+
start: number;
|
|
23
|
+
item: LauncherResult;
|
|
24
|
+
} | {
|
|
25
|
+
type: "group";
|
|
26
|
+
group: SearchGroup;
|
|
27
|
+
start: number;
|
|
28
|
+
visible: LauncherResult[];
|
|
29
|
+
more?: {
|
|
30
|
+
index: number;
|
|
31
|
+
count: number;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export type SearchLayout = {
|
|
35
|
+
blocks: SearchBlock[];
|
|
36
|
+
entries: SearchEntry[];
|
|
37
|
+
sizes: number[];
|
|
38
|
+
total: number;
|
|
39
|
+
};
|
|
40
|
+
export declare const inScope: (groups: SearchGroup[], scope: string) => SearchGroup[];
|
|
41
|
+
/** A scope's items as passed, unranked, for browsing before typing. */
|
|
42
|
+
export declare const scopeGroups: (input: {
|
|
43
|
+
scope: string;
|
|
44
|
+
actions?: readonly LauncherSearchItem[];
|
|
45
|
+
extraResults?: readonly LauncherResultGroup[];
|
|
46
|
+
actionsLabel: string;
|
|
47
|
+
}) => SearchGroup[];
|
|
48
|
+
export declare const countByScope: (groups: SearchGroup[], answers: number) => Map<string, number>;
|
|
49
|
+
export declare const takeTopHit: (groups: SearchGroup[]) => {
|
|
50
|
+
topHit?: LauncherResult;
|
|
51
|
+
groups: SearchGroup[];
|
|
52
|
+
};
|
|
53
|
+
/** Flat option order for keyboard and ARIA plus per-row group sizes for `moveResult`. */
|
|
54
|
+
export declare const layoutSearch: (input: {
|
|
55
|
+
answers: LauncherResult[];
|
|
56
|
+
topHit?: LauncherResult;
|
|
57
|
+
groups: SearchGroup[];
|
|
58
|
+
limit?: number;
|
|
59
|
+
expanded: ReadonlySet<string>;
|
|
60
|
+
}) => SearchLayout;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.layoutSearch = exports.takeTopHit = exports.countByScope = exports.scopeGroups = exports.inScope = void 0;
|
|
4
|
+
const spotlight_1 = require("./spotlight");
|
|
5
|
+
const inScope = (groups, scope) => scope === spotlight_1.SCOPE_ALL ? groups : groups.filter((g) => g.scope === scope);
|
|
6
|
+
exports.inScope = inScope;
|
|
7
|
+
/** A scope's items as passed, unranked, for browsing before typing. */
|
|
8
|
+
const scopeGroups = (input) => {
|
|
9
|
+
var _a, _b, _c;
|
|
10
|
+
const groups = [];
|
|
11
|
+
if (input.scope === spotlight_1.SCOPE_ACTIONS && ((_a = input.actions) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
12
|
+
groups.push({
|
|
13
|
+
id: spotlight_1.SCOPE_ACTIONS,
|
|
14
|
+
label: input.actionsLabel,
|
|
15
|
+
scope: spotlight_1.SCOPE_ACTIONS,
|
|
16
|
+
isSection: false,
|
|
17
|
+
items: input.actions.map((action) => ({ ...action, id: `action:${action.id}` })),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
for (const group of (_b = input.extraResults) !== null && _b !== void 0 ? _b : []) {
|
|
21
|
+
const scope = (_c = group.scope) !== null && _c !== void 0 ? _c : group.id;
|
|
22
|
+
if (scope !== input.scope || group.items.length === 0)
|
|
23
|
+
continue;
|
|
24
|
+
groups.push({
|
|
25
|
+
id: group.id,
|
|
26
|
+
label: group.label,
|
|
27
|
+
scope,
|
|
28
|
+
isSection: false,
|
|
29
|
+
items: group.items.map((item) => ({ ...item, id: `${group.id}:${item.id}` })),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return groups;
|
|
33
|
+
};
|
|
34
|
+
exports.scopeGroups = scopeGroups;
|
|
35
|
+
const countByScope = (groups, answers) => {
|
|
36
|
+
var _a;
|
|
37
|
+
const counts = new Map();
|
|
38
|
+
let all = answers;
|
|
39
|
+
for (const group of groups) {
|
|
40
|
+
counts.set(group.scope, ((_a = counts.get(group.scope)) !== null && _a !== void 0 ? _a : 0) + group.items.length);
|
|
41
|
+
all += group.items.length;
|
|
42
|
+
}
|
|
43
|
+
counts.set(spotlight_1.SCOPE_ALL, all);
|
|
44
|
+
return counts;
|
|
45
|
+
};
|
|
46
|
+
exports.countByScope = countByScope;
|
|
47
|
+
const takeTopHit = (groups) => {
|
|
48
|
+
let at = -1;
|
|
49
|
+
let index = -1;
|
|
50
|
+
let bestScore = 0;
|
|
51
|
+
for (let g = 0; g < groups.length; g += 1) {
|
|
52
|
+
groups[g].items.forEach((item, i) => {
|
|
53
|
+
var _a, _b;
|
|
54
|
+
if (((_a = item.score) !== null && _a !== void 0 ? _a : 0) <= bestScore)
|
|
55
|
+
return;
|
|
56
|
+
bestScore = (_b = item.score) !== null && _b !== void 0 ? _b : 0;
|
|
57
|
+
at = g;
|
|
58
|
+
index = i;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (at < 0)
|
|
62
|
+
return { groups };
|
|
63
|
+
return {
|
|
64
|
+
topHit: groups[at].items[index],
|
|
65
|
+
groups: groups
|
|
66
|
+
.map((group, g) => (g === at ? { ...group, items: group.items.filter((_, i) => i !== index) } : group))
|
|
67
|
+
.filter((group) => group.items.length > 0),
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
exports.takeTopHit = takeTopHit;
|
|
71
|
+
/** Flat option order for keyboard and ARIA plus per-row group sizes for `moveResult`. */
|
|
72
|
+
const layoutSearch = (input) => {
|
|
73
|
+
const blocks = [];
|
|
74
|
+
const entries = [];
|
|
75
|
+
const sizes = [];
|
|
76
|
+
if (input.answers.length) {
|
|
77
|
+
blocks.push({ type: "answers", start: 0, items: input.answers });
|
|
78
|
+
for (const item of input.answers) {
|
|
79
|
+
entries.push({ type: "answer", item });
|
|
80
|
+
sizes.push(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (input.topHit) {
|
|
84
|
+
blocks.push({ type: "top", start: entries.length, item: input.topHit });
|
|
85
|
+
entries.push({ type: "top", item: input.topHit });
|
|
86
|
+
sizes.push(1);
|
|
87
|
+
}
|
|
88
|
+
let total = entries.length;
|
|
89
|
+
for (const group of input.groups) {
|
|
90
|
+
const cap = input.limit !== undefined && !input.expanded.has(group.id) ? Math.max(1, input.limit) : Infinity;
|
|
91
|
+
const visible = group.items.slice(0, cap);
|
|
92
|
+
const hidden = group.items.length - visible.length;
|
|
93
|
+
const start = entries.length;
|
|
94
|
+
for (const item of visible)
|
|
95
|
+
entries.push({ type: "row", item, groupId: group.id });
|
|
96
|
+
sizes.push(visible.length);
|
|
97
|
+
total += group.items.length;
|
|
98
|
+
let more;
|
|
99
|
+
if (hidden > 0) {
|
|
100
|
+
more = { index: entries.length, count: hidden };
|
|
101
|
+
entries.push({ type: "more", groupId: group.id, count: hidden });
|
|
102
|
+
sizes.push(1);
|
|
103
|
+
}
|
|
104
|
+
blocks.push({ type: "group", group, start, visible, more });
|
|
105
|
+
}
|
|
106
|
+
return { blocks, entries, sizes, total };
|
|
107
|
+
};
|
|
108
|
+
exports.layoutSearch = layoutSearch;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type LauncherSearchField, type LauncherSearchIndex, type LauncherSynonyms } from "./engine/engine";
|
|
2
|
+
import type { LauncherResult } from "./match";
|
|
3
|
+
import type { LauncherResultGroup, LauncherSearchItem, LauncherSection } from "./NavLauncherProps";
|
|
4
|
+
export declare const SCOPE_ALL = "all";
|
|
5
|
+
export declare const SCOPE_SCREENS = "screens";
|
|
6
|
+
export declare const SCOPE_ACTIONS = "actions";
|
|
7
|
+
export type SearchGroup = {
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
scope: string;
|
|
11
|
+
isSection: boolean;
|
|
12
|
+
items: LauncherResult[];
|
|
13
|
+
};
|
|
14
|
+
type Entry = {
|
|
15
|
+
groupId: string;
|
|
16
|
+
usageId?: string;
|
|
17
|
+
result: LauncherResult;
|
|
18
|
+
};
|
|
19
|
+
export type SpotlightIndex = {
|
|
20
|
+
index: LauncherSearchIndex;
|
|
21
|
+
entries: Entry[];
|
|
22
|
+
groups: Array<Omit<SearchGroup, "items">>;
|
|
23
|
+
};
|
|
24
|
+
export declare const itemFields: (item: LauncherSearchItem) => LauncherSearchField[];
|
|
25
|
+
export declare function createSpotlightIndex(sections: readonly LauncherSection[], actions: readonly LauncherSearchItem[] | undefined, actionsLabel: string): SpotlightIndex;
|
|
26
|
+
export declare function spotlightBoosts(spot: SpotlightIndex, usage: {
|
|
27
|
+
pinnedIds?: readonly string[];
|
|
28
|
+
frequentIds?: readonly string[];
|
|
29
|
+
recentIds?: readonly string[];
|
|
30
|
+
}): Record<string, number>;
|
|
31
|
+
/** Ranked groups; local rows under 25% of the best score are dropped. */
|
|
32
|
+
export declare function searchSpotlight(spot: SpotlightIndex, input: {
|
|
33
|
+
query: string;
|
|
34
|
+
extraResults?: readonly LauncherResultGroup[];
|
|
35
|
+
synonyms?: LauncherSynonyms;
|
|
36
|
+
boosts?: Readonly<Record<string, number>>;
|
|
37
|
+
}): SearchGroup[];
|
|
38
|
+
export declare function matchAnswers(answers: readonly LauncherSearchItem[] | undefined, query: string, synonyms?: LauncherSynonyms): LauncherResult[];
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.itemFields = exports.SCOPE_ACTIONS = exports.SCOPE_SCREENS = exports.SCOPE_ALL = void 0;
|
|
4
|
+
exports.createSpotlightIndex = createSpotlightIndex;
|
|
5
|
+
exports.spotlightBoosts = spotlightBoosts;
|
|
6
|
+
exports.searchSpotlight = searchSpotlight;
|
|
7
|
+
exports.matchAnswers = matchAnswers;
|
|
8
|
+
const engine_1 = require("./engine/engine");
|
|
9
|
+
exports.SCOPE_ALL = "all";
|
|
10
|
+
exports.SCOPE_SCREENS = "screens";
|
|
11
|
+
exports.SCOPE_ACTIONS = "actions";
|
|
12
|
+
const SHOWN_FIELDS = new Set(["keyword", "fact", "answer"]);
|
|
13
|
+
const RELATIVE_CUTOFF = 0.25;
|
|
14
|
+
const keywordFields = (keywords) => (typeof keywords === "string" ? keywords.split(/[,;|]/) : (keywords !== null && keywords !== void 0 ? keywords : []))
|
|
15
|
+
.map((k) => k.trim())
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.map((text) => ({ name: "keyword", text, weight: 0.75 }));
|
|
18
|
+
const label = (text) => ({
|
|
19
|
+
name: "label",
|
|
20
|
+
text,
|
|
21
|
+
weight: 1,
|
|
22
|
+
});
|
|
23
|
+
const itemFields = (item) => {
|
|
24
|
+
var _a;
|
|
25
|
+
return [
|
|
26
|
+
label(item.label),
|
|
27
|
+
...keywordFields(item.keywords),
|
|
28
|
+
...(item.context
|
|
29
|
+
? [{ name: "context", text: item.context, weight: 0.45 }]
|
|
30
|
+
: []),
|
|
31
|
+
...((_a = item.facts) !== null && _a !== void 0 ? _a : []).map((f) => ({
|
|
32
|
+
name: "fact",
|
|
33
|
+
text: `${f.label}: ${f.value}`,
|
|
34
|
+
weight: 0.6,
|
|
35
|
+
})),
|
|
36
|
+
...(item.answer
|
|
37
|
+
? [
|
|
38
|
+
{ name: "answer", text: item.answer.label, weight: 0.9 },
|
|
39
|
+
{ name: "answer", text: item.answer.value, weight: 0.5 },
|
|
40
|
+
]
|
|
41
|
+
: []),
|
|
42
|
+
];
|
|
43
|
+
};
|
|
44
|
+
exports.itemFields = itemFields;
|
|
45
|
+
const decorate = (result, hit) => {
|
|
46
|
+
var _a;
|
|
47
|
+
return ({
|
|
48
|
+
...result,
|
|
49
|
+
score: hit.score,
|
|
50
|
+
keywordHint: (_a = hit.matches.find((m) => SHOWN_FIELDS.has(m.field))) === null || _a === void 0 ? void 0 : _a.text,
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
function createSpotlightIndex(sections, actions, actionsLabel) {
|
|
54
|
+
var _a;
|
|
55
|
+
const documents = [];
|
|
56
|
+
const entries = [];
|
|
57
|
+
const groups = [];
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
const add = (fields, entry) => {
|
|
60
|
+
documents.push({ id: entry.result.id, fields });
|
|
61
|
+
entries.push(entry);
|
|
62
|
+
};
|
|
63
|
+
for (const section of sections) {
|
|
64
|
+
const groupId = `section:${section.id}`;
|
|
65
|
+
groups.push({
|
|
66
|
+
id: groupId,
|
|
67
|
+
label: section.label,
|
|
68
|
+
scope: exports.SCOPE_SCREENS,
|
|
69
|
+
isSection: true,
|
|
70
|
+
});
|
|
71
|
+
for (const module of section.modules) {
|
|
72
|
+
if (module.screens.length === 0)
|
|
73
|
+
continue;
|
|
74
|
+
add([
|
|
75
|
+
label(module.label),
|
|
76
|
+
...keywordFields(module.keywords),
|
|
77
|
+
{ name: "context", text: section.label, weight: 0.35 },
|
|
78
|
+
], {
|
|
79
|
+
groupId,
|
|
80
|
+
usageId: module.screens[0].id,
|
|
81
|
+
result: {
|
|
82
|
+
id: `module:${module.id}`,
|
|
83
|
+
kind: "module",
|
|
84
|
+
label: module.label,
|
|
85
|
+
icon: module.icon,
|
|
86
|
+
badge: module.badge,
|
|
87
|
+
isNew: module.isNew,
|
|
88
|
+
href: module.href,
|
|
89
|
+
screenId: module.screens[0].id,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
for (const screen of module.screens) {
|
|
93
|
+
if (screen.label === module.label || seen.has(screen.id))
|
|
94
|
+
continue;
|
|
95
|
+
seen.add(screen.id);
|
|
96
|
+
add([
|
|
97
|
+
label(screen.label),
|
|
98
|
+
...keywordFields(screen.keywords),
|
|
99
|
+
{ name: "context", text: module.label, weight: 0.5 },
|
|
100
|
+
{ name: "section", text: section.label, weight: 0.3 },
|
|
101
|
+
], {
|
|
102
|
+
groupId,
|
|
103
|
+
usageId: screen.id,
|
|
104
|
+
result: {
|
|
105
|
+
id: `screen:${screen.id}`,
|
|
106
|
+
kind: "screen",
|
|
107
|
+
label: screen.label,
|
|
108
|
+
context: module.label,
|
|
109
|
+
icon: (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon,
|
|
110
|
+
badge: screen.badge,
|
|
111
|
+
href: screen.href,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (actions === null || actions === void 0 ? void 0 : actions.length) {
|
|
118
|
+
groups.push({
|
|
119
|
+
id: exports.SCOPE_ACTIONS,
|
|
120
|
+
label: actionsLabel,
|
|
121
|
+
scope: exports.SCOPE_ACTIONS,
|
|
122
|
+
isSection: false,
|
|
123
|
+
});
|
|
124
|
+
for (const action of actions) {
|
|
125
|
+
add((0, exports.itemFields)(action), {
|
|
126
|
+
groupId: exports.SCOPE_ACTIONS,
|
|
127
|
+
result: { ...action, id: `action:${action.id}` },
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { index: (0, engine_1.createSearchIndex)(documents), entries, groups };
|
|
132
|
+
}
|
|
133
|
+
function spotlightBoosts(spot, usage) {
|
|
134
|
+
const byScreen = (0, engine_1.usageBoosts)(usage);
|
|
135
|
+
const out = {};
|
|
136
|
+
spot.entries.forEach((entry) => {
|
|
137
|
+
const boost = entry.usageId ? byScreen[entry.usageId] : undefined;
|
|
138
|
+
if (boost)
|
|
139
|
+
out[entry.result.id] = boost;
|
|
140
|
+
});
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
const searchGroup = (group, query, synonyms) => {
|
|
144
|
+
const hits = (0, engine_1.searchDocuments)(group.items.map((item) => ({ id: item.id, fields: (0, exports.itemFields)(item) })), query, { synonyms });
|
|
145
|
+
const result = (index) => ({
|
|
146
|
+
...group.items[index],
|
|
147
|
+
id: `${group.id}:${group.items[index].id}`,
|
|
148
|
+
});
|
|
149
|
+
if (group.matchLocally)
|
|
150
|
+
return hits.map((hit) => decorate(result(hit.index), hit));
|
|
151
|
+
const byIndex = new Map(hits.map((hit) => [hit.index, hit]));
|
|
152
|
+
return group.items.map((_, index) => {
|
|
153
|
+
const hit = byIndex.get(index);
|
|
154
|
+
return hit ? decorate(result(index), hit) : { ...result(index), score: 0 };
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
/** Ranked groups; local rows under 25% of the best score are dropped. */
|
|
158
|
+
function searchSpotlight(spot, input) {
|
|
159
|
+
var _a, _b, _c, _d;
|
|
160
|
+
if (!input.query.trim())
|
|
161
|
+
return [];
|
|
162
|
+
const hits = (0, engine_1.searchIndex)(spot.index, input.query, {
|
|
163
|
+
synonyms: input.synonyms,
|
|
164
|
+
boosts: input.boosts,
|
|
165
|
+
});
|
|
166
|
+
const byGroup = new Map();
|
|
167
|
+
for (const hit of hits) {
|
|
168
|
+
const entry = spot.entries[hit.index];
|
|
169
|
+
const rows = (_a = byGroup.get(entry.groupId)) !== null && _a !== void 0 ? _a : [];
|
|
170
|
+
rows.push(decorate(entry.result, hit));
|
|
171
|
+
byGroup.set(entry.groupId, rows);
|
|
172
|
+
}
|
|
173
|
+
const groups = spot.groups.map((g) => {
|
|
174
|
+
var _a;
|
|
175
|
+
return ({
|
|
176
|
+
...g,
|
|
177
|
+
items: (_a = byGroup.get(g.id)) !== null && _a !== void 0 ? _a : [],
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
for (const group of (_b = input.extraResults) !== null && _b !== void 0 ? _b : []) {
|
|
181
|
+
groups.push({
|
|
182
|
+
id: group.id,
|
|
183
|
+
label: group.label,
|
|
184
|
+
scope: (_c = group.scope) !== null && _c !== void 0 ? _c : group.id,
|
|
185
|
+
isSection: false,
|
|
186
|
+
items: searchGroup(group, input.query, input.synonyms),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const remote = new Set((_d = input.extraResults) === null || _d === void 0 ? void 0 : _d.filter((g) => !g.matchLocally).map((g) => g.id));
|
|
190
|
+
const floor = RELATIVE_CUTOFF *
|
|
191
|
+
Math.max(0, ...groups.flatMap((g) => g.items.map((i) => { var _a; return (_a = i.score) !== null && _a !== void 0 ? _a : 0; })));
|
|
192
|
+
return groups
|
|
193
|
+
.map((g) => remote.has(g.id)
|
|
194
|
+
? g
|
|
195
|
+
: { ...g, items: g.items.filter((i) => { var _a; return ((_a = i.score) !== null && _a !== void 0 ? _a : 0) >= floor; }) })
|
|
196
|
+
.filter((g) => g.items.length > 0);
|
|
197
|
+
}
|
|
198
|
+
function matchAnswers(answers, query, synonyms) {
|
|
199
|
+
if (!(answers === null || answers === void 0 ? void 0 : answers.length))
|
|
200
|
+
return [];
|
|
201
|
+
return searchGroup({ id: "answer", label: "", items: answers, matchLocally: true }, query, synonyms);
|
|
202
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type LinkCtx } from "./launcherParts";
|
|
2
|
+
import type { LauncherResult } from "./match";
|
|
3
|
+
import type { LauncherFact, LauncherLabels, LauncherSearchItem } from "./NavLauncherProps";
|
|
4
|
+
export type ResolvedLabels = Required<Omit<LauncherLabels, "hintOpenMenu">>;
|
|
5
|
+
export declare const QUICK_ACTION_LIMIT = 5;
|
|
6
|
+
export declare function QuickActionsRow({ items, label, link, onRun, }: {
|
|
7
|
+
items: readonly LauncherSearchItem[];
|
|
8
|
+
label: string;
|
|
9
|
+
link: LinkCtx;
|
|
10
|
+
onRun: (item: LauncherSearchItem) => void;
|
|
11
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
type OptionCardProps = {
|
|
13
|
+
item: LauncherResult;
|
|
14
|
+
query: string;
|
|
15
|
+
isActive: boolean;
|
|
16
|
+
optionId: string;
|
|
17
|
+
link: LinkCtx;
|
|
18
|
+
labels: ResolvedLabels;
|
|
19
|
+
onOpen: () => void;
|
|
20
|
+
onHover: () => void;
|
|
21
|
+
describedBy?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function TopHitCard({ item, query, isActive, optionId, link, labels, onOpen, onHover, describedBy, }: OptionCardProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function AnswerCard({ item, isActive, optionId, link, labels, onOpen, onHover, describedBy, }: Omit<OptionCardProps, "query">): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export declare function ShowMoreOption({ count, isActive, optionId, label, onExpand, onHover, }: {
|
|
26
|
+
count: number;
|
|
27
|
+
isActive: boolean;
|
|
28
|
+
optionId: string;
|
|
29
|
+
label: (count: number) => string;
|
|
30
|
+
onExpand: () => void;
|
|
31
|
+
onHover: () => void;
|
|
32
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
export declare const describeFacts: (facts: readonly LauncherFact[]) => string;
|
|
34
|
+
export declare function FactList({ facts, labels, layout, onCopied, onCopyBlocked, }: {
|
|
35
|
+
facts: readonly LauncherFact[];
|
|
36
|
+
labels: ResolvedLabels;
|
|
37
|
+
layout: "pane" | "inline";
|
|
38
|
+
onCopied: () => void;
|
|
39
|
+
onCopyBlocked: (node: HTMLElement | null) => void;
|
|
40
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
export declare function PreviewPane({ item, placement, width, labels, onCopied, onCopyBlocked, }: {
|
|
42
|
+
item?: LauncherResult;
|
|
43
|
+
placement: "side" | "dock";
|
|
44
|
+
width?: string;
|
|
45
|
+
labels: ResolvedLabels;
|
|
46
|
+
onCopied: () => void;
|
|
47
|
+
onCopyBlocked: (node: HTMLElement | null) => void;
|
|
48
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
49
|
+
export {};
|