@stapel/search-react 0.3.1 → 0.7.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/CHANGELOG.md +180 -0
- package/MODULE.md +43 -4
- package/README.md +1 -1
- package/dist/api/generated/schema.d.ts +5 -1
- package/dist/api/generated/schema.d.ts.map +1 -1
- package/dist/default/DegradationNotice.d.ts +34 -0
- package/dist/default/DegradationNotice.d.ts.map +1 -1
- package/dist/default/DegradationNotice.js +28 -6
- package/dist/default/DegradationNotice.js.map +1 -1
- package/dist/default/FacetPanelPane.d.ts +54 -3
- package/dist/default/FacetPanelPane.d.ts.map +1 -1
- package/dist/default/FacetPanelPane.js +119 -19
- package/dist/default/FacetPanelPane.js.map +1 -1
- package/dist/default/LanguageSelect.d.ts +9 -0
- package/dist/default/LanguageSelect.d.ts.map +1 -0
- package/dist/default/LanguageSelect.js +72 -0
- package/dist/default/LanguageSelect.js.map +1 -0
- package/dist/default/PageSizeSelect.d.ts +29 -0
- package/dist/default/PageSizeSelect.d.ts.map +1 -0
- package/dist/default/PageSizeSelect.js +25 -0
- package/dist/default/PageSizeSelect.js.map +1 -0
- package/dist/default/RangeFilterRow.d.ts +12 -0
- package/dist/default/RangeFilterRow.d.ts.map +1 -0
- package/dist/default/RangeFilterRow.js +75 -0
- package/dist/default/RangeFilterRow.js.map +1 -0
- package/dist/default/RankingDisclosurePane.d.ts +5 -0
- package/dist/default/RankingDisclosurePane.d.ts.map +1 -1
- package/dist/default/RankingDisclosurePane.js +15 -15
- package/dist/default/RankingDisclosurePane.js.map +1 -1
- package/dist/default/SearchBox.d.ts +13 -0
- package/dist/default/SearchBox.d.ts.map +1 -0
- package/dist/default/SearchBox.js +67 -0
- package/dist/default/SearchBox.js.map +1 -0
- package/dist/default/SearchPage.d.ts +58 -16
- package/dist/default/SearchPage.d.ts.map +1 -1
- package/dist/default/SearchPage.js +155 -6
- package/dist/default/SearchPage.js.map +1 -1
- package/dist/default/SearchResultCard.d.ts +19 -18
- package/dist/default/SearchResultCard.d.ts.map +1 -1
- package/dist/default/SearchResultCard.js +178 -5
- package/dist/default/SearchResultCard.js.map +1 -1
- package/dist/default/SearchResultsPane.d.ts +54 -3
- package/dist/default/SearchResultsPane.d.ts.map +1 -1
- package/dist/default/SearchResultsPane.js +45 -25
- package/dist/default/SearchResultsPane.js.map +1 -1
- package/dist/default/SortSelect.d.ts +10 -2
- package/dist/default/SortSelect.d.ts.map +1 -1
- package/dist/default/SortSelect.js +27 -24
- package/dist/default/SortSelect.js.map +1 -1
- package/dist/default/UrlIssueNotice.d.ts.map +1 -1
- package/dist/default/UrlIssueNotice.js +19 -1
- package/dist/default/UrlIssueNotice.js.map +1 -1
- package/dist/default/index.d.ts +33 -16
- package/dist/default/index.d.ts.map +1 -1
- package/dist/default/index.js +26 -12
- package/dist/default/index.js.map +1 -1
- package/dist/default/sortLabels.d.ts +5 -0
- package/dist/default/sortLabels.d.ts.map +1 -0
- package/dist/default/sortLabels.js +32 -0
- package/dist/default/sortLabels.js.map +1 -0
- package/dist/headless/FacetPanel.d.ts +17 -0
- package/dist/headless/FacetPanel.d.ts.map +1 -1
- package/dist/headless/FacetPanel.js +23 -2
- package/dist/headless/FacetPanel.js.map +1 -1
- package/dist/headless/SearchResults.d.ts +20 -3
- package/dist/headless/SearchResults.d.ts.map +1 -1
- package/dist/headless/SearchResults.js +3 -1
- package/dist/headless/SearchResults.js.map +1 -1
- package/dist/headless/useAppliedCount.d.ts +8 -0
- package/dist/headless/useAppliedCount.d.ts.map +1 -0
- package/dist/headless/useAppliedCount.js +30 -0
- package/dist/headless/useAppliedCount.js.map +1 -0
- package/dist/headless/useScorerNames.d.ts +4 -0
- package/dist/headless/useScorerNames.d.ts.map +1 -0
- package/dist/headless/useScorerNames.js +34 -0
- package/dist/headless/useScorerNames.js.map +1 -0
- package/dist/headless/useSearchBox.d.ts +44 -0
- package/dist/headless/useSearchBox.d.ts.map +1 -0
- package/dist/headless/useSearchBox.js +116 -0
- package/dist/headless/useSearchBox.js.map +1 -0
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +32 -4
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/keys.d.ts +46 -2
- package/dist/i18n/keys.d.ts.map +1 -1
- package/dist/i18n/keys.js +86 -6
- package/dist/i18n/keys.js.map +1 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +38 -4
- package/dist/i18n/ru.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/model/queries.d.ts +26 -2
- package/dist/model/queries.d.ts.map +1 -1
- package/dist/model/queries.js +38 -1
- package/dist/model/queries.js.map +1 -1
- package/dist/state/degradations.d.ts +41 -0
- package/dist/state/degradations.d.ts.map +1 -1
- package/dist/state/degradations.js +41 -0
- package/dist/state/degradations.js.map +1 -1
- package/dist/state/limits.d.ts +44 -0
- package/dist/state/limits.d.ts.map +1 -0
- package/dist/state/limits.js +44 -0
- package/dist/state/limits.js.map +1 -0
- package/dist/state/ranges.d.ts +52 -0
- package/dist/state/ranges.d.ts.map +1 -0
- package/dist/state/ranges.js +108 -0
- package/dist/state/ranges.js.map +1 -0
- package/llms.txt +16 -5
- package/manifest.json +245 -22
- package/nav-manifest.json +1 -1
- package/package.json +15 -10
- package/src/analytics/generated/events.json +1 -1
- package/src/api/generated/schema.ts +5 -1
- package/src/default/DegradationNotice.tsx +84 -14
- package/src/default/FacetPanelPane.tsx +343 -64
- package/src/default/LanguageSelect.tsx +93 -0
- package/src/default/PageSizeSelect.tsx +80 -0
- package/src/default/RangeFilterRow.tsx +148 -0
- package/src/default/RankingDisclosurePane.tsx +67 -35
- package/src/default/SearchBox.tsx +130 -0
- package/src/default/SearchPage.tsx +356 -41
- package/src/default/SearchResultCard.tsx +231 -24
- package/src/default/SearchResultsPane.tsx +147 -76
- package/src/default/SortSelect.tsx +50 -37
- package/src/default/UrlIssueNotice.tsx +21 -3
- package/src/default/index.ts +42 -16
- package/src/default/sortLabels.ts +34 -0
- package/src/headless/FacetPanel.tsx +30 -2
- package/src/headless/SearchResults.tsx +32 -4
- package/src/headless/useAppliedCount.ts +41 -0
- package/src/headless/useScorerNames.ts +36 -0
- package/src/headless/useSearchBox.ts +189 -0
- package/src/i18n/es.ts +39 -4
- package/src/i18n/keys.ts +97 -6
- package/src/i18n/ru.ts +45 -4
- package/src/index.ts +30 -3
- package/src/model/queries.ts +51 -1
- package/src/state/degradations.ts +60 -0
- package/src/state/limits.ts +50 -0
- package/src/state/ranges.ts +144 -0
- package/dist/default/ErrorAlert.d.ts +0 -9
- package/dist/default/ErrorAlert.d.ts.map +0 -1
- package/dist/default/ErrorAlert.js +0 -27
- package/dist/default/ErrorAlert.js.map +0 -1
- package/dist/default/theme.d.ts +0 -24
- package/dist/default/theme.d.ts.map +0 -1
- package/dist/default/theme.js +0 -39
- package/dist/default/theme.js.map +0 -1
- package/src/default/ErrorAlert.tsx +0 -46
- package/src/default/theme.tsx +0 -66
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The RANGE half of the filter model — `r.<slug>=from..to`.
|
|
3
|
+
*
|
|
4
|
+
* The codec has carried ranges since 0.1 (`setRangeValue`, `RANGE_PREFIX`) and
|
|
5
|
+
* nothing ever drew one: a marketplace shipped without a price filter because
|
|
6
|
+
* the panel only knew how to draw checkboxes. This module is the missing half:
|
|
7
|
+
* which slugs a range row exists for, and what the row is called.
|
|
8
|
+
*
|
|
9
|
+
* ── Where a range row comes from, and why it is not the response ───────────
|
|
10
|
+
*
|
|
11
|
+
* A facet answer (`facets: {slug: {value: count}}`) enumerates DISCRETE values;
|
|
12
|
+
* a range is not enumerable and the server never sends one. So the rows come
|
|
13
|
+
* from the CATEGORY SCHEMA — the same `categoryFeatures` slot that gives the
|
|
14
|
+
* checkboxes their labels — filtered to the numeric value types, plus every
|
|
15
|
+
* slug the URL already carries a range for.
|
|
16
|
+
*
|
|
17
|
+
* That last clause is the same rule `buildFacetGroups` follows for a filtered
|
|
18
|
+
* slug that fell out of the plan: a constraint that is ACTIVE must always have
|
|
19
|
+
* a control that removes it, even when the schema no longer explains it.
|
|
20
|
+
* Otherwise a shared link narrows the search with nothing on screen to widen it
|
|
21
|
+
* again.
|
|
22
|
+
*
|
|
23
|
+
* `date` is range-capable on the wire and is deliberately NOT here: a date
|
|
24
|
+
* range needs a date editor, the editor lives in `@stapel/attributes-react`'s
|
|
25
|
+
* registry, and a numeric input over a Unix timestamp would be worse than no
|
|
26
|
+
* control at all. The codec still round-trips one a host sets.
|
|
27
|
+
*/
|
|
28
|
+
import { featureConfig, featureName, featureType } from "@stapel/attributes-react";
|
|
29
|
+
import type { FeatureDef } from "@stapel/attributes-react";
|
|
30
|
+
import type { SearchQueryState, SearchRange } from "../api/types.js";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Value types a numeric range row is drawn for (`config.type`, the
|
|
34
|
+
* stapel-attributes value-type slug).
|
|
35
|
+
*/
|
|
36
|
+
export const RANGE_FEATURE_TYPES: readonly string[] = [
|
|
37
|
+
"int",
|
|
38
|
+
"float",
|
|
39
|
+
"convertible_unit",
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
/** One `r.<slug>` row of the filter panel. */
|
|
43
|
+
export interface RangeGroup {
|
|
44
|
+
readonly slug: string;
|
|
45
|
+
/** The feature's display name (translated when it is a key), else the slug. */
|
|
46
|
+
readonly label: string;
|
|
47
|
+
/** The schema entry behind the slug, when the host supplied one. */
|
|
48
|
+
readonly feature: FeatureDef | undefined;
|
|
49
|
+
/** The applied bounds, exactly as the URL carries them (strings — the wire
|
|
50
|
+
* never promised a number, and re-formatting one would rewrite the link). */
|
|
51
|
+
readonly from: string | undefined;
|
|
52
|
+
readonly to: string | undefined;
|
|
53
|
+
/** Bounds the schema declares, for the input's own limits. */
|
|
54
|
+
readonly min: number | undefined;
|
|
55
|
+
readonly max: number | undefined;
|
|
56
|
+
/** Unit suffix the schema declares (`postfix`, or a convertible unit). */
|
|
57
|
+
readonly unit: string | undefined;
|
|
58
|
+
/** `1` for an integer feature — a whole-number input for a whole number. */
|
|
59
|
+
readonly step: number | undefined;
|
|
60
|
+
/** Whether the URL currently constrains this slug. */
|
|
61
|
+
readonly active: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface BuildRangeGroupsInput {
|
|
65
|
+
readonly state: SearchQueryState;
|
|
66
|
+
readonly categoryFeatures?: readonly FeatureDef[];
|
|
67
|
+
/** Translator for label keys (the schema's `name` is often one). */
|
|
68
|
+
readonly t?: (key: string) => string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function num(value: unknown): number | undefined {
|
|
72
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function str(value: unknown): string | undefined {
|
|
76
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function translate(t: ((key: string) => string) | undefined, key: string): string {
|
|
80
|
+
if (t === undefined) return key;
|
|
81
|
+
const resolved = t(key);
|
|
82
|
+
return resolved.length > 0 ? resolved : key;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Is this feature one a numeric range row is drawn for? */
|
|
86
|
+
export function isRangeFeature(feature: FeatureDef): boolean {
|
|
87
|
+
const type = featureType(feature);
|
|
88
|
+
return type !== undefined && RANGE_FEATURE_TYPES.includes(type);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The range rows for the current search: every numeric feature of the
|
|
93
|
+
* category, in the schema's own order, plus any slug the URL constrains that
|
|
94
|
+
* the schema does not explain.
|
|
95
|
+
*/
|
|
96
|
+
export function buildRangeGroups(
|
|
97
|
+
input: BuildRangeGroupsInput
|
|
98
|
+
): readonly RangeGroup[] {
|
|
99
|
+
const bySlug = new Map<string, FeatureDef>();
|
|
100
|
+
for (const feature of input.categoryFeatures ?? []) bySlug.set(feature.slug, feature);
|
|
101
|
+
|
|
102
|
+
const slugs: string[] = [];
|
|
103
|
+
for (const feature of input.categoryFeatures ?? []) {
|
|
104
|
+
if (isRangeFeature(feature)) slugs.push(feature.slug);
|
|
105
|
+
}
|
|
106
|
+
for (const slug of Object.keys(input.state.ranges)) {
|
|
107
|
+
if (!slugs.includes(slug)) slugs.push(slug);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return slugs.map((slug) => {
|
|
111
|
+
const feature = bySlug.get(slug);
|
|
112
|
+
const config = feature === undefined ? {} : featureConfig(feature);
|
|
113
|
+
const applied: SearchRange | undefined = input.state.ranges[slug];
|
|
114
|
+
return {
|
|
115
|
+
slug,
|
|
116
|
+
label:
|
|
117
|
+
feature === undefined ? slug : translate(input.t, featureName(feature)),
|
|
118
|
+
feature,
|
|
119
|
+
from: applied?.from,
|
|
120
|
+
to: applied?.to,
|
|
121
|
+
min: num(config["min"]),
|
|
122
|
+
max: num(config["max"]),
|
|
123
|
+
unit: str(config["postfix"]) ?? str(config["unit_m"]) ?? str(config["unit_i"]),
|
|
124
|
+
step: feature !== undefined && featureType(feature) === "int" ? 1 : undefined,
|
|
125
|
+
active: applied !== undefined,
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Is a from/to pair one the server could ever match?
|
|
132
|
+
*
|
|
133
|
+
* `100..50` is syntactically fine and semantically empty, and the backend does
|
|
134
|
+
* not refuse it — it answers zero results, which reads as "there is nothing
|
|
135
|
+
* like this" rather than "you typed it backwards". So the panel refuses to
|
|
136
|
+
* apply it and says why, beside the button (`search.facets.range_invalid`).
|
|
137
|
+
*/
|
|
138
|
+
export function isRangeUsable(range: SearchRange): boolean {
|
|
139
|
+
if (range.from === undefined || range.to === undefined) return true;
|
|
140
|
+
const from = Number(range.from);
|
|
141
|
+
const to = Number(range.to);
|
|
142
|
+
if (!Number.isFinite(from) || !Number.isFinite(to)) return true;
|
|
143
|
+
return from <= to;
|
|
144
|
+
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
|
-
import type { FlowErrorDisplay } from "@stapel/core";
|
|
3
|
-
export declare function ErrorAlert(props: {
|
|
4
|
-
error: FlowErrorDisplay | undefined;
|
|
5
|
-
style?: CSSProperties | undefined;
|
|
6
|
-
testId?: string | undefined;
|
|
7
|
-
action?: ReactNode;
|
|
8
|
-
}): ReactElement | null;
|
|
9
|
-
//# sourceMappingURL=ErrorAlert.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorAlert.d.ts","sourceRoot":"","sources":["../../src/default/ErrorAlert.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,KAAK,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,GAAG,YAAY,GAAG,IAAI,CAsBtB"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* The one error surface this pair's default skin renders, so the split copy
|
|
4
|
-
* core produces reaches a screen the same way everywhere (mirrors the
|
|
5
|
-
* docs/notifications/workspaces etalon).
|
|
6
|
-
*
|
|
7
|
-
* Core's `describeFlowError` splits a failure into the sentence a person
|
|
8
|
-
* reads and the technical detail a support agent quotes (owner report
|
|
9
|
-
* 2026-08-09: the status used to be spliced into the sentence, ending in a
|
|
10
|
-
* bare `" (500)"`). The split only helps if a skin renders both halves at
|
|
11
|
-
* their own weights: `message` at normal weight, `detail` muted and small.
|
|
12
|
-
*
|
|
13
|
-
* `undefined` in — including a `detail` core left `undefined` because there
|
|
14
|
-
* was nothing worth quoting — renders nothing rather than an empty line.
|
|
15
|
-
*/
|
|
16
|
-
import { Alert, Typography } from "antd";
|
|
17
|
-
export function ErrorAlert(props) {
|
|
18
|
-
const { error } = props;
|
|
19
|
-
if (!error)
|
|
20
|
-
return null;
|
|
21
|
-
return (_jsx(Alert, { type: "error", showIcon: true, ...(props.style ? { style: props.style } : {}), ...(props.testId ? { "data-testid": props.testId } : {}), ...(props.action ? { action: props.action } : {}), message: error.message, ...(error.detail
|
|
22
|
-
? {
|
|
23
|
-
description: (_jsx(Typography.Text, { type: "secondary", style: { fontSize: 12 }, children: error.detail })),
|
|
24
|
-
}
|
|
25
|
-
: {}) }));
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=ErrorAlert.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorAlert.js","sourceRoot":"","sources":["../../src/default/ErrorAlert.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAIzC,MAAM,UAAU,UAAU,CAAC,KAK1B;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IACxB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,CACL,KAAC,KAAK,IACJ,IAAI,EAAC,OAAO,EACZ,QAAQ,WACJ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC3C,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACrD,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAClD,OAAO,EAAE,KAAK,CAAC,OAAO,KAClB,CAAC,KAAK,CAAC,MAAM;YACf,CAAC,CAAC;gBACE,WAAW,EAAE,CACX,KAAC,UAAU,CAAC,IAAI,IAAC,IAAI,EAAC,WAAW,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,YACtD,KAAK,CAAC,MAAM,GACG,CACnB;aACF;YACH,CAAC,CAAC,EAAE,CAAC,GACP,CACH,CAAC;AACJ,CAAC"}
|
package/dist/default/theme.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
|
-
import type { ThemeMode } from "@stapel/tokens-antd";
|
|
3
|
-
export interface SearchSkinThemeProps {
|
|
4
|
-
/**
|
|
5
|
-
* Light or dark. Defaults to the mode the host's document declares
|
|
6
|
-
* (`resolveThemeMode()`). Pass explicitly to pin a side.
|
|
7
|
-
*/
|
|
8
|
-
readonly mode?: ThemeMode;
|
|
9
|
-
/** Extra styles merged onto the themed root element (layout only — colors
|
|
10
|
-
* come from the mode). */
|
|
11
|
-
readonly style?: CSSProperties;
|
|
12
|
-
readonly children: ReactNode;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* `<SearchSkinTheme/>` — the self-theming wrapper of
|
|
16
|
-
* `@stapel/search-react/default`. Standalone use is supported (wrap any
|
|
17
|
-
* composition of the skin's parts once); the shipped surfaces
|
|
18
|
-
* (`SearchPage`, `SearchResultsPane`, `FacetPanelPane`,
|
|
19
|
-
* `RankingDisclosurePane`) each already wrap themselves, and nested antd
|
|
20
|
-
* `ConfigProvider`s merge, so composing them under one `SearchSkinTheme`
|
|
21
|
-
* stays correct.
|
|
22
|
-
*/
|
|
23
|
-
export declare function SearchSkinTheme(props: SearchSkinThemeProps): ReactElement;
|
|
24
|
-
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/default/theme.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B;8BAC0B;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CAmBzE"}
|
package/dist/default/theme.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* The default skin's INTERNAL theme provider — every `/default` surface wraps
|
|
4
|
-
* itself in this, so the skin is readable no matter what the host supplies
|
|
5
|
-
* (tracker #26: a skin set with no internal provider once inherited a theme
|
|
6
|
-
* bridge serving light-mode values inside a dark document — text on
|
|
7
|
-
* background at 1.00:1). The theme derives from `@stapel/tokens` via
|
|
8
|
-
* `@stapel/tokens-antd`'s `toAntdThemeConfig(mode)`; `mode` defaults to what
|
|
9
|
-
* the HOST's document declares (`resolveThemeMode()` — the `data-theme`
|
|
10
|
-
* attribute `tokens.css` keys its dark block on), never to a hardcoded side.
|
|
11
|
-
*
|
|
12
|
-
* This is also what "override styles" means for this pair: a storefront
|
|
13
|
-
* retheming through the §68 token JSON regenerates its `--stapel-*` custom
|
|
14
|
-
* properties and the result page follows with zero code — a far better deal
|
|
15
|
-
* than a prop-per-colour API, and the reason the skin has none.
|
|
16
|
-
*/
|
|
17
|
-
import { useMemo } from "react";
|
|
18
|
-
import { ConfigProvider } from "antd";
|
|
19
|
-
import { resolveThemeMode, toAntdTheme, toAntdThemeConfig, } from "@stapel/tokens-antd";
|
|
20
|
-
/**
|
|
21
|
-
* `<SearchSkinTheme/>` — the self-theming wrapper of
|
|
22
|
-
* `@stapel/search-react/default`. Standalone use is supported (wrap any
|
|
23
|
-
* composition of the skin's parts once); the shipped surfaces
|
|
24
|
-
* (`SearchPage`, `SearchResultsPane`, `FacetPanelPane`,
|
|
25
|
-
* `RankingDisclosurePane`) each already wrap themselves, and nested antd
|
|
26
|
-
* `ConfigProvider`s merge, so composing them under one `SearchSkinTheme`
|
|
27
|
-
* stays correct.
|
|
28
|
-
*/
|
|
29
|
-
export function SearchSkinTheme(props) {
|
|
30
|
-
const mode = props.mode ?? resolveThemeMode();
|
|
31
|
-
const theme = useMemo(() => toAntdThemeConfig(mode), [mode]);
|
|
32
|
-
const token = useMemo(() => toAntdTheme(mode), [mode]);
|
|
33
|
-
return (_jsx(ConfigProvider, { theme: theme, children: _jsx("div", { "data-search-skin-root": true, "data-search-skin-mode": mode, style: {
|
|
34
|
-
color: token.colorText,
|
|
35
|
-
backgroundColor: token.colorBgContainer,
|
|
36
|
-
...props.style,
|
|
37
|
-
}, children: props.children }) }));
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=theme.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/default/theme.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAe7B;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,OAAO,CACL,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,YAC1B,sEAEyB,IAAI,EAC3B,KAAK,EAAE;gBACL,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,eAAe,EAAE,KAAK,CAAC,gBAAgB;gBACvC,GAAG,KAAK,CAAC,KAAK;aACf,YAEA,KAAK,CAAC,QAAQ,GACX,GACS,CAClB,CAAC;AACJ,CAAC"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The one error surface this pair's default skin renders, so the split copy
|
|
3
|
-
* core produces reaches a screen the same way everywhere (mirrors the
|
|
4
|
-
* docs/notifications/workspaces etalon).
|
|
5
|
-
*
|
|
6
|
-
* Core's `describeFlowError` splits a failure into the sentence a person
|
|
7
|
-
* reads and the technical detail a support agent quotes (owner report
|
|
8
|
-
* 2026-08-09: the status used to be spliced into the sentence, ending in a
|
|
9
|
-
* bare `" (500)"`). The split only helps if a skin renders both halves at
|
|
10
|
-
* their own weights: `message` at normal weight, `detail` muted and small.
|
|
11
|
-
*
|
|
12
|
-
* `undefined` in — including a `detail` core left `undefined` because there
|
|
13
|
-
* was nothing worth quoting — renders nothing rather than an empty line.
|
|
14
|
-
*/
|
|
15
|
-
import { Alert, Typography } from "antd";
|
|
16
|
-
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
17
|
-
import type { FlowErrorDisplay } from "@stapel/core";
|
|
18
|
-
|
|
19
|
-
export function ErrorAlert(props: {
|
|
20
|
-
error: FlowErrorDisplay | undefined;
|
|
21
|
-
style?: CSSProperties | undefined;
|
|
22
|
-
testId?: string | undefined;
|
|
23
|
-
action?: ReactNode;
|
|
24
|
-
}): ReactElement | null {
|
|
25
|
-
const { error } = props;
|
|
26
|
-
if (!error) return null;
|
|
27
|
-
return (
|
|
28
|
-
<Alert
|
|
29
|
-
type="error"
|
|
30
|
-
showIcon
|
|
31
|
-
{...(props.style ? { style: props.style } : {})}
|
|
32
|
-
{...(props.testId ? { "data-testid": props.testId } : {})}
|
|
33
|
-
{...(props.action ? { action: props.action } : {})}
|
|
34
|
-
message={error.message}
|
|
35
|
-
{...(error.detail
|
|
36
|
-
? {
|
|
37
|
-
description: (
|
|
38
|
-
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
|
39
|
-
{error.detail}
|
|
40
|
-
</Typography.Text>
|
|
41
|
-
),
|
|
42
|
-
}
|
|
43
|
-
: {})}
|
|
44
|
-
/>
|
|
45
|
-
);
|
|
46
|
-
}
|
package/src/default/theme.tsx
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The default skin's INTERNAL theme provider — every `/default` surface wraps
|
|
3
|
-
* itself in this, so the skin is readable no matter what the host supplies
|
|
4
|
-
* (tracker #26: a skin set with no internal provider once inherited a theme
|
|
5
|
-
* bridge serving light-mode values inside a dark document — text on
|
|
6
|
-
* background at 1.00:1). The theme derives from `@stapel/tokens` via
|
|
7
|
-
* `@stapel/tokens-antd`'s `toAntdThemeConfig(mode)`; `mode` defaults to what
|
|
8
|
-
* the HOST's document declares (`resolveThemeMode()` — the `data-theme`
|
|
9
|
-
* attribute `tokens.css` keys its dark block on), never to a hardcoded side.
|
|
10
|
-
*
|
|
11
|
-
* This is also what "override styles" means for this pair: a storefront
|
|
12
|
-
* retheming through the §68 token JSON regenerates its `--stapel-*` custom
|
|
13
|
-
* properties and the result page follows with zero code — a far better deal
|
|
14
|
-
* than a prop-per-colour API, and the reason the skin has none.
|
|
15
|
-
*/
|
|
16
|
-
import { useMemo } from "react";
|
|
17
|
-
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
18
|
-
import { ConfigProvider } from "antd";
|
|
19
|
-
import {
|
|
20
|
-
resolveThemeMode,
|
|
21
|
-
toAntdTheme,
|
|
22
|
-
toAntdThemeConfig,
|
|
23
|
-
} from "@stapel/tokens-antd";
|
|
24
|
-
import type { ThemeMode } from "@stapel/tokens-antd";
|
|
25
|
-
|
|
26
|
-
export interface SearchSkinThemeProps {
|
|
27
|
-
/**
|
|
28
|
-
* Light or dark. Defaults to the mode the host's document declares
|
|
29
|
-
* (`resolveThemeMode()`). Pass explicitly to pin a side.
|
|
30
|
-
*/
|
|
31
|
-
readonly mode?: ThemeMode;
|
|
32
|
-
/** Extra styles merged onto the themed root element (layout only — colors
|
|
33
|
-
* come from the mode). */
|
|
34
|
-
readonly style?: CSSProperties;
|
|
35
|
-
readonly children: ReactNode;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* `<SearchSkinTheme/>` — the self-theming wrapper of
|
|
40
|
-
* `@stapel/search-react/default`. Standalone use is supported (wrap any
|
|
41
|
-
* composition of the skin's parts once); the shipped surfaces
|
|
42
|
-
* (`SearchPage`, `SearchResultsPane`, `FacetPanelPane`,
|
|
43
|
-
* `RankingDisclosurePane`) each already wrap themselves, and nested antd
|
|
44
|
-
* `ConfigProvider`s merge, so composing them under one `SearchSkinTheme`
|
|
45
|
-
* stays correct.
|
|
46
|
-
*/
|
|
47
|
-
export function SearchSkinTheme(props: SearchSkinThemeProps): ReactElement {
|
|
48
|
-
const mode = props.mode ?? resolveThemeMode();
|
|
49
|
-
const theme = useMemo(() => toAntdThemeConfig(mode), [mode]);
|
|
50
|
-
const token = useMemo(() => toAntdTheme(mode), [mode]);
|
|
51
|
-
return (
|
|
52
|
-
<ConfigProvider theme={theme}>
|
|
53
|
-
<div
|
|
54
|
-
data-search-skin-root
|
|
55
|
-
data-search-skin-mode={mode}
|
|
56
|
-
style={{
|
|
57
|
-
color: token.colorText,
|
|
58
|
-
backgroundColor: token.colorBgContainer,
|
|
59
|
-
...props.style,
|
|
60
|
-
}}
|
|
61
|
-
>
|
|
62
|
-
{props.children}
|
|
63
|
-
</div>
|
|
64
|
-
</ConfigProvider>
|
|
65
|
-
);
|
|
66
|
-
}
|