@stapel/search-react 0.32.6 → 0.32.8
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 +28 -0
- package/README.md +7 -2
- package/dist/default/PartitionChips.d.ts +7 -8
- package/dist/default/PartitionChips.d.ts.map +1 -1
- package/dist/default/PartitionChips.js +54 -32
- package/dist/default/PartitionChips.js.map +1 -1
- package/dist/default/SearchPage.d.ts +42 -3
- package/dist/default/SearchPage.d.ts.map +1 -1
- package/dist/default/SearchPage.js +67 -4
- package/dist/default/SearchPage.js.map +1 -1
- package/dist/default/SearchResultsPane.d.ts +19 -0
- package/dist/default/SearchResultsPane.d.ts.map +1 -1
- package/dist/default/SearchResultsPane.js +52 -6
- package/dist/default/SearchResultsPane.js.map +1 -1
- package/dist/default/index.d.ts +2 -2
- package/dist/default/index.d.ts.map +1 -1
- package/dist/default/index.js +1 -1
- package/dist/default/index.js.map +1 -1
- package/llms.txt +1 -1
- package/manifest.json +1 -1
- package/nav-manifest.json +1 -1
- package/package.json +4 -4
- package/src/analytics/generated/events.json +1 -1
- package/src/default/PartitionChips.tsx +84 -44
- package/src/default/SearchPage.tsx +114 -5
- package/src/default/SearchResultsPane.tsx +62 -6
- package/src/default/index.ts +6 -1
|
@@ -42,9 +42,32 @@ export const RESULTS_MAX_WIDTH = 1400;
|
|
|
42
42
|
* bought went into card whitespace, not into legibility, and cost a whole
|
|
43
43
|
* column of listings on the reference desktop.
|
|
44
44
|
*/
|
|
45
|
+
export const RESULTS_AUTO_FILL_COLUMNS = "repeat(auto-fill, minmax(260px, 1fr))";
|
|
45
46
|
const RESULTS_GRID = {
|
|
46
47
|
display: "grid",
|
|
47
|
-
gridTemplateColumns:
|
|
48
|
+
gridTemplateColumns: RESULTS_AUTO_FILL_COLUMNS,
|
|
49
|
+
gap: spacing[3],
|
|
50
|
+
alignItems: "stretch",
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The same grid with the track declaration REMOVED, for the responsive column
|
|
54
|
+
* map — because an inline declaration beats a stylesheet, `!important` or not.
|
|
55
|
+
*
|
|
56
|
+
* The map's rules had nothing to win against: they were hung on a class on the
|
|
57
|
+
* very node that also carried `grid-template-columns: repeat(auto-fill, …)` as
|
|
58
|
+
* an inline style, and the browser resolves that in the inline's favour every
|
|
59
|
+
* time. A stand measuring `{ phone: 1, tablet: 2 }` read pure auto-fill (two
|
|
60
|
+
* columns at 759px, one at 448, three at 1199) — the prop was inert in a
|
|
61
|
+
* browser while every unit test on the emitted CSS string stayed green.
|
|
62
|
+
*
|
|
63
|
+
* A fixed count writes itself inline instead (there is one number and no
|
|
64
|
+
* cascade to run), so this shape is only for the map, whose base rung the
|
|
65
|
+
* sheet now always states — auto-fill when `phone` is left out, so "a key left
|
|
66
|
+
* out inherits the rung below it" still holds with nothing inline to inherit
|
|
67
|
+
* from.
|
|
68
|
+
*/
|
|
69
|
+
const RESULTS_GRID_UNSET_COLUMNS = {
|
|
70
|
+
display: "grid",
|
|
48
71
|
gap: spacing[3],
|
|
49
72
|
alignItems: "stretch",
|
|
50
73
|
};
|
|
@@ -88,10 +111,16 @@ export function resultsColumnsCss(columns) {
|
|
|
88
111
|
if (typeof columns === "number") {
|
|
89
112
|
return `${block}{grid-template-columns:${fixedColumns(columns)}}`;
|
|
90
113
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
114
|
+
// The base rung is always stated, because the pane no longer writes the
|
|
115
|
+
// auto-fill inline when a map is in play: with nothing inline to fall back
|
|
116
|
+
// to, "a key left out inherits the rung below it" has to mean the default
|
|
117
|
+
// grid, said out loud.
|
|
118
|
+
const rules = [
|
|
119
|
+
`${block}{container-type:inline-size}`,
|
|
120
|
+
`${block}{grid-template-columns:${columns.phone === undefined
|
|
121
|
+
? RESULTS_AUTO_FILL_COLUMNS
|
|
122
|
+
: fixedColumns(columns.phone)}}`,
|
|
123
|
+
];
|
|
95
124
|
for (const rung of [
|
|
96
125
|
{ at: breakpoints.tablet, count: columns.tablet },
|
|
97
126
|
{ at: breakpoints.desktop, count: columns.desktop },
|
|
@@ -148,6 +177,23 @@ export function SearchResultsPane(props) {
|
|
|
148
177
|
const columnRules = props.columns === undefined || props.layout === "list"
|
|
149
178
|
? null
|
|
150
179
|
: resultsColumnsCss(props.columns);
|
|
180
|
+
/**
|
|
181
|
+
* The tracks the NODE carries, which is the only declaration a browser
|
|
182
|
+
* actually resolves for it.
|
|
183
|
+
*
|
|
184
|
+
* An inline style beats a stylesheet rule at any specificity, so the pane
|
|
185
|
+
* must not write the auto-fill default onto the same node the column sheet
|
|
186
|
+
* targets: a fixed count is written inline (one number, no cascade to run)
|
|
187
|
+
* and a map leaves the property unset inline so its own rungs — base plus
|
|
188
|
+
* container queries — are the only ones in play.
|
|
189
|
+
*/
|
|
190
|
+
const gridStyle = props.layout === "list"
|
|
191
|
+
? RESULTS_LIST
|
|
192
|
+
: columnRules === null
|
|
193
|
+
? RESULTS_GRID
|
|
194
|
+
: typeof props.columns === "number"
|
|
195
|
+
? { ...RESULTS_GRID, gridTemplateColumns: fixedColumns(props.columns) }
|
|
196
|
+
: RESULTS_GRID_UNSET_COLUMNS;
|
|
151
197
|
return (_jsx(SkinTheme, { surface: "base", ...(props.mode !== undefined ? { mode: props.mode } : {}), style: {
|
|
152
198
|
width: "100%",
|
|
153
199
|
...(maxWidth !== null ? { maxWidth } : {}),
|
|
@@ -169,7 +215,7 @@ export function SearchResultsPane(props) {
|
|
|
169
215
|
? SEARCH_I18N_KEYS.resultsWindowExceeded
|
|
170
216
|
: SEARCH_I18N_KEYS.resultsLoadFailed), retryLabel: t(SEARCH_I18N_KEYS.resultsRetry), onRetry: bag.refetch }));
|
|
171
217
|
}, children: (items) => {
|
|
172
|
-
const arrangement = renderResults !== undefined ? (renderResults(items)) : (_jsxs("div", { style:
|
|
218
|
+
const arrangement = renderResults !== undefined ? (renderResults(items)) : (_jsxs("div", { style: gridStyle, ...(columnRules !== null
|
|
173
219
|
? { className: RESULTS_COLUMNS_CLASS }
|
|
174
220
|
: {}), "data-testid": "search-results-grid", "data-layout": props.layout ?? "grid", ...(columnRules !== null
|
|
175
221
|
? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchResultsPane.js","sourceRoot":"","sources":["../../src/default/SearchResultsPane.tsx"],"names":[],"mappings":";AA2BA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,cAAc,GACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAK/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAuCzD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC;;;;;;;;;;;;GAYG;AACH,MAAM,YAAY,GAAkB;IAClC,OAAO,EAAE,MAAM;IACf,mBAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"SearchResultsPane.js","sourceRoot":"","sources":["../../src/default/SearchResultsPane.tsx"],"names":[],"mappings":";AA2BA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,cAAc,GACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAK/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAuCzD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,uCAAuC,CAAC;AAEjF,MAAM,YAAY,GAAkB;IAClC,OAAO,EAAE,MAAM;IACf,mBAAmB,EAAE,yBAAyB;IAC9C,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACf,UAAU,EAAE,SAAS;CACtB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,0BAA0B,GAAkB;IAChD,OAAO,EAAE,MAAM;IACf,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACf,UAAU,EAAE,SAAS;CACtB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,YAAY,GAAkB;IAClC,GAAG,YAAY;IACf,mBAAmB,EAAE,KAAK;CAC3B,CAAC;AAcF,wDAAwD;AACxD,MAAM,CAAC,MAAM,qBAAqB,GAAG,+BAA+B,CAAC;AACrE,8DAA8D;AAC9D,MAAM,CAAC,MAAM,0BAA0B,GAAG,+BAA+B,CAAC;AAE1E;+EAC+E;AAC/E,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,UAAU,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAuB;IACvD,MAAM,KAAK,GAAG,IAAI,qBAAqB,EAAE,CAAC;IAC1C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,GAAG,KAAK,0BAA0B,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;IACpE,CAAC;IACD,wEAAwE;IACxE,2EAA2E;IAC3E,0EAA0E;IAC1E,uBAAuB;IACvB,MAAM,KAAK,GAAG;QACZ,GAAG,KAAK,8BAA8B;QACtC,GAAG,KAAK,0BACN,OAAO,CAAC,KAAK,KAAK,SAAS;YACzB,CAAC,CAAC,yBAAyB;YAC3B,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAChC,GAAG;KACJ,CAAC;IACF,KAAK,MAAM,IAAI,IAAI;QACjB,EAAE,EAAE,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;QACjD,EAAE,EAAE,EAAE,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE;KACpD,EAAE,CAAC;QACF,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,SAAS;QACvC,KAAK,CAAC,IAAI,CACR,0BAA0B,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;YAC5C,IAAI,KAAK,0BAA0B,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAClE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAyMD,SAAS,KAAK,CAAC,KAAgC;IAC7C,uEAAuE;IACvE,4EAA4E;IAC5E,uEAAuE;IACvE,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;IAC5B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,0EAA0E;IAC1E,wEAAwE;IACxE,mEAAmE;IACnE,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACrE,OAAO,CACL,KAAC,UAAU,CAAC,IAAI,IACd,IAAI,EAAC,WAAW,iBACJ,cAAc,qBACT,IAAI,CAAC,SAAS,YAE9B,IAAI,CAAC,SAAS,KAAK,UAAU;YAC5B,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YACtE,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,GACtD,CACnB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,KAAK,CAAC,KAAgC;IAC7C,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC;IACvD,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,OAAO,CACL,MAAC,IAAI,IAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAC,QAAQ,EAAC,IAAI,uBAAa,cAAc,aACrE,KAAC,WAAW,IACV,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,MAAM,EACf,MAAM,EAAC,aAAa,oBACL,MAAM,2BACC,0CAA0C,YAE/D,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,GACpB,EACd,KAAC,WAAW,IACV,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,MAAM,EACf,MAAM,EAAC,aAAa,oBACL,MAAM,2BACC,0CAA0C,YAE/D,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,GACpB,IACT,CACR,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAA6B;IAC7D,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IACzD,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IACnF,4EAA4E;IAC5E,4DAA4D;IAC5D,yEAAyE;IACzE,kEAAkE;IAClE,MAAM,kBAAkB,GAAG,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC;IAC/E,MAAM,WAAW,GACf,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;QACpD,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC;;;;;;;;;OASG;IACH,MAAM,SAAS,GACb,KAAK,CAAC,MAAM,KAAK,MAAM;QACrB,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,WAAW,KAAK,IAAI;YACpB,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;gBACjC,CAAC,CAAC,EAAE,GAAG,YAAY,EAAE,mBAAmB,EAAE,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;gBACvE,CAAC,CAAC,0BAA0B,CAAC;IAErC,OAAO,CACL,KAAC,SAAS,IACR,OAAO,EAAC,MAAM,KACV,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAC1D,KAAK,EAAE;YACL,KAAK,EAAE,MAAM;YACb,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3C,YAED,KAAC,aAAa,OAAK,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,YAC/E,CAAC,GAAG,EAAE,EAAE,CAAC,CACR,MAAC,IAAI,IAAC,QAAQ,QAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,aAC3B,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,CAC3B,6BAAiB,qBAAqB,YAAE,KAAK,CAAC,IAAI,GAAO,CAC1D,EACA,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAC5B,MAAC,IAAI,IAAC,QAAQ,QAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,iBAAc,+BAA+B,aACzE,KAAC,UAAU,CAAC,KAAK,IACf,KAAK,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,EAC9B,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,iBAC9C,wBAAwB,kBACtB,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,YAEnD,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,gBAAgB,CAAC,YAAY,CAAC,GACjC,EAClB,KAAK,CAAC,OAAO,EACd,KAAC,KAAK,IAAC,GAAG,EAAE,GAAG,GAAI,IACd,CACR,CAAC,CAAC,CAAC,CACF,MAAC,IAAI,IAAC,OAAO,EAAC,eAAe,EAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,QAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,aAC/D,KAAC,UAAU,CAAC,KAAK,IACf,KAAK,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,EAC9B,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,iBACR,wBAAwB,YAEnC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,gBAAgB,CAAC,YAAY,CAAC,GACjC,EACnB,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,QAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,aACvC,KAAC,KAAK,IAAC,GAAG,EAAE,GAAG,GAAI,EAClB,KAAK,CAAC,OAAO,IACT,IACF,CACR,EAED,KAAC,iBAAiB,IAChB,YAAY,EAAE,GAAG,CAAC,YAAY,EAC9B,OAAO,EAAE,KAAK,CAAC,iBAAiB,IAAI,QAAQ,EAC5C,UAAU,EAAE,UAAU,GACtB,EAKD,KAAK,CAAC,eAAe,KAAK,IAAI,IAAI,CACjC,KAAC,mBAAmB,OACd,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC/D,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS;4BACnC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE;4BACtC,CAAC,CAAC,EAAE,CAAC,KACH,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS;4BACnC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE;4BACtC,CAAC,CAAC,EAAE,CAAC,KACH,CAAC,KAAK,CAAC,oBAAoB,KAAK,SAAS;4BAC3C,CAAC,CAAC,EAAE,oBAAoB,EAAE,KAAK,CAAC,oBAAoB,EAAE;4BACtD,CAAC,CAAC,EAAE,CAAC,GACP,CACH,EAED,KAAC,QAAQ,IACP,KAAK,EAAE,GAAG,CAAC,KAAK,EAChB,MAAM,EAAC,QAAQ,EACf,YAAY,EAAE,CAAC,EACf,OAAO,EAAE,GAAG,CAAC,OAAO,EACpB,KAAK,EACH,8BACE,KAAC,UAAU,IACT,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,YAAY,CAAC,EACvC,MAAM,EAAC,cAAc,GACrB,EAIF,KAAC,UAAU,OACL,CAAC,KAAK,CAAC,gBAAgB,KAAK,SAAS;wCACvC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE;wCAC9C,CAAC,CAAC,EAAE,CAAC,KACH,CAAC,KAAK,CAAC,gBAAgB,KAAK,SAAS;wCACvC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,gBAAgB,EAAE;wCACzC,CAAC,CAAC,EAAE,CAAC,GACP,IACD,EAEL,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;4BAChB,2DAA2D;4BAC3D,uDAAuD;4BACvD,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,sBAAsB,CAAC;4BAC7D,OAAO,CACL,KAAC,UAAU,IACT,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,eAAe,EAC7D,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,CAAC,CACR,QAAQ;oCACN,CAAC,CAAC,gBAAgB,CAAC,qBAAqB;oCACxC,CAAC,CAAC,gBAAgB,CAAC,iBAAiB,CACvC,EACD,UAAU,EAAE,CAAC,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAC5C,OAAO,EAAE,GAAG,CAAC,OAAO,GACpB,CACH,CAAC;wBACJ,CAAC,YAEA,CAAC,KAAK,EAAE,EAAE;4BACT,MAAM,WAAW,GACf,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,CAC5B,aAAa,CAAC,KAAK,CAAC,CACrB,CAAC,CAAC,CAAC,CACF,eACE,KAAK,EAAE,SAAS,KAIZ,CAAC,WAAW,KAAK,IAAI;oCACvB,CAAC,CAAC,EAAE,SAAS,EAAE,qBAAqB,EAAE;oCACtC,CAAC,CAAC,EAAE,CAAC,iBACK,qBAAqB,iBACpB,KAAK,CAAC,MAAM,IAAI,MAAM,KAC/B,CAAC,WAAW,KAAK,IAAI;oCACvB,CAAC,CAAC;wCACE,cAAc,EACZ,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;4CAC/B,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;4CACvB,CAAC,CAAC,YAAY;qCACnB;oCACH,CAAC,CAAC,EAAE,CAAC,aAEN,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,CACtB,gBACE,IAAI,EAAE,0BAA0B,EAChC,UAAU,EAAC,SAAS,YAEnB,WAAW,GACN,CACT,CAAC,CAAC,CAAC,IAAI,EACP,KAAK,CAAC,GAAG,CAAC,CAAC,IAAgB,EAAE,EAAE,CAAC,CAC/B,wBACG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAC1B,UAAU,CAAC,IAAI,CAAC,CACjB,CAAC,CAAC,CAAC,CACF,KAAC,gBAAgB,IAAC,IAAI,EAAE,IAAI,GAAI,CACjC,IALO,IAAI,CAAC,GAAG,CAMZ,CACP,CAAC,IACE,CACP,CAAC;4BACJ,OAAO,CACL,6BAAiB,gBAAgB,YAC9B,WAAW,KAAK,SAAS;oCACxB,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC;oCACjC,CAAC,CAAC,WAAW,GACX,CACP,CAAC;wBACJ,CAAC,GACQ,EAEX,KAAC,KAAK,IAAC,GAAG,EAAE,GAAG,GAAI,EAClB,KAAK,CAAC,MAAM,IACR,CACR,GACa,GACN,CACb,CAAC;AACJ,CAAC"}
|
package/dist/default/index.d.ts
CHANGED
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
* a runtime `data-theme` flip actually repaints it.
|
|
40
40
|
*/
|
|
41
41
|
export { SearchPage, RAIL_CLASS, RAIL_STYLE_HREF, railScrollbarCss, } from "./SearchPage.js";
|
|
42
|
-
export type { SearchPageProps, SearchFiltersLayout } from "./SearchPage.js";
|
|
42
|
+
export type { SearchPageProps, SearchFiltersLayout, SearchRailFrom, } from "./SearchPage.js";
|
|
43
43
|
export { OtherCategoriesLine, OTHER_CATEGORIES_CLASS, OTHER_CATEGORIES_PHONE_ROWS, OTHER_CATEGORIES_SLOT_MIN_HEIGHT, OTHER_CATEGORIES_STYLE_HREF, otherCategoriesCss, otherCategoriesSlotHeight, } from "./OtherCategoriesLine.js";
|
|
44
44
|
export type { OtherCategoriesLineProps, OtherCategoryHrefResolver, OtherCategoryNamer, } from "./OtherCategoriesLine.js";
|
|
45
|
-
export { SearchResultsPane, RESULTS_MAX_WIDTH, RESULTS_COLUMNS_CLASS, RESULTS_COLUMNS_STYLE_HREF, resultsColumnsCss, } from "./SearchResultsPane.js";
|
|
45
|
+
export { SearchResultsPane, RESULTS_MAX_WIDTH, RESULTS_AUTO_FILL_COLUMNS, RESULTS_COLUMNS_CLASS, RESULTS_COLUMNS_STYLE_HREF, resultsColumnsCss, } from "./SearchResultsPane.js";
|
|
46
46
|
export type { ResultsColumns, SearchResultsPaneProps, SearchResultsRenderer, SearchResultsWrapper, } from "./SearchResultsPane.js";
|
|
47
47
|
export { FilterChips, CHIP_BAND_ORDER, CHIP_ROW_CAP, CHIP_ROW_CLASS, CHIP_ROW_MIN_HEIGHT, CHIP_ROW_STYLE_HREF, appliedChipTestId, appliedRowMinHeight, buildAppliedChips, capChipRow, categoryLeaf, chipRowCss, orderChipFilters, rangeChipText, rangeLabelSource, } from "./FilterChips.js";
|
|
48
48
|
export type { AppliedChip, AppliedChipTarget, ChipBand, ChipSpec, FilterChipsAppliedProps, FilterChipsCommonProps, FilterChipsMode, FilterChipsOpenerProps, FilterChipsProps, } from "./FilterChips.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AACzB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"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"}
|
package/dist/default/index.js
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
// ── surfaces ────────────────────────────────────────────────────────────────
|
|
42
42
|
export { SearchPage, RAIL_CLASS, RAIL_STYLE_HREF, railScrollbarCss, } from "./SearchPage.js";
|
|
43
43
|
export { OtherCategoriesLine, OTHER_CATEGORIES_CLASS, OTHER_CATEGORIES_PHONE_ROWS, OTHER_CATEGORIES_SLOT_MIN_HEIGHT, OTHER_CATEGORIES_STYLE_HREF, otherCategoriesCss, otherCategoriesSlotHeight, } from "./OtherCategoriesLine.js";
|
|
44
|
-
export { SearchResultsPane, RESULTS_MAX_WIDTH, RESULTS_COLUMNS_CLASS, RESULTS_COLUMNS_STYLE_HREF, resultsColumnsCss, } from "./SearchResultsPane.js";
|
|
44
|
+
export { SearchResultsPane, RESULTS_MAX_WIDTH, RESULTS_AUTO_FILL_COLUMNS, RESULTS_COLUMNS_CLASS, RESULTS_COLUMNS_STYLE_HREF, resultsColumnsCss, } from "./SearchResultsPane.js";
|
|
45
45
|
export { FilterChips, CHIP_BAND_ORDER, CHIP_ROW_CAP, CHIP_ROW_CLASS, CHIP_ROW_MIN_HEIGHT, CHIP_ROW_STYLE_HREF, appliedChipTestId, appliedRowMinHeight, buildAppliedChips, capChipRow, categoryLeaf, chipRowCss, orderChipFilters, rangeChipText, rangeLabelSource, } from "./FilterChips.js";
|
|
46
46
|
export { EmptyExits, RADIUS_WIDEN_FACTOR, parentCategory } from "./EmptyExits.js";
|
|
47
47
|
export { LocationSummaryLine } from "./LocationSummaryLine.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,+EAA+E;AAC/E,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,+EAA+E;AAC/E,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,2BAA2B,EAC3B,gCAAgC,EAChC,2BAA2B,EAC3B,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EACL,WAAW,EACX,eAAe,EACf,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAY1B,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGlF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,EAC1B,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAOhC,0EAA0E;AAC1E,uEAAuE;AACvE,8EAA8E;AAC9E,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAGtF,+EAA+E;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEhF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,+EAA+E;AAC/E,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAK3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
package/llms.txt
CHANGED
package/manifest.json
CHANGED
package/nav-manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stapel/search-react",
|
|
3
|
-
"version": "0.32.
|
|
3
|
+
"version": "0.32.8",
|
|
4
4
|
"description": "Headless React pair for stapel-search: a typed query client, TanStack Query hooks, and a URL-first state codec that makes a search shareable by construction (filters, ranges, geo, sort and the keyset cursor all live in the query string). Drill-down facets rendered with their remaining counts and with the server's own honesty flags — approximate, skipped, degraded — never swallowed; keyset pagination with the window refusal named; DSA Art. 26 `promoted` marking carried into every card slot and the P2B Art. 5 ranking disclosure exposed as data. Zero visual opinion in the main entry; an opt-in /default subpath ships the antd skin, and /router binds the codec to react-router's useSearchParams.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
"limit": "14.5 KB"
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
"name": "default — the antd skin (query box + a typeahead that offers CATEGORY destinations with their live counts, filters incl. ranges/geo/category slots + the phone chip row with its leading category chip and the location summary row + the rail's evidence-ranked disclosure groups, panel search and sticky count/clear footer, results incl. the view switch, the card photo GALLERY as a SkinCarousel strip, the empty state's derived exits, ranking, the dictionary control for a vocabulary facet, the popular-values block, the partition row in both its chip and segmented variants, the select-style dictionary FIELD the desktop rail opens, the from/to pickers a bounded integer axis draws and the rail's own scrollbar sheet) must stay out of the main bundle. Raised 24.5 → 25.5 KB for those four controls, then 25.5 → 26.25 KB for the chip row's APPLIED mode — one chip per applied value and per numeric bound, each removing that one constraint beside a rail that is already on screen (a storefront was carrying its own copy of it), then 26.25 → 27 KB for the \"search in other categories\" LINE — which is a net deletion on the page that mounts it, replacing a full-width block of one row per section that arrived after the results and pushed them, then 27 → 27.75 KB for the two frames the page now tells apart: the dictionary FIELD reaching `<SearchPage>` at all (per-layout default, field in the rail and inline in the sheet) and the footer bar being static in a column and sticky in a sheet, where it used to be pinned over the last two groups everywhere, then 27.75 → 28.5 KB for `categoryHref` on the other-categories line — a real `<a href>` per row with a modifier-click left to the browser, instead of a `<button>` with no address a person could open in a new tab, then 28.5 → 29.25 KB for the phone's dictionary SHEET — a trigger row over the shared `SkinPickerSheet` with a recommended band, an alphabetical rest paged fifty at a time and a draft committed in one write, which is the control the composer's vocabulary picker already was while the buyer got a wall of checkboxes, then 29.25 → 30.5 KB for the panel that draws all of it: groups and ranges as one ordered sequence with one «Apply» for the panel rather than one per row, the empty-group heading rule, `categoryFilter={false}` and the `resultsLead` slot for a page reached by walking the catalogue, `PopularValues columns=\\\"responsive\\\"` on a container query, `SortSelect` annotating a blocked option at every width, a loading arm that covers the whole pane (0.34 CLS on a live host), and the chip row reserving its own box (a further 0.045). Measured with dependencies held constant, this package's src at the commit before that work and then at it: 29.05 -> 30.16 KB — 1.11 KB, and every part of it is a shift or a mislabelled control a host was living with, then 30.5 -> 31 KB for `<SearchResultsPane columns>` and its pass-through on `<SearchPage resultsColumns>`: a fixed track count or a per-breakpoint map, emitted as a hoisted container-query sheet (the results block is the window minus a 280px rail, so a media query would answer about a width the cards never have). Measured with dependencies held constant, this package's src before and after: 30.40 -> 30.65 KB — 250 B, and what it replaces is a host's `!important` rule against a grid declaration it could not read back",
|
|
60
|
+
"name": "default — the antd skin (query box + a typeahead that offers CATEGORY destinations with their live counts, filters incl. ranges/geo/category slots + the phone chip row with its leading category chip and the location summary row + the rail's evidence-ranked disclosure groups, panel search and sticky count/clear footer, results incl. the view switch, the card photo GALLERY as a SkinCarousel strip, the empty state's derived exits, ranking, the dictionary control for a vocabulary facet, the popular-values block, the partition row in both its chip and segmented variants, the select-style dictionary FIELD the desktop rail opens, the from/to pickers a bounded integer axis draws and the rail's own scrollbar sheet) must stay out of the main bundle. Raised 24.5 → 25.5 KB for those four controls, then 25.5 → 26.25 KB for the chip row's APPLIED mode — one chip per applied value and per numeric bound, each removing that one constraint beside a rail that is already on screen (a storefront was carrying its own copy of it), then 26.25 → 27 KB for the \"search in other categories\" LINE — which is a net deletion on the page that mounts it, replacing a full-width block of one row per section that arrived after the results and pushed them, then 27 → 27.75 KB for the two frames the page now tells apart: the dictionary FIELD reaching `<SearchPage>` at all (per-layout default, field in the rail and inline in the sheet) and the footer bar being static in a column and sticky in a sheet, where it used to be pinned over the last two groups everywhere, then 27.75 → 28.5 KB for `categoryHref` on the other-categories line — a real `<a href>` per row with a modifier-click left to the browser, instead of a `<button>` with no address a person could open in a new tab, then 28.5 → 29.25 KB for the phone's dictionary SHEET — a trigger row over the shared `SkinPickerSheet` with a recommended band, an alphabetical rest paged fifty at a time and a draft committed in one write, which is the control the composer's vocabulary picker already was while the buyer got a wall of checkboxes, then 29.25 → 30.5 KB for the panel that draws all of it: groups and ranges as one ordered sequence with one «Apply» for the panel rather than one per row, the empty-group heading rule, `categoryFilter={false}` and the `resultsLead` slot for a page reached by walking the catalogue, `PopularValues columns=\\\"responsive\\\"` on a container query, `SortSelect` annotating a blocked option at every width, a loading arm that covers the whole pane (0.34 CLS on a live host), and the chip row reserving its own box (a further 0.045). Measured with dependencies held constant, this package's src at the commit before that work and then at it: 29.05 -> 30.16 KB — 1.11 KB, and every part of it is a shift or a mislabelled control a host was living with, then 30.5 -> 31 KB for `<SearchResultsPane columns>` and its pass-through on `<SearchPage resultsColumns>`: a fixed track count or a per-breakpoint map, emitted as a hoisted container-query sheet (the results block is the window minus a 280px rail, so a media query would answer about a width the cards never have). Measured with dependencies held constant, this package's src before and after: 30.40 -> 30.65 KB — 250 B, and what it replaces is a host's `!important` rule against a grid declaration it could not read back, then 31 -> 31.25 KB for the segmented partition being antd's `Segmented` rather than a row of buttons wearing a border: the walker read `data-variant=\"segmented\"` with `role=\"radiogroup\"` and found `.ant-segmented` zero times and `input[type=radio]` zero times (D304), so the cells are the design system's now — real radios under one name, the browser's own arrow keys and Tab stop. Measured with dependencies held constant, this package's src before and after: 30.95 -> 31.05 KB — 100 B, against ~30 lines of hand-rolled joined-row geometry deleted",
|
|
61
61
|
"path": "dist/default/index.js",
|
|
62
|
-
"limit": "31 KB"
|
|
62
|
+
"limit": "31.25 KB"
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
"name": "router — the react-router binding is opt-in; the main entry must never pull a router",
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
"size-limit": "^11.2.0",
|
|
116
116
|
"typescript": "^5.8.3",
|
|
117
117
|
"vitest": "^3.2.4",
|
|
118
|
-
"@stapel/attributes-react": "^0.16.
|
|
118
|
+
"@stapel/attributes-react": "^0.16.5",
|
|
119
119
|
"@stapel/core": "^0.25.4",
|
|
120
120
|
"@stapel/image": "^0.4.2",
|
|
121
121
|
"@stapel/showcase": "^0.3.0",
|
|
@@ -25,6 +25,28 @@
|
|
|
25
25
|
* with roving tabindex is the pattern for "one of these": Tab reaches the row
|
|
26
26
|
* once and lands on the chosen chip, the arrow keys move along it, and the
|
|
27
27
|
* group's own name says what is being chosen.
|
|
28
|
+
*
|
|
29
|
+
* ── The two variants are two CONTROLS, and each one is real ───────────────
|
|
30
|
+
*
|
|
31
|
+
* `chips` is this file's own row of `role="radio"` buttons — pills that wrap,
|
|
32
|
+
* the phone's shape.
|
|
33
|
+
*
|
|
34
|
+
* `segmented` is antd's `Segmented`, and it used to be this same row with a
|
|
35
|
+
* shared border drawn round it. That was a claim nothing backed: the walker
|
|
36
|
+
* read `data-variant="segmented"` with `role="radiogroup"` and found
|
|
37
|
+
* `.ant-segmented` zero times, `input[type=radio]` zero times, and plain
|
|
38
|
+
* `ant-btn` inside — on both axes of two categories (D304). A row that names
|
|
39
|
+
* a control it does not render sends the next reader looking for a bug in the
|
|
40
|
+
* wrong place, and hand-rolling the joined look was ~30 lines re-deciding
|
|
41
|
+
* geometry the design system already owns.
|
|
42
|
+
*
|
|
43
|
+
* So the segmented arm IS the design system's control now, and its radiogroup
|
|
44
|
+
* is the browser's rather than ours: real `input[type=radio]` sharing one
|
|
45
|
+
* `name`, so the selected state is the radio's own `checked` (`aria-checked`
|
|
46
|
+
* is how a BUTTON fakes what a radio has), the arrow keys are the control's,
|
|
47
|
+
* and one Tab stop is the platform's doing. The per-cell test ids stay where
|
|
48
|
+
* they were, plus `data-checked`, so a probe that reads a snapshot still has
|
|
49
|
+
* the chosen cell without asking the accessibility tree.
|
|
28
50
|
*/
|
|
29
51
|
import { useRef } from "react";
|
|
30
52
|
import type {
|
|
@@ -33,9 +55,9 @@ import type {
|
|
|
33
55
|
ReactElement,
|
|
34
56
|
ReactNode,
|
|
35
57
|
} from "react";
|
|
36
|
-
import { Button } from "antd";
|
|
58
|
+
import { Button, Segmented } from "antd";
|
|
37
59
|
import { useT } from "@stapel/core";
|
|
38
|
-
import {
|
|
60
|
+
import { radii, spacing } from "@stapel/tokens";
|
|
39
61
|
import { SEARCH_I18N_KEYS } from "../i18n/keys.js";
|
|
40
62
|
|
|
41
63
|
/** One child of a partitioned category. `path` is the slash-joined id path
|
|
@@ -61,19 +83,26 @@ export interface PartitionChipsProps {
|
|
|
61
83
|
/**
|
|
62
84
|
* Which shape the row takes. `"chips"` (the default) is the phone's: a
|
|
63
85
|
* wrapping row of rounded pills above the feed. `"segmented"` is the
|
|
64
|
-
* desktop RAIL's — one joined control under the axis's
|
|
65
|
-
* how the reference classified draws the same choice (a
|
|
66
|
-
* all, used, new) and what a 280px column has room for.
|
|
86
|
+
* desktop RAIL's — antd's `Segmented`, one joined control under the axis's
|
|
87
|
+
* own label, which is how the reference classified draws the same choice (a
|
|
88
|
+
* car-type row: all, used, new) and what a 280px column has room for.
|
|
67
89
|
*
|
|
68
|
-
* The SEMANTICS do not vary with it
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* accessible half of this control for the visible half.
|
|
90
|
+
* The SEMANTICS do not vary with it: both are a `radiogroup` naming itself,
|
|
91
|
+
* with one Tab stop and the arrow keys moving the choice. What varies is
|
|
92
|
+
* who provides them — this file's `role="radio"` buttons in `chips`, the
|
|
93
|
+
* browser's own `input[type=radio]` in `segmented`.
|
|
73
94
|
*/
|
|
74
95
|
readonly variant?: "chips" | "segmented";
|
|
75
96
|
}
|
|
76
97
|
|
|
98
|
+
/**
|
|
99
|
+
* The `value` of the parent cell inside the segmented control. `null` is this
|
|
100
|
+
* component's word for "the parent, unnarrowed" and a radio's value is a
|
|
101
|
+
* string, so the sentinel exists only between here and antd — it never
|
|
102
|
+
* reaches {@link PartitionChipsProps.onChange}, which still reports `null`.
|
|
103
|
+
*/
|
|
104
|
+
const ALL = "__all__";
|
|
105
|
+
|
|
77
106
|
const CHIP: CSSProperties = { borderRadius: radii.full };
|
|
78
107
|
|
|
79
108
|
const ROW: CSSProperties = {
|
|
@@ -82,33 +111,6 @@ const ROW: CSSProperties = {
|
|
|
82
111
|
gap: spacing[2],
|
|
83
112
|
};
|
|
84
113
|
|
|
85
|
-
/**
|
|
86
|
-
* The segmented row: one joined control, no gaps, the group's own outline.
|
|
87
|
-
*
|
|
88
|
-
* `gap: 0` plus a shared border is what makes three buttons read as one
|
|
89
|
-
* control — the thing a rail needs, because a wrapping pill row in a 280px
|
|
90
|
-
* column is two ragged lines. `overflow: hidden` clips the cells' own corners
|
|
91
|
-
* to the group's radius so the ends are round and the joins are square.
|
|
92
|
-
*/
|
|
93
|
-
const SEGMENTED_ROW: CSSProperties = {
|
|
94
|
-
display: "flex",
|
|
95
|
-
gap: 0,
|
|
96
|
-
inlineSize: "100%",
|
|
97
|
-
border: `1px solid ${cssVar("border")}`,
|
|
98
|
-
borderRadius: cssVar("radius-md"),
|
|
99
|
-
overflow: "hidden",
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
/** One cell of the segmented row: an equal share of the width, square joins,
|
|
103
|
-
* no border of its own — the group draws the outline. */
|
|
104
|
-
const SEGMENTED_CELL: CSSProperties = {
|
|
105
|
-
flex: "1 1 0",
|
|
106
|
-
minInlineSize: 0,
|
|
107
|
-
borderRadius: 0,
|
|
108
|
-
borderInline: "none",
|
|
109
|
-
borderBlock: "none",
|
|
110
|
-
};
|
|
111
|
-
|
|
112
114
|
/** The row's cells, as `[value, label]` — the parent first, then the
|
|
113
115
|
* children in catalogue order. */
|
|
114
116
|
function cells(
|
|
@@ -163,30 +165,68 @@ export function PartitionChips(props: PartitionChipsProps): ReactElement {
|
|
|
163
165
|
const active = options.findIndex(([value]) => value === props.value);
|
|
164
166
|
const stop = active >= 0 ? active : 0;
|
|
165
167
|
|
|
166
|
-
const
|
|
168
|
+
const name = props.label ?? t(SEARCH_I18N_KEYS.partitionLabel);
|
|
169
|
+
|
|
170
|
+
if (props.variant === "segmented") {
|
|
171
|
+
// antd's own control: `.ant-segmented`, one `input[type=radio]` per cell
|
|
172
|
+
// under a shared `name`, the selected cell's `checked`, and the arrow keys
|
|
173
|
+
// — the radiogroup this variant used to only claim to be. `role` and
|
|
174
|
+
// `aria-label` reach the root because the component spreads what it is
|
|
175
|
+
// given over its own defaults (which are `radiogroup` and the string
|
|
176
|
+
// "segmented control").
|
|
177
|
+
return (
|
|
178
|
+
<Segmented
|
|
179
|
+
block
|
|
180
|
+
size="small"
|
|
181
|
+
role="radiogroup"
|
|
182
|
+
aria-label={name}
|
|
183
|
+
data-variant="segmented"
|
|
184
|
+
data-testid="partition-chips"
|
|
185
|
+
value={props.value ?? ALL}
|
|
186
|
+
options={options.map(([value, label]) => ({
|
|
187
|
+
value: value ?? ALL,
|
|
188
|
+
label: (
|
|
189
|
+
// The cell's test id and its chosen state, on the one node inside
|
|
190
|
+
// a cell this component owns — antd names the cells itself, and a
|
|
191
|
+
// label a radio is bound to is what a click has to land on.
|
|
192
|
+
<span
|
|
193
|
+
data-testid={`partition-chip-${value ?? "all"}`}
|
|
194
|
+
data-checked={value === props.value ? "true" : "false"}
|
|
195
|
+
>
|
|
196
|
+
{label}
|
|
197
|
+
</span>
|
|
198
|
+
),
|
|
199
|
+
}))}
|
|
200
|
+
onChange={(next) => {
|
|
201
|
+
props.onChange(next === ALL ? null : String(next));
|
|
202
|
+
}}
|
|
203
|
+
/>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
167
207
|
return (
|
|
168
208
|
<div
|
|
169
|
-
style={
|
|
170
|
-
data-variant=
|
|
209
|
+
style={ROW}
|
|
210
|
+
data-variant="chips"
|
|
171
211
|
ref={row}
|
|
172
212
|
role="radiogroup"
|
|
173
|
-
aria-label={
|
|
213
|
+
aria-label={name}
|
|
174
214
|
data-testid="partition-chips"
|
|
175
215
|
>
|
|
176
216
|
{options.map(([value, label], index) => {
|
|
177
217
|
const selected = value === props.value;
|
|
178
218
|
return (
|
|
179
219
|
<Button
|
|
180
|
-
key={value ??
|
|
220
|
+
key={value ?? ALL}
|
|
181
221
|
size="small"
|
|
182
|
-
|
|
222
|
+
shape="round"
|
|
183
223
|
type={selected ? "primary" : "default"}
|
|
184
224
|
role="radio"
|
|
185
225
|
aria-checked={selected}
|
|
186
226
|
// Roving tabindex: the row is ONE Tab stop and it lands on the
|
|
187
227
|
// chosen chip, not on the first of eight.
|
|
188
228
|
tabIndex={index === stop ? 0 : -1}
|
|
189
|
-
style={
|
|
229
|
+
style={CHIP}
|
|
190
230
|
data-testid={`partition-chip-${value ?? "all"}`}
|
|
191
231
|
data-analytics="none"
|
|
192
232
|
data-analytics-reason="choosing a section is a read, not a flow step"
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
* nothing in it, and a layout that reflowed underneath a person mid-load would
|
|
62
62
|
* be worse than the hole.
|
|
63
63
|
*/
|
|
64
|
-
import { useState } from "react";
|
|
64
|
+
import { useState, useSyncExternalStore } from "react";
|
|
65
65
|
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
66
66
|
import { Button, Flex } from "antd";
|
|
67
67
|
import { SkinDialog, SkinTheme, useDialogSurface } from "@stapel/tokens-antd/skin";
|
|
@@ -106,6 +106,84 @@ import type { ThemeModeProp } from "./types.js";
|
|
|
106
106
|
/** Where the filters live: beside the results, or behind a button in a sheet. */
|
|
107
107
|
export type SearchFiltersLayout = "column" | "sheet";
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* WHERE the filter rail earns its 280px, when the token `tablet` edge is the
|
|
111
|
+
* wrong place to draw it.
|
|
112
|
+
*
|
|
113
|
+
* The default is `useDialogSurface()`, i.e. the same `tablet` breakpoint the
|
|
114
|
+
* bottom sheet is decided by — one rule, one source, and no third opinion
|
|
115
|
+
* about where a phone ends. That is right for a dialog and often wrong for
|
|
116
|
+
* THIS layout: at 768px the rail takes 280 of the window and leaves the
|
|
117
|
+
* results a 470px column, one card wide, which is worse than the sheet the
|
|
118
|
+
* page just stopped drawing. A storefront whose cards want two columns beside
|
|
119
|
+
* the rail says `railFrom={1024}` and gets the sheet below it.
|
|
120
|
+
*
|
|
121
|
+
* A width in CSS pixels, compared against the VIEWPORT — deliberately, and for
|
|
122
|
+
* the same reason `useDialogSurface` may: below the threshold the filters are
|
|
123
|
+
* a bottom sheet anchored to the viewport's edges, and there is no element
|
|
124
|
+
* whose width could be the right input to that decision. Above it the rail is
|
|
125
|
+
* an ordinary column and everything inside it measures its own box again.
|
|
126
|
+
*/
|
|
127
|
+
export type SearchRailFrom = number;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Is the viewport at least this wide right now?
|
|
131
|
+
*
|
|
132
|
+
* `useSyncExternalStore` over one live `matchMedia` handle, the shape
|
|
133
|
+
* `useDialogSurface` uses, so the FIRST client render already has the answer:
|
|
134
|
+
* an effect-based hook would paint the sheet arm on a desktop for one frame
|
|
135
|
+
* and swap it for the rail. `null` when there is nothing to ask — no
|
|
136
|
+
* threshold given, or no DOM (SSR) — and the caller falls back to the shared
|
|
137
|
+
* dialog-surface rule.
|
|
138
|
+
*/
|
|
139
|
+
function useWiderThan(px: number | undefined): boolean | null {
|
|
140
|
+
const query = px === undefined ? null : `(min-width: ${String(px)}px)`;
|
|
141
|
+
return useSyncExternalStore(
|
|
142
|
+
(onChange: () => void) => {
|
|
143
|
+
if (query === null) return () => undefined;
|
|
144
|
+
const list = matchMediaFor(query);
|
|
145
|
+
if (list === null) return () => undefined;
|
|
146
|
+
list.addEventListener("change", onChange);
|
|
147
|
+
return () => {
|
|
148
|
+
list.removeEventListener("change", onChange);
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
() => {
|
|
152
|
+
if (query === null) return null;
|
|
153
|
+
const list = matchMediaFor(query);
|
|
154
|
+
return list === null ? null : list.matches;
|
|
155
|
+
},
|
|
156
|
+
() => null
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The `MediaQueryList` for one query, made once per query string.
|
|
162
|
+
*
|
|
163
|
+
* `useSyncExternalStore` calls its snapshot on every render, so building a
|
|
164
|
+
* fresh live query object each time would ask the platform to parse the same
|
|
165
|
+
* media text on every pass — the cost `useDialogSurface`'s own cache exists to
|
|
166
|
+
* avoid. Keyed on the `matchMedia` function too, so a test that installs its
|
|
167
|
+
* own is never answered by the previous one's handle.
|
|
168
|
+
*/
|
|
169
|
+
const mediaCache = new Map<string, MediaQueryList>();
|
|
170
|
+
let cachedMatchMedia: typeof window.matchMedia | null = null;
|
|
171
|
+
|
|
172
|
+
function matchMediaFor(query: string): MediaQueryList | null {
|
|
173
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
if (cachedMatchMedia !== window.matchMedia) {
|
|
177
|
+
cachedMatchMedia = window.matchMedia;
|
|
178
|
+
mediaCache.clear();
|
|
179
|
+
}
|
|
180
|
+
const cached = mediaCache.get(query);
|
|
181
|
+
if (cached !== undefined) return cached;
|
|
182
|
+
const made = window.matchMedia(query);
|
|
183
|
+
mediaCache.set(query, made);
|
|
184
|
+
return made;
|
|
185
|
+
}
|
|
186
|
+
|
|
109
187
|
/**
|
|
110
188
|
* The desktop filter rail's width.
|
|
111
189
|
*
|
|
@@ -419,9 +497,29 @@ export interface SearchPageProps extends ThemeModeProp, ParseSearchStateOptions
|
|
|
419
497
|
* `"banner"`). Handed straight to `<SearchResultsPane>`. */
|
|
420
498
|
readonly degradationNotice?: DegradationNoticeVariant;
|
|
421
499
|
/**
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
500
|
+
* WHERE the filter rail takes over from the sheet, in CSS pixels.
|
|
501
|
+
*
|
|
502
|
+
* Default: the token `tablet` edge, because that is what `useDialogSurface`
|
|
503
|
+
* decides and one rule beats two. At 768px, though, the 280px rail leaves
|
|
504
|
+
* the results a 470px column — one card wide, and worse than the sheet it
|
|
505
|
+
* replaced. `railFrom={1024}` moves the changeover to where this page's
|
|
506
|
+
* cards actually fit beside the rail; below it the filters are the sheet.
|
|
507
|
+
*
|
|
508
|
+
* Read against the viewport (see {@link SearchRailFrom}), live: rotating a
|
|
509
|
+
* tablet across the threshold swaps the surface without a reload.
|
|
510
|
+
* {@link filtersLayout} still wins over it, being the pinned answer.
|
|
511
|
+
*/
|
|
512
|
+
readonly railFrom?: SearchRailFrom;
|
|
513
|
+
/**
|
|
514
|
+
* PIN the filter surface, instead of deciding it from the viewport at all.
|
|
515
|
+
*
|
|
516
|
+
* A real prop, not a test seam: a page rendered inside a phone-width
|
|
517
|
+
* container that is not the viewport (a preview frame, an embedded panel, a
|
|
518
|
+
* split view) has a viewport that answers the wrong question, and so does a
|
|
519
|
+
* surface that is a column by product decision at every width. Prefer
|
|
520
|
+
* {@link railFrom} when the answer is still "it depends on the width" and
|
|
521
|
+
* only the threshold is wrong — a pinned `"column"` on a phone puts a 280px
|
|
522
|
+
* rail beside a 110px result column.
|
|
425
523
|
*/
|
|
426
524
|
readonly filtersLayout?: SearchFiltersLayout;
|
|
427
525
|
/**
|
|
@@ -539,6 +637,7 @@ interface SearchPageBodyProps {
|
|
|
539
637
|
readonly categoryNamesPending?: boolean;
|
|
540
638
|
readonly resultsHeading?: ReactNode;
|
|
541
639
|
readonly degradationNotice?: DegradationNoticeVariant;
|
|
640
|
+
readonly railFrom?: SearchRailFrom;
|
|
542
641
|
readonly filtersLayout?: SearchFiltersLayout;
|
|
543
642
|
readonly defaultFiltersOpen?: boolean;
|
|
544
643
|
readonly pageSize?: boolean;
|
|
@@ -567,8 +666,16 @@ function SearchPageBody(props: SearchPageBodyProps): ReactElement {
|
|
|
567
666
|
});
|
|
568
667
|
const applied = useAppliedCount();
|
|
569
668
|
const surface = useDialogSurface();
|
|
669
|
+
const wideEnoughForRail = useWiderThan(props.railFrom);
|
|
570
670
|
const layout: SearchFiltersLayout =
|
|
571
|
-
props.filtersLayout ??
|
|
671
|
+
props.filtersLayout ??
|
|
672
|
+
(wideEnoughForRail !== null
|
|
673
|
+
? wideEnoughForRail
|
|
674
|
+
? "column"
|
|
675
|
+
: "sheet"
|
|
676
|
+
: surface === "sheet"
|
|
677
|
+
? "sheet"
|
|
678
|
+
: "column");
|
|
572
679
|
const [sheetOpen, setSheetOpen] = useState(props.defaultFiltersOpen === true);
|
|
573
680
|
|
|
574
681
|
// How the results are ARRANGED. Component state, not URL state: it changes
|
|
@@ -941,6 +1048,7 @@ export function SearchPage(props: SearchPageProps): ReactElement {
|
|
|
941
1048
|
categoryNamesPending,
|
|
942
1049
|
resultsHeading,
|
|
943
1050
|
degradationNotice,
|
|
1051
|
+
railFrom,
|
|
944
1052
|
filtersLayout,
|
|
945
1053
|
defaultFiltersOpen,
|
|
946
1054
|
pageSize,
|
|
@@ -992,6 +1100,7 @@ export function SearchPage(props: SearchPageProps): ReactElement {
|
|
|
992
1100
|
{...(categoryNamesPending !== undefined ? { categoryNamesPending } : {})}
|
|
993
1101
|
{...(resultsHeading !== undefined ? { resultsHeading } : {})}
|
|
994
1102
|
{...(degradationNotice !== undefined ? { degradationNotice } : {})}
|
|
1103
|
+
{...(railFrom !== undefined ? { railFrom } : {})}
|
|
995
1104
|
{...(filtersLayout !== undefined ? { filtersLayout } : {})}
|
|
996
1105
|
{...(defaultFiltersOpen !== undefined ? { defaultFiltersOpen } : {})}
|
|
997
1106
|
{...(pageSize !== undefined ? { pageSize } : {})}
|