@mailwoman/react 0.0.1 → 7.5.0
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/README.md +34 -4
- package/common/ClientOnly.tsx +30 -0
- package/common/CopyButton.tsx +44 -0
- package/common/KindBadge.tsx +44 -0
- package/common/LoadingIndicator.tsx +104 -0
- package/common/PresetChips.tsx +43 -0
- package/common/cx.ts +34 -0
- package/common/useClipboard.ts +73 -0
- package/common/useDebouncedValue.ts +23 -0
- package/index.ts +86 -4
- package/out/common/ClientOnly.d.ts +22 -0
- package/out/common/ClientOnly.d.ts.map +1 -0
- package/out/common/ClientOnly.js +20 -0
- package/out/common/ClientOnly.js.map +1 -0
- package/out/common/CopyButton.d.ts +21 -0
- package/out/common/CopyButton.d.ts.map +1 -0
- package/out/common/CopyButton.js +7 -0
- package/out/common/CopyButton.js.map +1 -0
- package/out/common/KindBadge.d.ts +24 -0
- package/out/common/KindBadge.d.ts.map +1 -0
- package/out/common/KindBadge.js +6 -0
- package/out/common/KindBadge.js.map +1 -0
- package/out/common/LoadingIndicator.d.ts +27 -0
- package/out/common/LoadingIndicator.d.ts.map +1 -0
- package/out/common/LoadingIndicator.js +41 -0
- package/out/common/LoadingIndicator.js.map +1 -0
- package/out/common/PresetChips.d.ts +22 -0
- package/out/common/PresetChips.d.ts.map +1 -0
- package/out/common/PresetChips.js +5 -0
- package/out/common/PresetChips.js.map +1 -0
- package/out/common/cx.d.ts +13 -0
- package/out/common/cx.d.ts.map +1 -0
- package/out/common/cx.js +28 -0
- package/out/common/cx.js.map +1 -0
- package/out/common/useClipboard.d.ts +16 -0
- package/out/common/useClipboard.d.ts.map +1 -0
- package/out/common/useClipboard.js +56 -0
- package/out/common/useClipboard.js.map +1 -0
- package/out/common/useDebouncedValue.d.ts +11 -0
- package/out/common/useDebouncedValue.d.ts.map +1 -0
- package/out/common/useDebouncedValue.js +19 -0
- package/out/common/useDebouncedValue.js.map +1 -0
- package/out/index.d.ts +57 -4
- package/out/index.d.ts.map +1 -1
- package/out/index.js +37 -4
- package/out/index.js.map +1 -1
- package/out/pipeline/CandidatePicker.d.ts +17 -0
- package/out/pipeline/CandidatePicker.d.ts.map +1 -0
- package/out/pipeline/CandidatePicker.js +6 -0
- package/out/pipeline/CandidatePicker.js.map +1 -0
- package/out/pipeline/ComponentTable.d.ts +14 -0
- package/out/pipeline/ComponentTable.d.ts.map +1 -0
- package/out/pipeline/ComponentTable.js +6 -0
- package/out/pipeline/ComponentTable.js.map +1 -0
- package/out/pipeline/ConfidenceCell.d.ts +13 -0
- package/out/pipeline/ConfidenceCell.d.ts.map +1 -0
- package/out/pipeline/ConfidenceCell.js +22 -0
- package/out/pipeline/ConfidenceCell.js.map +1 -0
- package/out/pipeline/PipelineExplorer.d.ts +25 -0
- package/out/pipeline/PipelineExplorer.d.ts.map +1 -0
- package/out/pipeline/PipelineExplorer.js +27 -0
- package/out/pipeline/PipelineExplorer.js.map +1 -0
- package/out/pipeline/QueryForm.d.ts +19 -0
- package/out/pipeline/QueryForm.d.ts.map +1 -0
- package/out/pipeline/QueryForm.js +9 -0
- package/out/pipeline/QueryForm.js.map +1 -0
- package/out/pipeline/ResolvedPlace.d.ts +16 -0
- package/out/pipeline/ResolvedPlace.d.ts.map +1 -0
- package/out/pipeline/ResolvedPlace.js +14 -0
- package/out/pipeline/ResolvedPlace.js.map +1 -0
- package/out/pipeline/copy.d.ts +11 -0
- package/out/pipeline/copy.d.ts.map +1 -0
- package/out/pipeline/copy.js +31 -0
- package/out/pipeline/copy.js.map +1 -0
- package/out/pipeline/presets.d.ts +12 -0
- package/out/pipeline/presets.d.ts.map +1 -0
- package/out/pipeline/presets.js +21 -0
- package/out/pipeline/presets.js.map +1 -0
- package/out/pipeline/types.d.ts +110 -0
- package/out/pipeline/types.d.ts.map +1 -0
- package/out/pipeline/types.js +12 -0
- package/out/pipeline/types.js.map +1 -0
- package/out/pipeline/useParsePipeline.d.ts +34 -0
- package/out/pipeline/useParsePipeline.d.ts.map +1 -0
- package/out/pipeline/useParsePipeline.js +55 -0
- package/out/pipeline/useParsePipeline.js.map +1 -0
- package/out/poi/AbstainPanel.d.ts +14 -0
- package/out/poi/AbstainPanel.d.ts.map +1 -0
- package/out/poi/AbstainPanel.js +5 -0
- package/out/poi/AbstainPanel.js.map +1 -0
- package/out/poi/LiveResultsBlock.d.ts +21 -0
- package/out/poi/LiveResultsBlock.d.ts.map +1 -0
- package/out/poi/LiveResultsBlock.js +7 -0
- package/out/poi/LiveResultsBlock.js.map +1 -0
- package/out/poi/OverpassBlock.d.ts +15 -0
- package/out/poi/OverpassBlock.d.ts.map +1 -0
- package/out/poi/OverpassBlock.js +11 -0
- package/out/poi/OverpassBlock.js.map +1 -0
- package/out/poi/POIExplorer.d.ts +31 -0
- package/out/poi/POIExplorer.d.ts.map +1 -0
- package/out/poi/POIExplorer.js +43 -0
- package/out/poi/POIExplorer.js.map +1 -0
- package/out/poi/QueryInput.d.ts +17 -0
- package/out/poi/QueryInput.d.ts.map +1 -0
- package/out/poi/QueryInput.js +5 -0
- package/out/poi/QueryInput.js.map +1 -0
- package/out/poi/SubjectPanel.d.ts +16 -0
- package/out/poi/SubjectPanel.d.ts.map +1 -0
- package/out/poi/SubjectPanel.js +12 -0
- package/out/poi/SubjectPanel.js.map +1 -0
- package/out/poi/runtime.d.ts +43 -0
- package/out/poi/runtime.d.ts.map +1 -0
- package/out/poi/runtime.js +67 -0
- package/out/poi/runtime.js.map +1 -0
- package/out/poi/types.d.ts +113 -0
- package/out/poi/types.d.ts.map +1 -0
- package/out/poi/types.js +12 -0
- package/out/poi/types.js.map +1 -0
- package/out/poi/usePOISearch.d.ts +42 -0
- package/out/poi/usePOISearch.d.ts.map +1 -0
- package/out/poi/usePOISearch.js +158 -0
- package/out/poi/usePOISearch.js.map +1 -0
- package/package.json +52 -8
- package/pipeline/CandidatePicker.tsx +45 -0
- package/pipeline/ComponentTable.tsx +41 -0
- package/pipeline/ConfidenceCell.tsx +33 -0
- package/pipeline/PipelineExplorer.tsx +148 -0
- package/pipeline/QueryForm.tsx +52 -0
- package/pipeline/ResolvedPlace.tsx +50 -0
- package/pipeline/copy.ts +37 -0
- package/pipeline/presets.ts +24 -0
- package/pipeline/types.ts +118 -0
- package/pipeline/useParsePipeline.ts +84 -0
- package/poi/AbstainPanel.tsx +22 -0
- package/poi/LiveResultsBlock.tsx +70 -0
- package/poi/OverpassBlock.tsx +37 -0
- package/poi/POIExplorer.tsx +133 -0
- package/poi/QueryInput.tsx +26 -0
- package/poi/SubjectPanel.tsx +79 -0
- package/poi/runtime.ts +78 -0
- package/poi/types.ts +112 -0
- package/poi/usePOISearch.ts +234 -0
- package/styles.css +648 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @copyright Sister Software
|
|
4
|
+
* @license AGPL-3.0
|
|
5
|
+
* @author Teffen Ellis, et al.
|
|
6
|
+
*
|
|
7
|
+
* `POIExplorer` — the composed POI-intent tester. Detects a POI subject in free text, shows the
|
|
8
|
+
* category + OverpassQL export, and (when a live-search probe is injected) searches the published
|
|
9
|
+
* poi.db layer. The intent path is self-contained — no weights, no network. All runtime concerns are
|
|
10
|
+
* in {@link usePOISearch}; this file is composition + a `ClientOnly` SSR boundary.
|
|
11
|
+
*/
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import { ClientOnly } from "../common/ClientOnly.js";
|
|
14
|
+
import { KindBadge } from "../common/KindBadge.js";
|
|
15
|
+
import { PresetChips } from "../common/PresetChips.js";
|
|
16
|
+
import { AbstainPanel } from "./AbstainPanel.js";
|
|
17
|
+
import { LiveResultsBlock } from "./LiveResultsBlock.js";
|
|
18
|
+
import { OverpassBlock } from "./OverpassBlock.js";
|
|
19
|
+
import { QueryInput } from "./QueryInput.js";
|
|
20
|
+
import { POI_DEFAULT_TEXT, POI_PRESETS } from "./runtime.js";
|
|
21
|
+
import { SubjectPanel } from "./SubjectPanel.js";
|
|
22
|
+
import { usePOISearch } from "./usePOISearch.js";
|
|
23
|
+
function POIExplorerInner({ defaultText, presets, loadRuntime, runLiveSearch, brandLiveSearch, }) {
|
|
24
|
+
const [text, setText] = useState(defaultText);
|
|
25
|
+
const { result, liveSearch, searchLive } = usePOISearch({
|
|
26
|
+
text,
|
|
27
|
+
loadRuntime,
|
|
28
|
+
runLiveSearch,
|
|
29
|
+
brandLiveSearch,
|
|
30
|
+
});
|
|
31
|
+
const subject = result?.subject;
|
|
32
|
+
// The live block appears whenever the subject COULD be live-searched with an anchor — i.e. capable minus the
|
|
33
|
+
// anchor-present requirement (`canSearchLive` also requires an anchor; the block itself renders the "add an anchor"
|
|
34
|
+
// hint, so it must show one step earlier). Category: not build-local. Brand: brand-capable probe + a QID.
|
|
35
|
+
const showLiveBlock = Boolean(runLiveSearch &&
|
|
36
|
+
subject &&
|
|
37
|
+
(subject.kind === "brand" ? brandLiveSearch && subject.wikidata !== undefined : !subject.buildLocal));
|
|
38
|
+
return (_jsxs("div", { className: "mw-poi-explorer", children: [_jsx(QueryInput, { id: "mw-poi-input", label: "Query", value: text, onChange: setText, placeholder: POI_DEFAULT_TEXT }), _jsx(PresetChips, { presets: presets, onPick: setText }), result ? (_jsxs("div", { className: "mw-result", children: [_jsx(KindBadge, { kindResult: result.kindResult }), subject ? (_jsxs(_Fragment, { children: [_jsx(SubjectPanel, { subject: subject }), subject.kind === "category" ? (_jsx(OverpassBlock, { overpassQL: result.overpassQL, overpassError: result.overpassError })) : null, showLiveBlock ? (_jsx(LiveResultsBlock, { subjectLabel: subject.kind === "brand" ? subject.name : subject.category.label, anchor: subject.remainder, state: liveSearch, onSearch: searchLive })) : null] })) : (_jsx(AbstainPanel, { kind: result.kindResult.kind }))] })) : null] }));
|
|
39
|
+
}
|
|
40
|
+
export function POIExplorer({ defaultText = POI_DEFAULT_TEXT, presets = POI_PRESETS, loadRuntime, runLiveSearch, brandLiveSearch, }) {
|
|
41
|
+
return (_jsx(ClientOnly, { fallback: _jsx("div", { className: "mw-poi-explorer", children: _jsx("p", { children: "Loading POI tester\u2026" }) }), children: () => (_jsx(POIExplorerInner, { defaultText: defaultText, presets: presets, loadRuntime: loadRuntime, runLiveSearch: runLiveSearch, brandLiveSearch: brandLiveSearch })) }));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=POIExplorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"POIExplorer.js","sourceRoot":"","sources":["../../poi/POIExplorer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `QueryInput` — the labelled text field for the POI explorer. Controlled; presentational only.
|
|
7
|
+
*/
|
|
8
|
+
import type { ReactNode } from "react";
|
|
9
|
+
export interface QueryInputProps {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
value: string;
|
|
13
|
+
onChange: (value: string) => void;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function QueryInput({ id, label, value, onChange, placeholder }: QueryInputProps): ReactNode;
|
|
17
|
+
//# sourceMappingURL=QueryInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryInput.d.ts","sourceRoot":"","sources":["../../poi/QueryInput.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,eAAe,GAAG,SAAS,CAOlG"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function QueryInput({ id, label, value, onChange, placeholder }) {
|
|
3
|
+
return (_jsxs("div", { className: "mw-field", children: [_jsx("label", { htmlFor: id, children: label }), _jsx("input", { id: id, type: "text", value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder })] }));
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=QueryInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryInput.js","sourceRoot":"","sources":["../../poi/QueryInput.tsx"],"names":[],"mappings":";AAkBA,MAAM,UAAU,UAAU,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAmB;IACtF,OAAO,CACN,eAAK,SAAS,EAAC,UAAU,aACxB,gBAAO,OAAO,EAAE,EAAE,YAAG,KAAK,GAAS,EACnC,gBAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAC,MAAM,EAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,GAAI,IAC3G,CACN,CAAA;AACF,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `SubjectPanel` — renders the detected POI subject. For a CATEGORY: the category chip, the optional
|
|
7
|
+
* build-local badge + note. For a BRAND: the brand-name chip + a Wikidata QID chip (linked). Both
|
|
8
|
+
* share the match-detail list (matched phrase, confidence, anchor). Presentational.
|
|
9
|
+
*/
|
|
10
|
+
import type { ReactNode } from "react";
|
|
11
|
+
import type { POISubject } from "./types.ts";
|
|
12
|
+
export interface SubjectPanelProps {
|
|
13
|
+
subject: POISubject;
|
|
14
|
+
}
|
|
15
|
+
export declare function SubjectPanel({ subject }: SubjectPanelProps): ReactNode;
|
|
16
|
+
//# sourceMappingURL=SubjectPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubjectPanel.d.ts","sourceRoot":"","sources":["../../poi/SubjectPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,UAAU,CAAA;CACnB;AAkBD,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,iBAAiB,GAAG,SAAS,CA4CtE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/** The shared match-detail list (matched phrase, confidence, anchor) — identical for category + brand subjects. */
|
|
3
|
+
function MatchDetail({ subject }) {
|
|
4
|
+
return (_jsxs("dl", { className: "mw-subject__detail", children: [_jsx("dt", { children: "matched phrase" }), _jsx("dd", { children: _jsx("code", { children: subject.matchedPhrase }) }), _jsx("dt", { children: "confidence" }), _jsxs("dd", { children: [Math.round(subject.confidence * 100), "%"] }), _jsx("dt", { children: "anchor" }), _jsx("dd", { children: subject.remainder ? subject.remainder : _jsx("em", { children: "none \u2014 global query" }) })] }));
|
|
5
|
+
}
|
|
6
|
+
export function SubjectPanel({ subject }) {
|
|
7
|
+
if (subject.kind === "brand") {
|
|
8
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mw-subject__row", children: [_jsx("span", { className: "mw-subject__chip", children: subject.name }), _jsx("span", { className: "mw-subject__badge mw-subject__badge--brand", children: "brand" }), subject.wikidata ? (_jsx("a", { className: "mw-subject__qid", href: `https://www.wikidata.org/wiki/${subject.wikidata}`, target: "_blank", rel: "noreferrer", children: subject.wikidata })) : null] }), _jsx(MatchDetail, { subject: subject }), _jsx("p", { className: "mw-subject__note", children: "Matched as a chain brand \u2014 resolved by Wikidata QID against the layer's brand index." })] }));
|
|
9
|
+
}
|
|
10
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mw-subject__row", children: [_jsx("span", { className: "mw-subject__chip", children: subject.category.label }), subject.buildLocal ? _jsx("span", { className: "mw-subject__badge", children: "build-local" }) : null] }), _jsx(MatchDetail, { subject: subject }), subject.buildLocal ? (_jsx("p", { className: "mw-subject__note", children: "Requires the locally-built OSM layer (ODbL) \u2014 mailwoman ships the builder, not the data." })) : null] }));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=SubjectPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubjectPanel.js","sourceRoot":"","sources":["../../poi/SubjectPanel.tsx"],"names":[],"mappings":";AAkBA,mHAAmH;AACnH,SAAS,WAAW,CAAC,EAAE,OAAO,EAAqB;IAClD,OAAO,CACN,cAAI,SAAS,EAAC,oBAAoB,aACjC,0CAAuB,EACvB,uBACC,yBAAO,OAAO,CAAC,aAAa,GAAQ,GAChC,EACL,sCAAmB,EACnB,yBAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,GAAG,GAAG,CAAC,SAAO,EAChD,kCAAe,EACf,uBAAK,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,oDAA4B,GAAM,IAC3E,CACL,CAAA;AACF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAE,OAAO,EAAqB;IAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC9B,OAAO,CACN,8BACC,eAAK,SAAS,EAAC,iBAAiB,aAC/B,eAAM,SAAS,EAAC,kBAAkB,YAAE,OAAO,CAAC,IAAI,GAAQ,EACxD,eAAM,SAAS,EAAC,4CAA4C,sBAAa,EACxE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CACnB,YACC,SAAS,EAAC,iBAAiB,EAC3B,IAAI,EAAE,iCAAiC,OAAO,CAAC,QAAQ,EAAE,EACzD,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,YAEf,OAAO,CAAC,QAAQ,GACd,CACJ,CAAC,CAAC,CAAC,IAAI,IACH,EAEN,KAAC,WAAW,IAAC,OAAO,EAAE,OAAO,GAAI,EAEjC,YAAG,SAAS,EAAC,kBAAkB,0GAE3B,IACF,CACH,CAAA;IACF,CAAC;IAED,OAAO,CACN,8BACC,eAAK,SAAS,EAAC,iBAAiB,aAC/B,eAAM,SAAS,EAAC,kBAAkB,YAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,GAAQ,EACjE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,eAAM,SAAS,EAAC,mBAAmB,4BAAmB,CAAC,CAAC,CAAC,IAAI,IAC9E,EAEN,KAAC,WAAW,IAAC,OAAO,EAAE,OAAO,GAAI,EAEhC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CACrB,YAAG,SAAS,EAAC,kBAAkB,8GAE3B,CACJ,CAAC,CAAC,CAAC,IAAI,IACN,CACH,CAAA;AACF,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* The default POI runtime loader + presentation helpers. `loadPOIRuntime` dynamically imports the
|
|
7
|
+
* ~2k-record Overture taxonomy snapshot (so bundlers code-split it into its own chunk, fetched only
|
|
8
|
+
* when the explorer actually mounts) and wires the kind classifier over it. Pure + browser-safe: no
|
|
9
|
+
* network, no DOM — the whole intent path runs offline.
|
|
10
|
+
*/
|
|
11
|
+
import type { POIRuntime } from "./types.ts";
|
|
12
|
+
/**
|
|
13
|
+
* Build the POI runtime, dynamically importing the taxonomy + brand JSON so the tables land in their own chunk. A
|
|
14
|
+
* static import would inline the whole snapshot into every consumer's bundle.
|
|
15
|
+
*
|
|
16
|
+
* The lexicon unions categories then brands, mirroring the Node runtime's `poiTaxonomyLookup` precedence: a phrase that
|
|
17
|
+
* matches a taxonomy CATEGORY wins (the curated set); only on a category miss does the chain-brand table fire,
|
|
18
|
+
* returning a `kind: "brand"` match carrying the brand's canonical name + Wikidata QID. (The Node path also chains
|
|
19
|
+
* `@mailwoman/variant-aliases` regional slang; the browser tester leaves that out — one fewer package + data table for
|
|
20
|
+
* a demo, and the QID-keyed brand table already covers the headline brands.)
|
|
21
|
+
*/
|
|
22
|
+
export declare function loadPOIRuntime(): Promise<POIRuntime>;
|
|
23
|
+
/** Default example queries for the POI explorer — a mix of category, build-local, and chain-brand subjects. */
|
|
24
|
+
export declare const POI_PRESETS: readonly [{
|
|
25
|
+
readonly label: "Drinking fountain";
|
|
26
|
+
readonly value: "drinking fountain near Springfield";
|
|
27
|
+
}, {
|
|
28
|
+
readonly label: "Fire hydrant";
|
|
29
|
+
readonly value: "fire hydrant";
|
|
30
|
+
}, {
|
|
31
|
+
readonly label: "Hospital + address";
|
|
32
|
+
readonly value: "hospital, 350 5th Ave, New York";
|
|
33
|
+
}, {
|
|
34
|
+
readonly label: "Chevron (brand)";
|
|
35
|
+
readonly value: "chevron near Houston";
|
|
36
|
+
}, {
|
|
37
|
+
readonly label: "Applebee's (brand)";
|
|
38
|
+
readonly value: "applebee's near Chicago";
|
|
39
|
+
}];
|
|
40
|
+
export declare const POI_DEFAULT_TEXT: "drinking fountain near Springfield";
|
|
41
|
+
/** `742 m` under 1 km, `1.9 km` past it — matches the demo's distance captions. */
|
|
42
|
+
export declare function formatDistance(distanceM: number): string;
|
|
43
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../poi/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C;;;;;;;;;GASG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,CAAC,CAgC1D;AAED,+GAA+G;AAC/G,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;EAMd,CAAA;AAEV,eAAO,MAAM,gBAAgB,sCAAuB,CAAA;AAEpD,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIxD"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* The default POI runtime loader + presentation helpers. `loadPOIRuntime` dynamically imports the
|
|
7
|
+
* ~2k-record Overture taxonomy snapshot (so bundlers code-split it into its own chunk, fetched only
|
|
8
|
+
* when the explorer actually mounts) and wires the kind classifier over it. Pure + browser-safe: no
|
|
9
|
+
* network, no DOM — the whole intent path runs offline.
|
|
10
|
+
*/
|
|
11
|
+
import { createKindClassifier } from "@mailwoman/kind-classifier";
|
|
12
|
+
import { createPOIBrandLookup, createPOITaxonomyLookup } from "@mailwoman/poi-taxonomy/table";
|
|
13
|
+
/**
|
|
14
|
+
* Build the POI runtime, dynamically importing the taxonomy + brand JSON so the tables land in their own chunk. A
|
|
15
|
+
* static import would inline the whole snapshot into every consumer's bundle.
|
|
16
|
+
*
|
|
17
|
+
* The lexicon unions categories then brands, mirroring the Node runtime's `poiTaxonomyLookup` precedence: a phrase that
|
|
18
|
+
* matches a taxonomy CATEGORY wins (the curated set); only on a category miss does the chain-brand table fire,
|
|
19
|
+
* returning a `kind: "brand"` match carrying the brand's canonical name + Wikidata QID. (The Node path also chains
|
|
20
|
+
* `@mailwoman/variant-aliases` regional slang; the browser tester leaves that out — one fewer package + data table for
|
|
21
|
+
* a demo, and the QID-keyed brand table already covers the headline brands.)
|
|
22
|
+
*/
|
|
23
|
+
export async function loadPOIRuntime() {
|
|
24
|
+
const [table, brandTable] = await Promise.all([
|
|
25
|
+
import("@mailwoman/poi-taxonomy/data/taxonomy.json").then((m) => m.default),
|
|
26
|
+
import("@mailwoman/poi-taxonomy/data/brands.json").then((m) => m.default),
|
|
27
|
+
]);
|
|
28
|
+
const lookup = createPOITaxonomyLookup(table);
|
|
29
|
+
const brands = createPOIBrandLookup(brandTable);
|
|
30
|
+
// Adapt the taxonomy + brand lookups to the `POIPhraseLookup` shape the classifier expects: categories first, brands
|
|
31
|
+
// on a category miss.
|
|
32
|
+
const lexicon = (phrase, locale) => {
|
|
33
|
+
const categoryHits = lookup.lookupPOICategory(phrase, locale);
|
|
34
|
+
if (categoryHits.length > 0) {
|
|
35
|
+
return categoryHits.map((match) => ({
|
|
36
|
+
kind: "category",
|
|
37
|
+
categoryID: match.category.id,
|
|
38
|
+
matchedPhrase: match.matchedPhrase,
|
|
39
|
+
confidence: match.confidence,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
return brands.lookupPOIBrand(phrase).map((match) => ({
|
|
43
|
+
kind: "brand",
|
|
44
|
+
categoryID: match.brand.name,
|
|
45
|
+
wikidata: match.brand.wikidata,
|
|
46
|
+
matchedPhrase: match.matchedPhrase,
|
|
47
|
+
confidence: match.confidence,
|
|
48
|
+
}));
|
|
49
|
+
};
|
|
50
|
+
return { lookup, lexicon, classify: createKindClassifier({ poiLexicon: lexicon }) };
|
|
51
|
+
}
|
|
52
|
+
/** Default example queries for the POI explorer — a mix of category, build-local, and chain-brand subjects. */
|
|
53
|
+
export const POI_PRESETS = [
|
|
54
|
+
{ label: "Drinking fountain", value: "drinking fountain near Springfield" },
|
|
55
|
+
{ label: "Fire hydrant", value: "fire hydrant" },
|
|
56
|
+
{ label: "Hospital + address", value: "hospital, 350 5th Ave, New York" },
|
|
57
|
+
{ label: "Chevron (brand)", value: "chevron near Houston" },
|
|
58
|
+
{ label: "Applebee's (brand)", value: "applebee's near Chicago" },
|
|
59
|
+
];
|
|
60
|
+
export const POI_DEFAULT_TEXT = POI_PRESETS[0].value;
|
|
61
|
+
/** `742 m` under 1 km, `1.9 km` past it — matches the demo's distance captions. */
|
|
62
|
+
export function formatDistance(distanceM) {
|
|
63
|
+
if (distanceM < 1000)
|
|
64
|
+
return `${Math.round(distanceM)} m`;
|
|
65
|
+
return `${(distanceM / 1000).toFixed(1)} km`;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../poi/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEjE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;AAI7F;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IACnC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC7C,MAAM,CAAC,4CAA4C,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3E,MAAM,CAAC,0CAA0C,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KACzE,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAiE,CAAC,CAAA;IACzG,MAAM,MAAM,GAAG,oBAAoB,CAAC,UAAmE,CAAC,CAAA;IAExG,qHAAqH;IACrH,sBAAsB;IACtB,MAAM,OAAO,GAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;QACnD,MAAM,YAAY,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAE7D,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACnC,IAAI,EAAE,UAAU;gBAChB,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE;gBAC7B,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,UAAU,EAAE,KAAK,CAAC,UAAU;aAC5B,CAAC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACpD,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;YAC5B,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ;YAC9B,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,UAAU,EAAE,KAAK,CAAC,UAAU;SAC5B,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,oBAAoB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,EAAE,CAAA;AACpF,CAAC;AAED,+GAA+G;AAC/G,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,oCAAoC,EAAE;IAC3E,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;IAChD,EAAE,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,iCAAiC,EAAE;IACzE,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,sBAAsB,EAAE;IAC3D,EAAE,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,yBAAyB,EAAE;CACxD,CAAA;AAEV,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AAEpD,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC/C,IAAI,SAAS,GAAG,IAAI;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAA;IAEzD,OAAO,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;AAC7C,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Types for the POI explorer. The intent path (classification → subject → OverpassQL) is fully
|
|
7
|
+
* self-contained over the pure `@mailwoman/*` packages; the live poi.db path is expressed only as an
|
|
8
|
+
* INJECTED async function ({@link POILiveSearch}) so the httpvfs/worker machinery stays out of this
|
|
9
|
+
* package's browser graph (it lives in the docs site, which knows where the layer is served).
|
|
10
|
+
*/
|
|
11
|
+
import type { POIPhraseLookup, QueryKindResult } from "@mailwoman/kind-classifier";
|
|
12
|
+
import type { createKindClassifier } from "@mailwoman/kind-classifier";
|
|
13
|
+
import type { createPOITaxonomyLookup } from "@mailwoman/poi-taxonomy/table";
|
|
14
|
+
export type TaxonomyLookup = ReturnType<typeof createPOITaxonomyLookup>;
|
|
15
|
+
export type CategoryRecord = NonNullable<ReturnType<TaxonomyLookup["getPOICategory"]>>;
|
|
16
|
+
/** The lazily-loaded POI runtime: the taxonomy lookup, the adapted lexicon, and the kind classifier over it. */
|
|
17
|
+
export interface POIRuntime {
|
|
18
|
+
lookup: TaxonomyLookup;
|
|
19
|
+
lexicon: POIPhraseLookup;
|
|
20
|
+
classify: ReturnType<typeof createKindClassifier>;
|
|
21
|
+
}
|
|
22
|
+
/** Fields shared by every resolved POI subject, category or brand. */
|
|
23
|
+
export interface POISubjectBase {
|
|
24
|
+
matchedPhrase: string;
|
|
25
|
+
confidence: number;
|
|
26
|
+
/** The non-subject remainder of the query (the location anchor, e.g. "near Springfield"). */
|
|
27
|
+
remainder: string;
|
|
28
|
+
}
|
|
29
|
+
/** A resolved POI subject that names a taxonomy CATEGORY (`cafe`, `hospital`, `drinking fountain`). */
|
|
30
|
+
export interface POICategorySubject extends POISubjectBase {
|
|
31
|
+
kind: "category";
|
|
32
|
+
category: CategoryRecord;
|
|
33
|
+
/** Whether this category needs the locally-built OSM (ODbL) layer — precomputed off the runtime. */
|
|
34
|
+
buildLocal: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A resolved POI subject that names a chain BRAND (`chevron`, `applebee's`). Brands carry a Wikidata QID and are
|
|
38
|
+
* searched by that QID, NOT by category k-ring — see `@mailwoman/poi-taxonomy`'s brand table + the layer's
|
|
39
|
+
* `brand_wikidata` index.
|
|
40
|
+
*/
|
|
41
|
+
export interface POIBrandSubject extends POISubjectBase {
|
|
42
|
+
kind: "brand";
|
|
43
|
+
/** The brand's canonical display name. */
|
|
44
|
+
name: string;
|
|
45
|
+
/** Wikidata QID, when the lexicon carried one (`Q319642` = Chevron). Absent ⇒ matched by name alone. */
|
|
46
|
+
wikidata?: string;
|
|
47
|
+
}
|
|
48
|
+
/** A resolved POI subject — a taxonomy category or a chain brand — plus its match metadata. */
|
|
49
|
+
export type POISubject = POICategorySubject | POIBrandSubject;
|
|
50
|
+
/** The intent-only result: the kind verdict plus (when a subject was detected) its OverpassQL export (category only). */
|
|
51
|
+
export interface POIExplorerResult {
|
|
52
|
+
kindResult: QueryKindResult;
|
|
53
|
+
subject?: POISubject;
|
|
54
|
+
overpassQL?: string;
|
|
55
|
+
overpassError?: string;
|
|
56
|
+
}
|
|
57
|
+
/** One live poi.db hit, as the results list renders it. */
|
|
58
|
+
export interface POISearchHit {
|
|
59
|
+
name: string;
|
|
60
|
+
lat: number;
|
|
61
|
+
lon: number;
|
|
62
|
+
distanceM: number;
|
|
63
|
+
country: string;
|
|
64
|
+
confidence: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Result of an injected live search. Preserves the original tester's two failure modes — the anchor not resolving vs
|
|
68
|
+
* the published layer being unreachable — so the UI can word them differently.
|
|
69
|
+
*/
|
|
70
|
+
export type POILiveSearchResult = {
|
|
71
|
+
status: "success";
|
|
72
|
+
hits: POISearchHit[];
|
|
73
|
+
centerName: string;
|
|
74
|
+
} | {
|
|
75
|
+
status: "unplaced";
|
|
76
|
+
anchor: string;
|
|
77
|
+
} | {
|
|
78
|
+
status: "unavailable";
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* The injected live-search function. Given the resolved category (+ its Overture leaf fan-out) and the anchor text, it
|
|
82
|
+
* probes the published poi.db and returns hits. Absent ⇒ the explorer runs intent-only (no "Search live" button).
|
|
83
|
+
*
|
|
84
|
+
* Brand support is ADDITIVE: when the resolved subject is a chain brand, `brandWikidata` carries its QID and the probe
|
|
85
|
+
* fetches by that QID instead of a category k-ring (`categoryID`/`overtureCategoryIDs` are then the brand name / empty
|
|
86
|
+
* and unused). The category path is byte-identical to before. A probe that can't serve brands simply leaves brand live
|
|
87
|
+
* search unwired at the call site (see `usePOISearch`'s `brandLiveSearch` option) — the docs' httpvfs probe does
|
|
88
|
+
* exactly that, brand-wide row hydration being pathological over byte-range (measured; the brand path is server-side
|
|
89
|
+
* only).
|
|
90
|
+
*/
|
|
91
|
+
export type POILiveSearch = (params: {
|
|
92
|
+
categoryID: string;
|
|
93
|
+
overtureCategoryIDs: string[];
|
|
94
|
+
anchor: string;
|
|
95
|
+
/** Present when the subject is a chain brand — the probe fetches by this QID, not a category k-ring. */
|
|
96
|
+
brandWikidata?: string;
|
|
97
|
+
}) => Promise<POILiveSearchResult>;
|
|
98
|
+
/** "Search live" state machine. */
|
|
99
|
+
export type LiveSearchState = {
|
|
100
|
+
status: "idle";
|
|
101
|
+
} | {
|
|
102
|
+
status: "loading";
|
|
103
|
+
} | {
|
|
104
|
+
status: "error";
|
|
105
|
+
message: string;
|
|
106
|
+
} | {
|
|
107
|
+
status: "success";
|
|
108
|
+
hits: POISearchHit[];
|
|
109
|
+
centerName: string;
|
|
110
|
+
};
|
|
111
|
+
/** A single-argument runtime loader — injectable so stories/tests can substitute a mock taxonomy. */
|
|
112
|
+
export type LoadPOIRuntime = () => Promise<POIRuntime>;
|
|
113
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../poi/types.ts"],"names":[],"mappings":"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"}
|
package/out/poi/types.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Types for the POI explorer. The intent path (classification → subject → OverpassQL) is fully
|
|
7
|
+
* self-contained over the pure `@mailwoman/*` packages; the live poi.db path is expressed only as an
|
|
8
|
+
* INJECTED async function ({@link POILiveSearch}) so the httpvfs/worker machinery stays out of this
|
|
9
|
+
* package's browser graph (it lives in the docs site, which knows where the layer is served).
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../poi/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `usePOISearch` — the headless core of the POI explorer. Owns the taxonomy-runtime load, the
|
|
7
|
+
* debounced classify → subject → OverpassQL derivation, and the "Search live" state machine. The
|
|
8
|
+
* runtime loader and the live-search probe are both INJECTABLE, so stories/tests drive it with mocks
|
|
9
|
+
* and no network or db. Presentation is entirely the caller's concern.
|
|
10
|
+
*/
|
|
11
|
+
import type { LiveSearchState, LoadPOIRuntime, POIExplorerResult, POILiveSearch } from "./types.ts";
|
|
12
|
+
export interface UsePOISearchOptions {
|
|
13
|
+
/** The current query text (controlled by the caller). */
|
|
14
|
+
text: string;
|
|
15
|
+
/** Runtime loader. @default loadPOIRuntime */
|
|
16
|
+
loadRuntime?: LoadPOIRuntime;
|
|
17
|
+
/** Injected live-search probe. Absent ⇒ the live-results affordance is disabled. */
|
|
18
|
+
runLiveSearch?: POILiveSearch;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the injected probe can serve BRAND subjects (fetch by Wikidata QID). Default false: brand subjects show the
|
|
21
|
+
* intent + QID chip but no live-search affordance. The docs' httpvfs probe leaves this off — brand-wide row hydration
|
|
22
|
+
* is pathological over byte-range (measured) — so brand live search is a server-side-backend capability. Category
|
|
23
|
+
* live search is unaffected either way.
|
|
24
|
+
*/
|
|
25
|
+
brandLiveSearch?: boolean;
|
|
26
|
+
/** Debounce before (re)classifying. @default 250 */
|
|
27
|
+
debounceMs?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface UsePOISearch {
|
|
30
|
+
/** True once the taxonomy runtime has loaded. */
|
|
31
|
+
runtimeReady: boolean;
|
|
32
|
+
/** The intent result for the current (debounced) query, or null for empty input. */
|
|
33
|
+
result: POIExplorerResult | null;
|
|
34
|
+
/** State of the on-demand live poi.db search. */
|
|
35
|
+
liveSearch: LiveSearchState;
|
|
36
|
+
/** Whether a live search can run right now (a probe is wired + there's a resolved subject with an anchor). */
|
|
37
|
+
canSearchLive: boolean;
|
|
38
|
+
/** Kick off a live search for the current subject. No-op when {@link canSearchLive} is false. */
|
|
39
|
+
searchLive: () => Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export declare function usePOISearch({ text, loadRuntime, runLiveSearch, brandLiveSearch, debounceMs, }: UsePOISearchOptions): UsePOISearch;
|
|
42
|
+
//# sourceMappingURL=usePOISearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePOISearch.d.ts","sourceRoot":"","sources":["../../poi/usePOISearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAc,MAAM,YAAY,CAAA;AAE/G,MAAM,WAAW,mBAAmB;IACnC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B,oFAAoF;IACpF,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,iDAAiD;IACjD,YAAY,EAAE,OAAO,CAAA;IACrB,oFAAoF;IACpF,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAChC,iDAAiD;IACjD,UAAU,EAAE,eAAe,CAAA;IAC3B,8GAA8G;IAC9G,aAAa,EAAE,OAAO,CAAA;IACtB,iGAAiG;IACjG,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B;AA2BD,wBAAgB,YAAY,CAAC,EAC5B,IAAI,EACJ,WAA4B,EAC5B,aAAa,EACb,eAAuB,EACvB,UAAgB,GAChB,EAAE,mBAAmB,GAAG,YAAY,CAsJpC"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `usePOISearch` — the headless core of the POI explorer. Owns the taxonomy-runtime load, the
|
|
7
|
+
* debounced classify → subject → OverpassQL derivation, and the "Search live" state machine. The
|
|
8
|
+
* runtime loader and the live-search probe are both INJECTABLE, so stories/tests drive it with mocks
|
|
9
|
+
* and no network or db. Presentation is entirely the caller's concern.
|
|
10
|
+
*/
|
|
11
|
+
import { matchPOISubject } from "@mailwoman/kind-classifier";
|
|
12
|
+
import { emitOverpassQL } from "@mailwoman/poi-taxonomy/overpass";
|
|
13
|
+
import { computeQueryShape } from "@mailwoman/query-shape";
|
|
14
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
15
|
+
import { useDebouncedValue } from "../common/useDebouncedValue.js";
|
|
16
|
+
import { loadPOIRuntime } from "./runtime.js";
|
|
17
|
+
/** Compute the OverpassQL export for a matched subject, capturing any emitter error rather than throwing. */
|
|
18
|
+
function buildOverpass(runtime, categoryID, matchedPhrase, remainder) {
|
|
19
|
+
const category = runtime.lookup.getPOICategory(categoryID);
|
|
20
|
+
if (!category) {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
const intent = {
|
|
24
|
+
subject: { kind: "category", categoryID, matched: matchedPhrase },
|
|
25
|
+
...(remainder ? { anchor: { text: remainder } } : {}),
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
return { overpassQL: emitOverpassQL(intent, category.osmTag ? { osmTag: category.osmTag } : {}) };
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return { overpassError: err instanceof Error ? err.message : String(err) };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function usePOISearch({ text, loadRuntime = loadPOIRuntime, runLiveSearch, brandLiveSearch = false, debounceMs = 250, }) {
|
|
35
|
+
const [runtime, setRuntime] = useState(null);
|
|
36
|
+
const [result, setResult] = useState(null);
|
|
37
|
+
const [liveSearch, setLiveSearch] = useState({ status: "idle" });
|
|
38
|
+
const debouncedText = useDebouncedValue(text, debounceMs);
|
|
39
|
+
// Capture the loader in a ref so the load fires exactly ONCE on mount, regardless of whether the
|
|
40
|
+
// caller passes a fresh `loadRuntime` closure each render (an inline `async () => …` would otherwise
|
|
41
|
+
// retrigger the effect → reload → re-render loop). The runtime is a load-once resource.
|
|
42
|
+
const loadRuntimeRef = useRef(loadRuntime);
|
|
43
|
+
loadRuntimeRef.current = loadRuntime;
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
let cancelled = false;
|
|
46
|
+
loadRuntimeRef.current().then((loaded) => {
|
|
47
|
+
if (!cancelled) {
|
|
48
|
+
setRuntime(loaded);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return () => {
|
|
52
|
+
cancelled = true;
|
|
53
|
+
};
|
|
54
|
+
}, []);
|
|
55
|
+
// Classify the debounced query and derive the subject + OverpassQL (async, so it lives in an effect).
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (!runtime)
|
|
58
|
+
return;
|
|
59
|
+
let cancelled = false;
|
|
60
|
+
const trimmed = debouncedText.trim();
|
|
61
|
+
// A new query invalidates live results from the previous one.
|
|
62
|
+
setLiveSearch({ status: "idle" });
|
|
63
|
+
if (!trimmed) {
|
|
64
|
+
setResult(null);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const input = { raw: trimmed, normalized: trimmed };
|
|
68
|
+
const shape = computeQueryShape(trimmed);
|
|
69
|
+
runtime.classify(input, shape).then((kindResult) => {
|
|
70
|
+
if (cancelled)
|
|
71
|
+
return;
|
|
72
|
+
const matched = kindResult.kind === "poi_query" ? matchPOISubject(trimmed, undefined, runtime.lexicon) : null;
|
|
73
|
+
if (!matched) {
|
|
74
|
+
setResult({ kindResult });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Brand subject: the lexicon carries the brand's canonical name as `categoryID` + its Wikidata QID. No category
|
|
78
|
+
// record, no OverpassQL (brands are searched by QID against the layer's `brand_wikidata` index, not OSM tags).
|
|
79
|
+
if ((matched.match.kind ?? "category") === "brand") {
|
|
80
|
+
setResult({
|
|
81
|
+
kindResult,
|
|
82
|
+
subject: {
|
|
83
|
+
kind: "brand",
|
|
84
|
+
name: matched.match.categoryID,
|
|
85
|
+
...(matched.match.wikidata ? { wikidata: matched.match.wikidata } : {}),
|
|
86
|
+
matchedPhrase: matched.match.matchedPhrase,
|
|
87
|
+
confidence: matched.match.confidence,
|
|
88
|
+
remainder: matched.remainder,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const category = runtime.lookup.getPOICategory(matched.match.categoryID);
|
|
94
|
+
if (!category) {
|
|
95
|
+
setResult({ kindResult });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
setResult({
|
|
99
|
+
kindResult,
|
|
100
|
+
subject: {
|
|
101
|
+
kind: "category",
|
|
102
|
+
category,
|
|
103
|
+
matchedPhrase: matched.match.matchedPhrase,
|
|
104
|
+
confidence: matched.match.confidence,
|
|
105
|
+
remainder: matched.remainder,
|
|
106
|
+
buildLocal: runtime.lookup.requiresBuildLocalLayer(category),
|
|
107
|
+
},
|
|
108
|
+
...buildOverpass(runtime, matched.match.categoryID, matched.match.matchedPhrase, matched.remainder),
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
return () => {
|
|
112
|
+
cancelled = true;
|
|
113
|
+
};
|
|
114
|
+
}, [debouncedText, runtime]);
|
|
115
|
+
const subject = result?.subject;
|
|
116
|
+
// A subject is live-searchable when a probe is wired, it has an anchor, and: a CATEGORY that isn't build-local, or a
|
|
117
|
+
// BRAND with a QID AND a brand-capable probe (`brandLiveSearch`). Brands without a QID / without a brand probe show
|
|
118
|
+
// the intent + QID chip but no live affordance.
|
|
119
|
+
const subjectLiveCapable = subject !== undefined &&
|
|
120
|
+
(subject.kind === "brand" ? brandLiveSearch && subject.wikidata !== undefined : !subject.buildLocal);
|
|
121
|
+
const canSearchLive = Boolean(runLiveSearch && runtime && subject && subjectLiveCapable && subject.remainder.trim().length > 0);
|
|
122
|
+
const searchLive = useCallback(async () => {
|
|
123
|
+
if (!runLiveSearch || !runtime || !subject || !subject.remainder.trim())
|
|
124
|
+
return;
|
|
125
|
+
if (subject.kind === "category" ? subject.buildLocal : !(brandLiveSearch && subject.wikidata))
|
|
126
|
+
return;
|
|
127
|
+
setLiveSearch({ status: "loading" });
|
|
128
|
+
try {
|
|
129
|
+
const outcome = await runLiveSearch(subject.kind === "brand"
|
|
130
|
+
? {
|
|
131
|
+
categoryID: subject.name,
|
|
132
|
+
overtureCategoryIDs: [],
|
|
133
|
+
anchor: subject.remainder,
|
|
134
|
+
brandWikidata: subject.wikidata,
|
|
135
|
+
}
|
|
136
|
+
: {
|
|
137
|
+
categoryID: subject.category.id,
|
|
138
|
+
// Fan the canonical seed id out over its Overture leaves — the same translation the Node reader uses.
|
|
139
|
+
overtureCategoryIDs: runtime.lookup.resolveOvertureCategories(subject.category.id),
|
|
140
|
+
anchor: subject.remainder,
|
|
141
|
+
});
|
|
142
|
+
if (outcome.status === "success") {
|
|
143
|
+
setLiveSearch({ status: "success", hits: outcome.hits, centerName: outcome.centerName });
|
|
144
|
+
}
|
|
145
|
+
else if (outcome.status === "unplaced") {
|
|
146
|
+
setLiveSearch({ status: "error", message: `couldn't place "${outcome.anchor}"` });
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
setLiveSearch({ status: "error", message: "the published POI layer isn't reachable" });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
setLiveSearch({ status: "error", message: "the published POI layer isn't reachable" });
|
|
154
|
+
}
|
|
155
|
+
}, [runLiveSearch, runtime, subject, brandLiveSearch]);
|
|
156
|
+
return { runtimeReady: runtime !== null, result, liveSearch, canSearchLive, searchLive };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=usePOISearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePOISearch.js","sourceRoot":"","sources":["../../poi/usePOISearch.ts"],"names":[],"mappings":"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"}
|