@bicharts/chart-host 0.6.83 → 0.6.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  formatSourceDateFor,
6
6
  isExcelDateFormat,
7
7
  normaliseAggregation
8
- } from "./chunk-4KCSAHL5.mjs";
8
+ } from "./chunk-GG4U66E4.mjs";
9
9
  import {
10
10
  ANNOTATION_CLASS,
11
11
  ANNOTATION_LAYER_CLASS,
@@ -111,31 +111,68 @@ import {
111
111
  toSourceRows,
112
112
  unpinScrolledAxis,
113
113
  valuePlacementFlag
114
- } from "./chunk-CJNONH6V.mjs";
114
+ } from "./chunk-2HKO6GEK.mjs";
115
+ import {
116
+ LASSO_AXES_SLOT,
117
+ LASSO_COUNT_CLASS,
118
+ LASSO_DEFAULT_ACTIONS,
119
+ LASSO_DRAG_PX,
120
+ LASSO_EVENT,
121
+ LASSO_KNOB_KEY,
122
+ LASSO_MAX_VERTICES,
123
+ LASSO_MODE_ATTR,
124
+ LASSO_NOTE_CLASS,
125
+ LASSO_OUTLINE_CLASS,
126
+ LASSO_PLOT_CLASS,
127
+ LASSO_RESTORE_MAX_SHAPES,
128
+ LASSO_RESTORE_MAX_VERTICES,
129
+ LASSO_ROW_CAP,
130
+ LASSO_SAMPLE_PX,
131
+ LASSO_SURFACE_CLASS,
132
+ clearLasso,
133
+ installLasso,
134
+ lassoActions,
135
+ lassoRowCap,
136
+ lassoVerdict,
137
+ pointInShape,
138
+ registerLassoAction
139
+ } from "./chunk-QIRLWJBI.mjs";
115
140
  import {
116
141
  _3,
117
142
  l,
118
143
  o
119
- } from "./chunk-2XWE6YFO.mjs";
144
+ } from "./chunk-2ZUUIZWL.mjs";
120
145
  import {
121
146
  MIN_HIT_BAND_PX,
122
- SELECTION_GLYPH_CLASS,
123
147
  censusHitBands,
148
+ ensureCrossfilterHitTargets,
149
+ hitBandFlag
150
+ } from "./chunk-7HKVV5T5.mjs";
151
+ import {
152
+ CONTAINER_SLOT_PRESS_AT,
153
+ DRAG_NOT_CLICK_PX,
154
+ ROW_SET_MAX,
155
+ SELECTION_GLYPH_CLASS,
156
+ clearPress,
124
157
  clearSelectionGlyphs,
158
+ clickWasDrag,
125
159
  collectD3GlyphCenters,
126
160
  createMarkResolver,
127
- ensureCrossfilterHitTargets,
128
- hitBandFlag,
161
+ dispatchRowSet,
162
+ gestureWasDrag,
129
163
  isInsideControl,
130
164
  markKeyOf,
131
165
  nextClickedMarks,
132
166
  nextSelection,
133
167
  paintSelectionGlyphs,
134
168
  planSelectionPaint,
169
+ pressOf,
135
170
  rowIdxsFromMark,
136
171
  sameRowSet,
137
- selectionRuleOf
138
- } from "./chunk-MGAO2DR7.mjs";
172
+ selectionRuleOf,
173
+ trackPress,
174
+ validRowSet
175
+ } from "./chunk-IURROJT7.mjs";
139
176
  import "./chunk-A2GMXZP7.mjs";
140
177
  import {
141
178
  ACTIVE_TICK_CLASS,
@@ -187,7 +224,7 @@ import {
187
224
  chartOwnsTimeline,
188
225
  periodTickSuppressesFeedback,
189
226
  withoutViewOnlyKeys
190
- } from "./chunk-7JWL6LYE.mjs";
227
+ } from "./chunk-MR6TL7QZ.mjs";
191
228
  import "./chunk-GHODWOAL.mjs";
192
229
 
193
230
  // src/optionsVocabulary.ts
@@ -1132,7 +1169,21 @@ function qualifyGroupHeadingFor(row, state) {
1132
1169
  return null;
1133
1170
  }
1134
1171
  function newQualifyRefusalGroupState() {
1135
- return { poorFit: false, cannotDraw: false };
1172
+ return { poorFit: false, tooSmall: false, cannotDraw: false };
1173
+ }
1174
+ var QUALIFY_TILE_REFUSAL_CODES = Object.freeze([
1175
+ "TILE_TOO_NARROW",
1176
+ "TILE_TOO_SHORT",
1177
+ "TILE_NOT_SQUARE",
1178
+ "TILE_NOT_TALL",
1179
+ "TILE_TOO_SMALL",
1180
+ "EMBED_NOTHING_FITS_TILE",
1181
+ "EMBED_BEESWARM_TILE_TOO_SMALL"
1182
+ ]);
1183
+ var QUALIFY_TOO_SMALL_HEADING = "Needs a bigger tile";
1184
+ function refusalIsTileBound(row) {
1185
+ const code = row?.reasonCode;
1186
+ return typeof code === "string" && QUALIFY_TILE_REFUSAL_CODES.includes(code);
1136
1187
  }
1137
1188
  function refusalIsSelectable(row) {
1138
1189
  return !!row && row.isVeto !== true;
@@ -1140,9 +1191,23 @@ function refusalIsSelectable(row) {
1140
1191
  function orderRefusalsForDisplay(rows) {
1141
1192
  if (!Array.isArray(rows)) return [];
1142
1193
  const named = rows.filter((r2) => !!r2 && typeof r2.name === "string" && r2.name.trim() !== "");
1143
- return [...named.filter(refusalIsSelectable), ...named.filter((r2) => !refusalIsSelectable(r2))];
1194
+ const tile = named.filter(refusalIsTileBound);
1195
+ const rest = named.filter((r2) => !refusalIsTileBound(r2));
1196
+ return [
1197
+ ...rest.filter(refusalIsSelectable),
1198
+ ...tile.filter(refusalIsSelectable),
1199
+ ...tile.filter((r2) => !refusalIsSelectable(r2)),
1200
+ ...rest.filter((r2) => !refusalIsSelectable(r2))
1201
+ ];
1144
1202
  }
1145
1203
  function qualifyRefusalHeadingFor(row, state) {
1204
+ if (refusalIsTileBound(row)) {
1205
+ if (!state.tooSmall) {
1206
+ state.tooSmall = true;
1207
+ return "tooSmall";
1208
+ }
1209
+ return null;
1210
+ }
1146
1211
  if (refusalIsSelectable(row)) {
1147
1212
  if (!state.poorFit) {
1148
1213
  state.poorFit = true;
@@ -2325,6 +2390,7 @@ export {
2325
2390
  CONTAINER_SLOT_ANIM_STOP,
2326
2391
  CONTAINER_SLOT_CLICKED_MARKS,
2327
2392
  CONTAINER_SLOT_INITIAL_XF_MARK,
2393
+ CONTAINER_SLOT_PRESS_AT,
2328
2394
  CONTAINER_SLOT_UI_STATE,
2329
2395
  CONTAINER_SLOT_XF_CLEAR,
2330
2396
  CONTROL_CLASS,
@@ -2334,6 +2400,7 @@ export {
2334
2400
  DEFAULT_MODEL_SUFFIX,
2335
2401
  DIM_OPACITY_DEFAULT,
2336
2402
  DIM_OPACITY_VAR,
2403
+ DRAG_NOT_CLICK_PX,
2337
2404
  DUPLICATE_GENERATE_WINDOW_MS,
2338
2405
  FILTER_MIN_HEIGHT_PX,
2339
2406
  FILTER_MIN_TERM_CHARS,
@@ -2356,6 +2423,22 @@ export {
2356
2423
  LABEL_CONTRAST_CAP,
2357
2424
  LABEL_CONTRAST_DONE_ATTR,
2358
2425
  LABEL_PILL_CLASS,
2426
+ LASSO_AXES_SLOT,
2427
+ LASSO_COUNT_CLASS,
2428
+ LASSO_DEFAULT_ACTIONS,
2429
+ LASSO_DRAG_PX,
2430
+ LASSO_EVENT,
2431
+ LASSO_KNOB_KEY,
2432
+ LASSO_MAX_VERTICES,
2433
+ LASSO_MODE_ATTR,
2434
+ LASSO_NOTE_CLASS,
2435
+ LASSO_OUTLINE_CLASS,
2436
+ LASSO_PLOT_CLASS,
2437
+ LASSO_RESTORE_MAX_SHAPES,
2438
+ LASSO_RESTORE_MAX_VERTICES,
2439
+ LASSO_ROW_CAP,
2440
+ LASSO_SAMPLE_PX,
2441
+ LASSO_SURFACE_CLASS,
2359
2442
  LEGEND_MARK_CLASS,
2360
2443
  LEGIBLE_LIGHTNESS,
2361
2444
  LIFT_SELECTED_CLASS,
@@ -2391,8 +2474,11 @@ export {
2391
2474
  PRODUCT_FEEDBACK_MAX_CHARS,
2392
2475
  PRODUCT_FEEDBACK_MIN_CHARS,
2393
2476
  QUALIFY_REFUSAL_UNSPECIFIED,
2477
+ QUALIFY_TILE_REFUSAL_CODES,
2478
+ QUALIFY_TOO_SMALL_HEADING,
2394
2479
  RECOVERY_UNREACHABLE_MESSAGE,
2395
2480
  ROW_IDX_ATTR,
2481
+ ROW_SET_MAX,
2396
2482
  SAME_SHADE_DELTA_E,
2397
2483
  SCROLL_SLACK_PX,
2398
2484
  SEASONAL_MARKERS_DEFAULT,
@@ -2441,7 +2527,10 @@ export {
2441
2527
  chartSvgOf,
2442
2528
  chooserFitsViewport,
2443
2529
  clearGeoCache,
2530
+ clearLasso,
2531
+ clearPress,
2444
2532
  clearSelectionGlyphs,
2533
+ clickWasDrag,
2445
2534
  clippedTextFlag,
2446
2535
  codeReadsDatesInLocalTime,
2447
2536
  codeReadsOption,
@@ -2464,6 +2553,7 @@ export {
2464
2553
  decidePendingRecovery,
2465
2554
  defaultModelFirst,
2466
2555
  deltaEHex,
2556
+ dispatchRowSet,
2467
2557
  encodePendingGenerate,
2468
2558
  ensureCrossfilterHitTargets,
2469
2559
  explainRenderFailure,
@@ -2478,12 +2568,14 @@ export {
2478
2568
  generationCancelledMessage,
2479
2569
  geoAssetFor,
2480
2570
  geoFromCache,
2571
+ gestureWasDrag,
2481
2572
  glyphSampleGrid,
2482
2573
  hasRefusalsToShow,
2483
2574
  hitBandFlag,
2484
2575
  htmlNaturalSize,
2485
2576
  htmlToSvgDataUrl,
2486
2577
  inlineFilterGate,
2578
+ installLasso,
2487
2579
  invalidSentinelReason,
2488
2580
  isBlankRender,
2489
2581
  isBlindMarker,
@@ -2498,6 +2590,9 @@ export {
2498
2590
  isPickableModelCode,
2499
2591
  isPillBackdropAlpha,
2500
2592
  labelBand,
2593
+ lassoActions,
2594
+ lassoRowCap,
2595
+ lassoVerdict,
2501
2596
  latePickupAction,
2502
2597
  latePickupKeepsMarker,
2503
2598
  launchFavorStyle,
@@ -2536,7 +2631,9 @@ export {
2536
2631
  planFrameGrow,
2537
2632
  planSelectionPaint,
2538
2633
  planTrivialChart,
2634
+ pointInShape,
2539
2635
  pollGiveUpKeepsMarker,
2636
+ pressOf,
2540
2637
  productFeedbackSendable,
2541
2638
  qualifyAuto,
2542
2639
  qualifyCancel,
@@ -2562,9 +2659,11 @@ export {
2562
2659
  recoveryPollRunning,
2563
2660
  recoveryProvesNothingCharged,
2564
2661
  refusalIsSelectable,
2662
+ refusalIsTileBound,
2565
2663
  registerCityTable,
2566
2664
  registerGeo,
2567
2665
  registerGeoAsset,
2666
+ registerLassoAction,
2568
2667
  relativeLuminance,
2569
2668
  requiredD3Plugins,
2570
2669
  resolveAutoColorScale,
@@ -2594,9 +2693,11 @@ export {
2594
2693
  tableHostOf,
2595
2694
  toRGBA,
2596
2695
  toSourceRows,
2696
+ trackPress,
2597
2697
  transportFailureShouldRecover,
2598
2698
  unpinScrolledAxis,
2599
2699
  updateRowHighWater,
2700
+ validRowSet,
2600
2701
  valuePlacementFlag,
2601
2702
  vegaSpecReadsDatesInLocalTime,
2602
2703
  wireLimitCount,
package/dist/page.mjs CHANGED
@@ -14,7 +14,10 @@ import {
14
14
  readControls,
15
15
  viewFromToken,
16
16
  viewToken
17
- } from "./chunk-XIAL6EEC.mjs";
17
+ } from "./chunk-DTOGTKAJ.mjs";
18
+ import "./chunk-QIRLWJBI.mjs";
19
+ import "./chunk-IURROJT7.mjs";
20
+ import "./chunk-MR6TL7QZ.mjs";
18
21
  import "./chunk-GHODWOAL.mjs";
19
22
  export {
20
23
  LINKED_HOVER_CLASS,
package/dist/react.mjs CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  payloadRowReader,
14
14
  viewFromToken,
15
15
  viewToken
16
- } from "./chunk-XIAL6EEC.mjs";
16
+ } from "./chunk-DTOGTKAJ.mjs";
17
17
  import {
18
18
  assembleD3,
19
19
  createChartGroup,
@@ -22,11 +22,13 @@ import {
22
22
  loadGeo,
23
23
  syncMemberSelection,
24
24
  toSourceRows
25
- } from "./chunk-CJNONH6V.mjs";
26
- import "./chunk-2XWE6YFO.mjs";
27
- import "./chunk-MGAO2DR7.mjs";
25
+ } from "./chunk-2HKO6GEK.mjs";
26
+ import "./chunk-QIRLWJBI.mjs";
27
+ import "./chunk-2ZUUIZWL.mjs";
28
+ import "./chunk-7HKVV5T5.mjs";
29
+ import "./chunk-IURROJT7.mjs";
28
30
  import "./chunk-A2GMXZP7.mjs";
29
- import "./chunk-7JWL6LYE.mjs";
31
+ import "./chunk-MR6TL7QZ.mjs";
30
32
  import "./chunk-GHODWOAL.mjs";
31
33
 
32
34
  // src/react.tsx
package/dist/testing.mjs CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  MARK_CLASS,
5
5
  MARK_SELECTED_CLASS,
6
6
  ROW_IDX_ATTR
7
- } from "./chunk-7JWL6LYE.mjs";
7
+ } from "./chunk-MR6TL7QZ.mjs";
8
8
  import "./chunk-GHODWOAL.mjs";
9
9
 
10
10
  // src/testing/interact.ts
@@ -1,4 +1,4 @@
1
- export declare const HOST_CONTRACT_VERSION = "1.14.0";
1
+ export declare const HOST_CONTRACT_VERSION = "1.16.0";
2
2
  export type GeoPointPrecision = "latlon" | "city" | "zip3" | "state" | "country";
3
3
  /** Every valid tier, ordered most precise → coarsest. Runtime form of GeoPointPrecision. */
4
4
  export declare const GEO_POINT_PRECISIONS: readonly GeoPointPrecision[];
@@ -19,6 +19,18 @@ export declare const MARK_KEY_ATTR = "data-mark-key";
19
19
  export declare const NO_ROW_MARKS_ATTR = "data-lch-no-row-marks";
20
20
  export declare const SNAPSHOT_SVG_ATTR = "data-lch-snapshot";
21
21
  export declare const XFILTER_REFRESH_EVENT = "llm-xfilter-refresh";
22
+ /** What the event carries. `source` names who selected ("user" when a reader's gesture did); the host
23
+ * passes it on to its subscribers, and "chart" stands in when it is absent. */
24
+ export type XfilterRefreshDetail = {
25
+ clear: true;
26
+ source?: string;
27
+ } | {
28
+ mark: Element;
29
+ source?: string;
30
+ } | {
31
+ rows: readonly number[];
32
+ source?: string;
33
+ };
22
34
  export declare const CONTAINER_SLOT_ANIM_STOP = "__llmAnimStop";
23
35
  export declare const CONTAINER_SLOT_XF_CLEAR = "__llmXfClear";
24
36
  export declare const CONTAINER_SLOT_INITIAL_XF_MARK = "__llmInitialXfMark";
@@ -109,6 +121,9 @@ export interface RenderOptions {
109
121
  rolesRefused?: string[];
110
122
  } | null;
111
123
  dateCellsAreUtcDays?: boolean;
124
+ dataComplete?: boolean;
125
+ rowsWithheld?: number;
126
+ rowsFilteredOut?: number;
112
127
  geoPointDest?: {
113
128
  precision: GeoPointPrecision | null;
114
129
  precisionCounts: Record<GeoPointPrecision, number>;
@@ -178,6 +193,25 @@ export interface RenderOptions {
178
193
  * take the reader's gesture with it: the helper swallows anything this raises.
179
194
  */
180
195
  onControlChange?: (e: ChartControlChange) => void;
196
+ /**
197
+ * THE HOST LASSO (contract 1.16.0): whether this chart gets the gesture that draws around marks and selects the
198
+ * ones inside, and what the host does when it ends. A chart never draws the gesture; it hears it as an
199
+ * `llm-lasso` event on its container.
200
+ * capable - the capability the SERVER sent with this chart (the chart's type declares that it has no drag
201
+ * gesture of its own and that a lasso means something for it). ABSENT MEANS NOT CAPABLE: no host
202
+ * holds a list of chart types, so a chart saved before the capability existed has none.
203
+ * enabled - the reader's setting; on unless it is exactly false. Both must hold for a surface to be drawn.
204
+ * rowCap - the most rows in view that still get a lasso; above it the whole lasso is off and a caption says
205
+ * so. Absent is LASSO_ROW_CAP (provisional).
206
+ * actions - what the host runs on release, in order, by name. Absent is ["select"]; a name the host does
207
+ * not know is skipped, so a list can be sent ahead of the build that understands it.
208
+ */
209
+ lasso?: {
210
+ enabled?: boolean;
211
+ rowCap?: number;
212
+ actions?: string[];
213
+ capable?: boolean;
214
+ };
181
215
  }
182
216
  /** One reader gesture on a chart's own control. */
183
217
  export interface ChartControlChange {
@@ -1,4 +1,4 @@
1
- export { HOST_CONTRACT_VERSION, GEO_POINT_PRECISIONS, MARK_CLASS, LEGEND_MARK_CLASS, AXIS_FILTER_CLASS, ROW_IDX_ATTR, LIFT_SELECTED_CLASS, CONTROL_CLASS, NO_ROW_MARKS_ATTR, SELECTION_RULE_ATTR, SELECTION_RULE_CLICKED_MARKS, MARK_KEY_ATTR, CONTAINER_SLOT_CLICKED_MARKS, SNAPSHOT_SVG_ATTR, XFILTER_REFRESH_EVENT, CONTAINER_SLOT_ANIM_STOP, CONTAINER_SLOT_XF_CLEAR, CONTAINER_SLOT_INITIAL_XF_MARK, CONTAINER_SLOT_UI_STATE, VIEW_ONLY_UI_STATE_KEYS, withoutViewOnlyKeys, HOST_CONTAINER_CLASS, SELECTION_ACTIVE_CLASS, MARK_SELECTED_CLASS, ACTIVE_TICK_CLASS, DIM_OPACITY_VAR, DIM_OPACITY_DEFAULT, chartOwnsTimeline, periodTickSuppressesFeedback, ANIM_PLAY_SPEED_DEFAULT, ANIM_PLAY_SPEED_MIN, ANIM_PLAY_SPEED_MAX, ANIM_LOOP_DELAY_DEFAULT, ANIM_LOOP_DELAY_MIN, ANIM_MAX_IDEAL_FRAMES_DEFAULT, ANIM_MAX_IDEAL_FRAMES_MIN, ANIM_MAX_IDEAL_FRAMES_MAX, ANIMATION_OPTION_KEYS, COLOR_SCALE_SELF_CLAMP_PCT_DEFAULT, COLOR_SCALE_SELF_CLAMP_PCT_MIN, COLOR_SCALE_SELF_CLAMP_PCT_MAX, FLIP_MODE_DEFAULT, FLIP_INTERVAL_MIN_MS, FLIP_INTERVAL_MAX_MS, FLIP_DIRECTION_DEFAULT, APPROXIMATE_POSITIONS_DEFAULT, VALUE_AXIS_BASELINE_DEFAULT, SEASONAL_MARKERS_DEFAULT, MAX_MAP_POINTS_DEFAULT, type GeoPointPrecision, type GeoMapKind, type TimelineStyle, type FlipMode, type FlipDirection, type ApproximatePositions, type ValueAxisBaseline, type SeasonalMarkers, type ColorScaleScope, type RenderOptions, type ViewStateProvider, type ChartControlChange, } from "./contract";
1
+ export { HOST_CONTRACT_VERSION, GEO_POINT_PRECISIONS, MARK_CLASS, LEGEND_MARK_CLASS, AXIS_FILTER_CLASS, ROW_IDX_ATTR, LIFT_SELECTED_CLASS, CONTROL_CLASS, NO_ROW_MARKS_ATTR, SELECTION_RULE_ATTR, SELECTION_RULE_CLICKED_MARKS, MARK_KEY_ATTR, CONTAINER_SLOT_CLICKED_MARKS, SNAPSHOT_SVG_ATTR, XFILTER_REFRESH_EVENT, CONTAINER_SLOT_ANIM_STOP, CONTAINER_SLOT_XF_CLEAR, CONTAINER_SLOT_INITIAL_XF_MARK, CONTAINER_SLOT_UI_STATE, VIEW_ONLY_UI_STATE_KEYS, withoutViewOnlyKeys, HOST_CONTAINER_CLASS, SELECTION_ACTIVE_CLASS, MARK_SELECTED_CLASS, ACTIVE_TICK_CLASS, DIM_OPACITY_VAR, DIM_OPACITY_DEFAULT, chartOwnsTimeline, periodTickSuppressesFeedback, ANIM_PLAY_SPEED_DEFAULT, ANIM_PLAY_SPEED_MIN, ANIM_PLAY_SPEED_MAX, ANIM_LOOP_DELAY_DEFAULT, ANIM_LOOP_DELAY_MIN, ANIM_MAX_IDEAL_FRAMES_DEFAULT, ANIM_MAX_IDEAL_FRAMES_MIN, ANIM_MAX_IDEAL_FRAMES_MAX, ANIMATION_OPTION_KEYS, COLOR_SCALE_SELF_CLAMP_PCT_DEFAULT, COLOR_SCALE_SELF_CLAMP_PCT_MIN, COLOR_SCALE_SELF_CLAMP_PCT_MAX, FLIP_MODE_DEFAULT, FLIP_INTERVAL_MIN_MS, FLIP_INTERVAL_MAX_MS, FLIP_DIRECTION_DEFAULT, APPROXIMATE_POSITIONS_DEFAULT, VALUE_AXIS_BASELINE_DEFAULT, SEASONAL_MARKERS_DEFAULT, MAX_MAP_POINTS_DEFAULT, type GeoPointPrecision, type GeoMapKind, type TimelineStyle, type FlipMode, type FlipDirection, type ApproximatePositions, type ValueAxisBaseline, type SeasonalMarkers, type ColorScaleScope, type RenderOptions, type ViewStateProvider, type ChartControlChange, type XfilterRefreshDetail, } from "./contract";
2
2
  export { resolveOptions, type ResolveOptionsInput } from "./defaults";
3
3
  export { OPTIONS_VOCABULARY, LIVE_OPTION_KEYS, MAX_MAP_POINTS_MIN, MAX_MAP_POINTS_MAX, LIMIT_COUNT_MAX, wireLimitCount, codeReadsOption, type OptionVocabularyEntry, type OptionTiming, type OptionWire, type OptionKey, } from "./optionsVocabulary";
4
4
  export { loadGeo, geoFromCache, registerGeo, registerGeoAsset, geoAssetFor, clearGeoCache, type GeoAssetName, } from "./geoLazy";
@@ -13,14 +13,15 @@ export type { MarkNoteLike, NoteBadgeOptions } from "./markNotes";
13
13
  export type { Controls, ControlInfo, ControlsAttachment } from "./controls";
14
14
  export { createChartGroup, toSourceRows, syncMemberSelection, type ChartGroup, type ChartGroupMember, type ChartGroupSelection, type ChartGroupChange, type ChartGroupMemberOptions, type ChartGroupSourceOptions, type ChartGroupPayload } from "./group";
15
15
  export type { Filter, FilterScope, FilterOptions, FilterKey, FilterChangeReason, FilterBinding, BindFilterOptions, VegaInteractionEvent, PageView } from "./filterScope";
16
- export { createMarkResolver, isInsideControl, rowIdxsFromMark, nextSelection, selectionRuleOf, markKeyOf, planSelectionPaint, nextClickedMarks, sameRowSet, type SelectionRule, type ClickedMarks, type SelectionPaintMark, type SelectionPaintMode, type SelectionPaintPlan, collectD3GlyphCenters, clearSelectionGlyphs, paintSelectionGlyphs, SELECTION_GLYPH_CLASS, type MarkResolver, type MarkResolverEnv, type GlyphCenter, type SelectionGlyphStyle, type SelectionModifiers, } from "./selection";
16
+ export { createMarkResolver, isInsideControl, rowIdxsFromMark, nextSelection, DRAG_NOT_CLICK_PX, gestureWasDrag, trackPress, pressOf, clearPress, clickWasDrag, CONTAINER_SLOT_PRESS_AT, type PressPoint, dispatchRowSet, validRowSet, ROW_SET_MAX, selectionRuleOf, markKeyOf, planSelectionPaint, nextClickedMarks, sameRowSet, type SelectionRule, type ClickedMarks, type SelectionPaintMark, type SelectionPaintMode, type SelectionPaintPlan, collectD3GlyphCenters, clearSelectionGlyphs, paintSelectionGlyphs, SELECTION_GLYPH_CLASS, type MarkResolver, type MarkResolverEnv, type GlyphCenter, type SelectionGlyphStyle, type SelectionModifiers, } from "./selection";
17
+ export { installLasso, clearLasso, lassoVerdict, lassoRowCap, lassoActions, registerLassoAction, pointInShape, LASSO_ROW_CAP, LASSO_DRAG_PX, LASSO_SAMPLE_PX, LASSO_MAX_VERTICES, LASSO_RESTORE_MAX_VERTICES, LASSO_RESTORE_MAX_SHAPES, LASSO_EVENT, LASSO_SURFACE_CLASS, LASSO_OUTLINE_CLASS, LASSO_COUNT_CLASS, LASSO_NOTE_CLASS, LASSO_PLOT_CLASS, LASSO_MODE_ATTR, LASSO_KNOB_KEY, LASSO_AXES_SLOT, LASSO_DEFAULT_ACTIONS, type LassoSetting, type LassoVerdict, type LassoMode, type LassoSpace, type LassoShape, type LassoStored, type LassoEventDetail, type LassoAxes, type LassoAction, type LassoActionContext, type LassoEnv, type LassoHandle, } from "./lasso";
17
18
  export type { AdapterEvent, AdapterHit, AdapterId, AdapterScene, MarkHandle, MarkInfo, MarkRole, PaintRequest, RendererAdapter, RowTable, } from "./adapters/types";
18
19
  export { planTrivialChart, compileTrivialSource, type TrivialPlan, type TrivialShapeKind } from "./trivial";
19
20
  export { captureSvgSnapshot, svgToDataUrl, svgNaturalSize, rasterizeSvgToPngDataUrl, tableHostOf, chartSvgOf, htmlToSvgDataUrl, htmlNaturalSize, type SnapshotOptions } from "./snapshot";
20
21
  export { shouldReview, buildReviewWire, bareBase64, actionFor, type ReviewGate, type ReviewWire, type ReviewVerdict, type ReviewAction } from "./review";
21
22
  export { askApplyImprovements, type ReviewDialogOptions, type ReviewDialogText } from "./reviewDialog";
22
23
  export { mountProductFeedbackBox, normaliseProductFeedbackText, productFeedbackSendable, buildProductFeedbackPayload, PRODUCT_FEEDBACK_MAX_CHARS, PRODUCT_FEEDBACK_MIN_CHARS, type ProductFeedbackBox, type ProductFeedbackBoxOptions, type ProductFeedbackText, type ProductFeedbackSendResult, type ProductFeedbackPayload, type ProductFeedbackIdentity, type ProductFeedbackHost, } from "./productFeedback";
23
- export { qualifyGroupHeadingFor, newQualifyGroupState, type QualifyGroupRow, type QualifyGroupState, type QualifyGroupHeading, orderRefusalsForDisplay, refusalIsSelectable, hasRefusalsToShow, qualifyRefusalHeadingFor, newQualifyRefusalGroupState, qualifyRefusalReason, QUALIFY_REFUSAL_UNSPECIFIED, type QualifyRefusalRow, type QualifyRefusalGroupState, type QualifyRefusalHeading, } from "./qualifyGroups";
24
+ export { qualifyGroupHeadingFor, newQualifyGroupState, type QualifyGroupRow, type QualifyGroupState, type QualifyGroupHeading, orderRefusalsForDisplay, refusalIsSelectable, hasRefusalsToShow, qualifyRefusalHeadingFor, newQualifyRefusalGroupState, qualifyRefusalReason, QUALIFY_REFUSAL_UNSPECIFIED, refusalIsTileBound, QUALIFY_TILE_REFUSAL_CODES, QUALIFY_TOO_SMALL_HEADING, type QualifyRefusalRow, type QualifyRefusalGroupState, type QualifyRefusalHeading, } from "./qualifyGroups";
24
25
  export { qualifyPick, qualifyAuto, qualifyCancel, launchGenerates, launchFavorStyle, chooserFitsViewport, shouldOpenChooserOnGenerate, shouldOpenInlineChooserOnGenerate, canConfirmLaunch, confirmLaunch, qualifyFailureFallsOpen, CHOOSER_MIN_WIDTH_PX, CHOOSER_MIN_HEIGHT_PX, type QualifyLaunchOutcome, type ChooserGateInput, } from "./qualifyLaunch";
25
26
  export { normalizeFilterTerm, filterQualifyRows, readQualifyChartRow, readQualifyRefusalRow, DEFAULT_FILTER_MATCH_STYLE, filterMatchStyleOf, type FilterMatchStyle, filterFitsChooser, listNeedsFilter, qualifyFilterGate, inlineFilterGate, FILTER_MIN_TERM_CHARS, FILTER_ROW_PX, FILTER_MIN_WIDTH_PX, FILTER_MIN_HEIGHT_PX, INLINE_FILTER_MIN_ROWS, computeQualifyFilterView, qualifyFilterCountText, type QualifyFilterTier, type QualifyFilterResult, type QualifyFilterRead, type QualifyFilterGateReason, type QualifyFilterGateInput, type QualifyFilterRow, type QualifyFilterGroup, type QualifyFilterView, type QualifyFilterNoteKind, } from "./qualifyFilter";
26
27
  export { qualifyTableRows, type QualifyTableRow, type QualifyTableSource } from "./qualifyTable";
@@ -0,0 +1,143 @@
1
+ import { type RenderOptions } from "./contract";
2
+ /**
3
+ * THE MOST ROWS A CHART MAY HAVE IN VIEW AND STILL OFFER A LASSO.
4
+ *
5
+ * PROVISIONAL. Unmeasured: 5,000 is a stand-in until the time Power BI Desktop takes to apply a selection
6
+ * of that many ids is measured on a release-test page (1,000, 5,000 and 13,000 ids), and that number
7
+ * replaces this one. Do not read it as a finding. It is the worst case that is allowed for, not the
8
+ * typical one: a reader can lasso everything.
9
+ *
10
+ * Above it the WHOLE lasso is off: no surface is installed, and a one-line caption says why. It is one
11
+ * number for every host; a host may pass its own through RenderOptions.lasso.rowCap.
12
+ */
13
+ export declare const LASSO_ROW_CAP = 5000;
14
+ /** Travel, in px on either axis, at which a press stops being a click and becomes a lasso. */
15
+ export declare const LASSO_DRAG_PX = 5;
16
+ /** A freeform point is kept only when it is this far from the last one kept. */
17
+ export declare const LASSO_SAMPLE_PX = 3;
18
+ /** A freeform shape longer than this is thinned before it is used, so what is published, stored and
19
+ * restored is one and the same shape. */
20
+ export declare const LASSO_MAX_VERTICES = 400;
21
+ /** What a restore will read, per shape and in all: a bag is untrusted, and a poisoned one must not be able
22
+ * to ask for unbounded work. */
23
+ export declare const LASSO_RESTORE_MAX_VERTICES = 2000;
24
+ export declare const LASSO_RESTORE_MAX_SHAPES = 32;
25
+ /** The DOM event a chart listens for on its container. detail is a LassoEventDetail. */
26
+ export declare const LASSO_EVENT = "llm-lasso";
27
+ export declare const LASSO_SURFACE_CLASS = "lch-lasso-surface";
28
+ export declare const LASSO_OUTLINE_CLASS = "lch-lasso-outline";
29
+ export declare const LASSO_COUNT_CLASS = "lch-lasso-count";
30
+ export declare const LASSO_NOTE_CLASS = "lch-lasso-note";
31
+ /** The group a chart draws its plot in; the surface goes over it. Without one the chart's svg is the plot. */
32
+ export declare const LASSO_PLOT_CLASS = "lch-plot";
33
+ /** Set on the container to switch to a rectangle ("rect"); anything else is freeform. */
34
+ export declare const LASSO_MODE_ATTR = "data-lch-lasso-mode";
35
+ /** The key in the shared knob bag. */
36
+ export declare const LASSO_KNOB_KEY = "lasso";
37
+ /** A chart registers { toData([x, y]), toScreen([dx, dy]) } here so the shape is stored in data coordinates.
38
+ * x and y are in the user space of the element the surface sits in (the plot group). */
39
+ export declare const LASSO_AXES_SLOT = "__lchLassoAxes";
40
+ /** The action list a host runs when none is configured. */
41
+ export declare const LASSO_DEFAULT_ACTIONS: readonly string[];
42
+ /** RenderOptions.lasso. `capable` is the capability the server sent with this chart (absent means not
43
+ * capable); `enabled` is the reader's setting (default on); both must hold. */
44
+ export type LassoSetting = NonNullable<RenderOptions["lasso"]>;
45
+ /** "on" installs a surface. The others say why not; only "over-cap" shows a caption. */
46
+ export type LassoVerdict = "on" | "not-capable" | "disabled" | "over-cap";
47
+ /** The row cap in force: the setting's when it is a positive number, else LASSO_ROW_CAP. */
48
+ export declare function lassoRowCap(setting: LassoSetting | null | undefined): number;
49
+ /** The action names to run on release, in order. Anything that is not a list of names is the default. */
50
+ export declare function lassoActions(setting: LassoSetting | null | undefined): string[];
51
+ /** Whether a chart with `rows` rows in view gets a lasso under `setting`. */
52
+ export declare function lassoVerdict(setting: LassoSetting | null | undefined, rows: number): LassoVerdict;
53
+ type Pt = [number, number];
54
+ export type LassoMode = "free" | "rect";
55
+ export type LassoSpace = "data" | "unit";
56
+ /** One drawn shape as stored: a freeform polygon, or the four corners of a rectangle. */
57
+ export interface LassoShape {
58
+ mode: LassoMode;
59
+ pts: Pt[];
60
+ }
61
+ /** What the knob bag holds under LASSO_KNOB_KEY. */
62
+ export interface LassoStored {
63
+ v: 1;
64
+ space: LassoSpace;
65
+ shapes: LassoShape[];
66
+ }
67
+ /** detail of the `llm-lasso` DOM event. `polygon` is the last shape drawn, `polygons` every shape in the
68
+ * lasso, both in `space` (data coordinates, or fractions of the plot box); `rows` is empty when the lasso
69
+ * was cleared. source: "user" a gesture or a clear, "restore" a lasso re-applied on draw, "host" a clear the
70
+ * host made because the selection was replaced from outside. */
71
+ export interface LassoEventDetail {
72
+ rows: number[];
73
+ polygon: Pt[];
74
+ polygons: Pt[][];
75
+ mode: LassoMode;
76
+ space: LassoSpace;
77
+ source: "user" | "restore" | "host";
78
+ }
79
+ export interface LassoAxes {
80
+ toData(p: [number, number]): ArrayLike<unknown>;
81
+ toScreen(p: [number, number]): ArrayLike<unknown>;
82
+ }
83
+ /** Point in a shape: the bounding box rejects first; a rectangle is then done, and a freeform polygon is
84
+ * an even-odd ray cast. Implemented here so the host takes no dependency on a geometry library. */
85
+ export declare function pointInShape(shape: {
86
+ mode: LassoMode;
87
+ pts: ReadonlyArray<{
88
+ x: number;
89
+ y: number;
90
+ }>;
91
+ }, x: number, y: number): boolean;
92
+ /** What an action is given on release. */
93
+ export interface LassoActionContext {
94
+ /** The rows inside the lasso (every shape of it), ascending. */
95
+ rows: number[];
96
+ mode: LassoMode;
97
+ source: "user";
98
+ env: LassoEnv;
99
+ }
100
+ export type LassoAction = (ctx: LassoActionContext) => void;
101
+ /**
102
+ * Make `name` available to the action list (RenderOptions.lasso.actions). A name in the list that nothing
103
+ * registered is skipped, so a host can carry a list ahead of the build that understands it.
104
+ */
105
+ export declare function registerLassoAction(name: string, action: LassoAction): void;
106
+ /** What the host gives the lasso. The lasso never reaches into the host's selection itself. */
107
+ export interface LassoEnv {
108
+ container: HTMLElement;
109
+ /** The options of the render now on screen (a function, because setOptions replaces them). */
110
+ options: () => RenderOptions;
111
+ /** How many rows the chart was handed: the number the cap is measured against. */
112
+ rows: number;
113
+ /** Publish this row set as the selection (what the "select" action does). */
114
+ select(rows: number[]): void;
115
+ /** Clear the host's selection the way an empty click does: the chart's own clear slot first when the
116
+ * chart owns the selection, then a published clear. A no-op when nothing is selected. */
117
+ clearSelection(): void;
118
+ }
119
+ export interface LassoHandle {
120
+ /** The surface the gesture is read on; null when the lasso is off at this row count. */
121
+ readonly surface: Element | null;
122
+ /** The rows inside the lasso now drawn, ascending; empty when none. */
123
+ rows(): number[];
124
+ /** Erase the lasso. By default it also clears the host's selection and says so with `llm-lasso`. */
125
+ clear(opts?: {
126
+ publish?: boolean;
127
+ source?: "user" | "host";
128
+ }): void;
129
+ /** Remove the listeners and everything the lasso drew. Nothing is persisted. */
130
+ destroy(): void;
131
+ }
132
+ /**
133
+ * Put the lasso on the chart in `env.container`, which has just drawn. Returns null when the chart gets none
134
+ * (not capable, switched off, nothing to draw on); a handle for the caption when the rows exceed the cap;
135
+ * otherwise the live handle. A lasso already installed on the container is destroyed first.
136
+ */
137
+ export declare function installLasso(env: LassoEnv): LassoHandle | null;
138
+ /** Erase the lasso on `container`, if it has one, and clear the selection with it. */
139
+ export declare function clearLasso(container: Element | null | undefined, opts?: {
140
+ publish?: boolean;
141
+ source?: "user" | "host";
142
+ }): void;
143
+ export {};
@@ -44,15 +44,66 @@ export interface QualifyRefusalRow {
44
44
  reason?: string | null;
45
45
  /** True = a required channel is ABSENT. Absent/false = a threshold we are willing to waive. */
46
46
  isVeto?: boolean | null;
47
+ /**
48
+ * WHICH GATE wrote `reason`, as the server's stable code. Absent from a server that predates
49
+ * the code, which reads as "not known to be about the tile": the row keeps the grouping the
50
+ * list always had.
51
+ */
52
+ reasonCode?: string | null;
47
53
  }
48
54
  /** Which heading to write BEFORE a refused row, if any. */
49
- export type QualifyRefusalHeading = "poorFit" | "cannotDraw";
55
+ export type QualifyRefusalHeading = "poorFit" | "tooSmall" | "cannotDraw";
50
56
  /** Carried across the refusal loop. One per render. */
51
57
  export interface QualifyRefusalGroupState {
52
58
  poorFit: boolean;
59
+ tooSmall: boolean;
53
60
  cannotDraw: boolean;
54
61
  }
55
62
  export declare function newQualifyRefusalGroupState(): QualifyRefusalGroupState;
63
+ /**
64
+ * THE REFUSAL CODES THAT MEAN "THE TILE", NOT "THE FIELDS".
65
+ *
66
+ * Each refusal carries the code of the gate that wrote its sentence. These gates compare what a
67
+ * chart type needs with the size and shape of the tile and nothing else:
68
+ * - TILE_TOO_NARROW, TILE_TOO_SHORT, TILE_NOT_SQUARE, TILE_NOT_TALL: too narrow, too short, not
69
+ * square enough, not tall enough.
70
+ * - TILE_TOO_SMALL: a type that does not hold up on a small tile, turned down because the tile is
71
+ * under the size the full catalogue needs, whatever the data is.
72
+ * - EMBED_NOTHING_FITS_TILE: a headline-plus-small-drawing type whose drawing has no form that
73
+ * fits the tile; the headline alone is still drawable on a plain card.
74
+ * - EMBED_BEESWARM_TILE_TOO_SMALL: a beeswarm turned down because the tile is under the size it
75
+ * needs.
76
+ * The data can be exactly right and the type is still turned down, and the one thing that changes
77
+ * the answer is a bigger tile.
78
+ *
79
+ * Without this split those rows sat under "Can't be drawn from the fields as bound" or "Poor fit
80
+ * for these fields" - headings that send the reader to rebind data that is fine.
81
+ *
82
+ * ONLY GATES THAT LOOK AT THE TILE ALONE ARE LISTED. A gate that weighs the tile against the data
83
+ * (ROWS_CRAMPED, a row-per-category floor; TOO_MANY_PANELS, a panel budget; CATEGORIES_TOO_WIDE)
84
+ * can be answered by either, so naming it a tile problem would be the same false instruction
85
+ * turned around. A code is added here when the server starts sending one that is purely about the
86
+ * tile; an unknown code keeps the grouping it had.
87
+ */
88
+ export declare const QUALIFY_TILE_REFUSAL_CODES: readonly string[];
89
+ /**
90
+ * THE HEADING OVER THE TILE BLOCK, in the one place every host reads it from, so the wording
91
+ * cannot drift between them and a test pins it once.
92
+ *
93
+ * It says what the reader can do about it, not what category the row is in, and it says nothing
94
+ * about the fields: the rows under it are exactly the ones the fields are not the problem for.
95
+ * English source text - a host that localizes looks it up like its other headings.
96
+ */
97
+ export declare const QUALIFY_TOO_SMALL_HEADING = "Needs a bigger tile";
98
+ /**
99
+ * IS THIS REFUSAL ABOUT THE TILE'S SIZE OR SHAPE? Decided from the server's code, never from the
100
+ * sentence: a host that matched the English would go blind the day the sentences are translated,
101
+ * and would re-derive a verdict it was already handed.
102
+ *
103
+ * A row with no code (an older server) is NOT tile-bound. That is the safe direction: it keeps
104
+ * the two-heading grouping the list had before the code existed.
105
+ */
106
+ export declare function refusalIsTileBound(row: QualifyRefusalRow | null | undefined): boolean;
56
107
  /**
57
108
  * MAY THE READER PICK THIS ONE? The single place that answers it, in either host.
58
109
  *
@@ -63,15 +114,22 @@ export declare function newQualifyRefusalGroupState(): QualifyRefusalGroupState;
63
114
  */
64
115
  export declare function refusalIsSelectable(row: QualifyRefusalRow | null | undefined): boolean;
65
116
  /**
66
- * The refused rows in RENDER ORDER: everything pickable first, then the vetoes.
117
+ * The refused rows in RENDER ORDER: the pickable ones first, then the ones the tile alone turned
118
+ * down, then the vetoes the fields cause.
67
119
  *
68
120
  * A STABLE PARTITION, not a sort — within each block the server's alphabetical order survives, so
69
121
  * two answers over the same shape stay diffable. Rows without a name are dropped: a control
70
122
  * labelled with nothing cannot be chosen and a reason with no subject cannot be read.
71
123
  *
72
- * The two blocks are ordered pickable-first because the reader opened this section to DO something.
124
+ * The blocks are ordered pickable-first because the reader opened this section to DO something.
73
125
  * Putting the inert half above the actionable half makes them scroll past every chart they cannot
74
126
  * have to reach the ones they can.
127
+ *
128
+ * THE TILE BLOCK SITS BETWEEN THE TWO, and its own rows are pickable-first too. A tile refusal is
129
+ * a veto or a waivable one like any other (the reader may still pick the waivable ones), but what
130
+ * it asks of the reader is different: resize, not rebind. Every row the code marks as about the
131
+ * tile goes there whichever way its veto flag points, so none is left under a heading that names
132
+ * the fields.
75
133
  */
76
134
  export declare function orderRefusalsForDisplay<T extends QualifyRefusalRow>(rows: readonly T[] | null | undefined): T[];
77
135
  /**