@trdrs/quickcharts 5.4.0 → 5.6.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 CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 5.6.0
6
+
7
+ The currency and unit box holds its words in a 24px row inside its outline, at the row's start, 3px in from each end on a radius of 3. With `scaleUnitMenu` the row ends in a 7 by 5 caret and lights under the pointer, and `ScaleUnitMenuRequest.expanded(open)` lets the host say its menu stands open, which keeps the row lit and turns the caret up. The auto-scale and logarithmic buttons stand 4px apart, the pair centred on the scale.
8
+
9
+ ## 5.5.0
10
+
11
+ The indicator picker's rail offers Favorites only while something is starred, and keeps it while it is open. The author and count columns stand only while a listed row fills them, so a list of starred built-ins reads as stars and names. Items a host answers for the `builtin` collection list in Technicals after the shipped definitions, under the host's own kinds. `IndicatorPickerCollection.empty` gives a collection an empty state: a title, text, a mark drawn 120px square from the 28-unit glyph grid, and one action that reaches `act` with a `collection` target. `IndicatorPickerEmpty` is exported. `chart.indicators.open` takes a `kind` beside `collection` and opens with that kind's filter pressed.
12
+
5
13
  ## 5.4.0
6
14
 
7
15
  What is drawn over the canvas reads its ink from the canvas's lightness. Over a canvas of the other mode's lightness, such as a white canvas in dark mode, the legend, the scales' boxes and buttons, the pane and navigation buttons and the corner mark wear that mode's built-in colors, and the factory scale text and lines, grid and watermark are that mode's, so they read dark on a light canvas and light on a dark one. A color the host or the viewer named stays theirs.
package/README.md CHANGED
@@ -1603,20 +1603,26 @@ part in each through `contributeCapture` (see Extensions).
1603
1603
  ### Indicator picker content
1604
1604
 
1605
1605
  The Indicators button and `commands.execute('chart.indicators.open')` open the same picker.
1606
- Pass `{ collection: 'saved' }` as the command argument to open a declared host collection directly.
1606
+ Pass `{ collection: 'saved' }` as the command argument to open a declared host collection directly,
1607
+ and `kind` beside it (`{ collection: 'builtin', kind: 'template' }`) to open with that kind's filter
1608
+ pressed; a kind neither the chart's `indicator` nor one your source declares leaves every kind listed.
1607
1609
  An unknown collection falls back to the shipped catalog. Reopening an already open picker keeps its current selection and query.
1608
1610
  The picker opens on the same search field as the symbol search. Beside its list stands a rail of
1609
- collections: Favorites under Personal, and the 23 shipped definitions as Technicals under Built-in.
1610
- Pressing a definition's row adds a new instance to the currently active chart and keeps the picker
1611
- open. Favorites use your `ChartStorage` port. The list reads as a table of each row's star, name,
1612
- author, favorite count and actions; the shipped catalog shows the star, the name and the actions.
1613
- Escape and a press outside the box close the picker.
1611
+ collections: Favorites under Personal while anything is starred, and the 23 shipped definitions as
1612
+ Technicals under Built-in. Favorites stays in the rail while it is open, so unstarring the last row
1613
+ there leaves the trader where they are. Pressing a definition's row adds a new instance to the
1614
+ currently active chart and keeps the picker open. Favorites use your `ChartStorage` port. The list
1615
+ reads as a table of each row's star, name, author, favorite count and actions; the author and count
1616
+ columns stand only while a listed row fills them, so the shipped catalog shows the star, the name
1617
+ and the actions. Escape and a press outside the box close the picker.
1614
1618
 
1615
1619
  Supply `ChartWidgetOptions.indicatorPicker` to include additional localized collections and rows
1616
1620
  in that picker. You supply data and opaque actions, not DOM, indicator definitions, or a renderer.
1617
1621
  Built-in annotations can add favorite state, counts and actions; they cannot replace a definition,
1618
- its name, or Add, and their counts show wherever the list is a table (Favorites, and your table
1619
- collections). Without a source, the picker has only shipped built-ins and Favorites.
1622
+ its name, or Add, and their counts show wherever the list is a table. Items you answer for the
1623
+ `builtin` collection list in Technicals after the shipped definitions, so a kind of your own (see
1624
+ `kinds` below) can stand beside the chart's indicators there. Without a source, the picker has only
1625
+ shipped built-ins and Favorites.
1620
1626
 
1621
1627
  ```ts
1622
1628
  import type { IndicatorPickerSource } from '@trdrs/quickcharts'
@@ -1679,6 +1685,23 @@ const withTemplates: IndicatorPickerSource = {
1679
1685
  }
1680
1686
  ```
1681
1687
 
1688
+ A collection can carry an `empty` state for the list to show while it lists nothing and no search
1689
+ is typed: a `title`, optional `text`, an optional `icon` drawn 120px square from the same 28-unit
1690
+ grid as every contributed glyph, and an optional `action`, a button whose press reaches `act` with
1691
+ the target `{ kind: 'collection', id }`. The kind filters step aside while it shows. Without one, an
1692
+ empty collection reads the chart's own no-matches line.
1693
+
1694
+ ```ts
1695
+ import type { IndicatorPickerCollection } from '@trdrs/quickcharts'
1696
+
1697
+ const scripts: IndicatorPickerCollection = {
1698
+ id: 'scripts',
1699
+ label: 'My scripts',
1700
+ layout: 'list',
1701
+ empty: { title: 'No scripts yet', text: 'Write one and it lists here.', action: { id: 'create', label: 'Create script' } },
1702
+ }
1703
+ ```
1704
+
1682
1705
  A favorite action receives the requested next boolean. Successful actions refresh the current
1683
1706
  collection unless they return `close: true`. Refusals and exceptions keep the picker open with
1684
1707
  plain text, never rendered markup. Icons reuse `ChartExtensionIcon`; invalid icons draw no glyph.
@@ -2439,7 +2462,9 @@ the same in both modes, in `CHART_FACTORY_COLORS`. The sections and what stands
2439
2462
  `scaleUnitMenu` option the box is a button titled with the setting's name: a press hands your
2440
2463
  handler a `ScaleUnitMenuRequest` (the chart, the box's place in viewport pixels, and whether the
2441
2464
  keyboard pressed it) so your own currency and unit menu opens against it, and the box stays
2442
- while the pointer rests on it. Without the option the box is a label that takes no pointer, so
2465
+ while the pointer rests on it. Call the request's `expanded(true)` as your menu opens and
2466
+ `expanded(false)` as it closes: while it stands open the box stays lit and the caret at the end
2467
+ of its row points up. Without the option the box is a label that takes no pointer, so
2443
2468
  the scale under it still drags. The price-to-bar
2444
2469
  ratio lock (`lockPriceToBarRatio`) holds the price one bar's width spans: engaging it with no
2445
2470
  `priceToBarRatio` of its own takes the ratio on screen into that leaf, the scale stops framing
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.4.0",
2
+ "version": "5.6.0",
3
3
  "styles": [
4
4
  {
5
5
  "id": "candles",
package/dist/index.d.ts CHANGED
@@ -3689,6 +3689,19 @@ interface IndicatorPickerCollection {
3689
3689
  group?: string;
3690
3690
  /** Catalog columns by default; a personal list can omit author and favorite columns. */
3691
3691
  layout?: 'table' | 'list';
3692
+ /** What the list shows while the collection lists no row and no search is typed. Omitted, it
3693
+ * reads the chart's own no-matches line. */
3694
+ empty?: IndicatorPickerEmpty;
3695
+ }
3696
+ /** A collection's empty state, centred where its list stands: a mark, a title, a line of text and
3697
+ * one action, which the source's `act` runs with a `collection` target. */
3698
+ interface IndicatorPickerEmpty {
3699
+ title: string;
3700
+ text?: string;
3701
+ /** Drawn 120px square from the same 28-unit grid as every contributed glyph. */
3702
+ icon?: ChartExtensionIcon;
3703
+ /** The empty state's one button. `add` and `favorite` belong to the chart. */
3704
+ action?: IndicatorPickerAction;
3692
3705
  }
3693
3706
  /** A kind of row a host lists beside the chart's indicators. The picker offers each declared kind as
3694
3707
  * a filter under its search field, after All and the chart's own Indicators. */
@@ -3737,7 +3750,8 @@ interface IndicatorPickerSource {
3737
3750
  kinds?: readonly IndicatorPickerKind[];
3738
3751
  /** The host supplies localized text. A new query or collection aborts the previous read.
3739
3752
  * `builtInIds` are the built-ins the picker lists: every one, or those `builtInIndicators`
3740
- * offers. */
3753
+ * offers. Items answered for `builtin` list after the shipped definitions, and items answered
3754
+ * for `favorites` list there when starred. */
3741
3755
  list(request: {
3742
3756
  collection: string;
3743
3757
  query: string;
@@ -3750,11 +3764,12 @@ interface IndicatorPickerSource {
3750
3764
  kind: 'unavailable';
3751
3765
  message: string;
3752
3766
  }>;
3753
- /** `favorite` carries the requested next value. Closing aborts pending work; hosts must also
3754
- * check the signal before performing late UI effects. Add is never routed here. */
3767
+ /** `favorite` carries the requested next value. A `collection` target is the empty state's action
3768
+ * in the collection of that id. Closing aborts pending work; hosts must also check the signal
3769
+ * before performing late UI effects. Add is never routed here. */
3755
3770
  act(request: {
3756
3771
  target: {
3757
- kind: 'builtin' | 'item';
3772
+ kind: 'builtin' | 'item' | 'collection';
3758
3773
  id: string;
3759
3774
  };
3760
3775
  action: string;
@@ -5593,6 +5608,9 @@ interface ScaleUnitMenuRequest {
5593
5608
  };
5594
5609
  /** Whether the box was pressed from the keyboard, so the menu takes the focus. */
5595
5610
  readonly keyboard: boolean;
5611
+ /** Say whether the menu stands open: `true` as it opens and `false` as it closes. While it is open
5612
+ * the box stays lit and its caret points up. */
5613
+ expanded(open: boolean): void;
5596
5614
  }
5597
5615
  /** Everything needed to construct a widget. `container` and `datafeed` are the two hard
5598
5616
  * requirements; every other field has a working default. */
@@ -6612,4 +6630,4 @@ declare function mountTimeframePicker(options: TimeframePickerOptions & {
6612
6630
  container: HTMLElement;
6613
6631
  }): MountedTimeframePicker;
6614
6632
 
6615
- export { ARRANGEMENTS, type AccessPolicy, type ActiveSubsession, type Arrangement, type AttachDrawingsOptions, BRAND_DOWN, BRAND_UP, BUILT_IN_INDICATORS, BUILT_IN_LOCALES, type BuiltInIndicator, CHART_DATE_FORMATS, CHART_FACTORY_COLORS, CHART_ICON_IDS, CHART_SETTINGS_SECTIONS, CHART_STYLES, COLLAPSED_H, COMPARE_COLORS, type CandleStyleSettings, type CanvasTheme, type Capabilities, type ChartBackgroundType, ChartBody, type ChartChrome, type ChartCompareApi, type ChartControlVisibility, type ChartCustomLocale, ChartDatafeed, type ChartDateFormat, type ChartDictionary, type ChartDrawingsApi, type ChartEvents, type ChartExtension, type ChartExtensionCapture, type ChartExtensionCaptureFrame, type ChartExtensionChart, type ChartExtensionCommand, type ChartExtensionContext, type ChartExtensionHandle, type ChartExtensionIcon, type ChartExtensionIconPath, type ChartExtensionLegendRow, type ChartExtensionMenuBuilder, type ChartExtensionMenuContext, type ChartExtensionMenuItem, type ChartExtensionPane, type ChartExtensionPriceLine, type ChartExtensionReplayState, type ChartExtensionScope, type ChartExtensionSeries, type ChartFactoryColors, type ChartHandle, type ChartHistoryApi, type ChartHoursFormat, type ChartI18n, type ChartI18nOptions, type ChartIconArtwork, type ChartIconContext, type ChartIconDiagnostic, type ChartIconFactory, type ChartIconFailure, type ChartIconId, type ChartIcons, type ChartLastValueMode, type ChartLegendRow, type ChartLineColorType, type ChartLocale, type ChartLocaleCode, type ChartMenuAction, type ChartMenuContext, type ChartMenuIcon, type ChartMenuRow, ChartMessageKey, ChartMeta, type ChartPaneSyncApi, type ChartPreferences, type ChartPriceFormatter, type ChartPricePrecision, type ChartPriceSource, type ChartReplayApi, ChartSaveLoadAdapter, type ChartSaveLoadApi, type ChartScalePlacement, type ChartSessionHours, type ChartSettings, type ChartSettingsContribution, type ChartSettingsControls, type ChartSettingsForm, type ChartSettingsIconPainter, type ChartSettingsOption, type ChartSettingsPageId, type ChartSettingsRowHandle, type ChartSettingsSection, type ChartSettingsTip, type ChartStorage, type ChartStrokeStyle, type ChartStyleId, type ChartTimezone, type ChartTitleSource, type ChartTranslate, type ChartWidget, type ChartWidgetOptions, type CommandRegistry, type CommandResult, type CommandScope, type CommandSpec, type CompareDeps, type CompareEntry, type CompareHandle, type ComparePlacement, type CompareSnapshot, type CompareSymbol, type ContextMenuHandle, type CrosshairUi, type CustomThemes, DEFAULT_SUBSESSION, DEFAULT_TIMEZONE, type DataSourceMarkPainter, DataStatus, DatafeedSearchOptions, type DrawingApplyOutcome, DrawingAssetPort, DrawingContextKind, type DrawingDocumentApi, type DrawingDocumentPort, type DrawingDocumentRefusal, type DrawingEvent, type DrawingInks, type DrawingOwner, DrawingPreferences, type DrawingPresets, type DrawingReadOutcome, type DrawingRejection, type DrawingRejectionReason, DrawingResourceContext, DrawingsBody, type DrawingsEvents, type DrawingsHandle, DrawingsMeta, type DrawingsWorkflow, EXCHANGE_TIMEZONE, type FeatureConfig, FeedBar, type FetchLike, FillBetweenPrimitive, type FullscreenApi, type FullscreenOptions, type HistoryChange, type HistoryEventState, IMAGE_HEADER_H, type ImageApi, type ImageEvent, type ImageHeader, type ImageOptions, type ImageTextRun, type ImageTile, type IndicatorCategory, type IndicatorDefinition, type IndicatorEvent, type IndicatorFill, type IndicatorInstance, type IndicatorLevel, type IndicatorManifest, type IndicatorOverrides, type IndicatorPickerAction, type IndicatorPickerBuiltInState, type IndicatorPickerCollection, type IndicatorPickerItem, type IndicatorPickerKind, type IndicatorPickerSource, type IndicatorPlot, type IndicatorPlots, type IndicatorsApi, type IndicatorsRenderer, LAYOUT_MENU_ROWS, type LayoutApi, LayoutBody, type LayoutEvent, LayoutMeta, type LayoutOptions, type LayoutSaveLoadApi, type LayoutSyncFlags, type LegendUi, type LineStyleSettings, type LogicalRange, MAIN_MIN_H, MIN_BAR_SPACING, MIRRORED_ICONS, type ManifestFill, type ManifestInput, type ManifestLevel, type ManifestPlot, type ManifestRun, MarkIconId, type MarkPainters, type MarketStatus, type MatchSegment, type MountedSymbolSearch, type MountedTimeframePicker, type OpenResource, PRICE_SCALE_MODE, type PaneOp, type PanePlan, type PaneRect, type PaneState, type PartialChartSettings, type PlacedImage, type PlotArea, type PlotPoint, PriceFormat, PriceFormatter, RANGE_PRESETS, RECENT_SYMBOLS_CAP, REPLAY_SPEEDS, type RangeFrameTarget, type RangePreset, type RangeSpan, type ReadChartSettings, type RecentsPort, type ReplayEventState, type ReplaySpeed, type ResourceLoadOutcome, ResourceRef, type ResourceRemoveOutcome, type ResourceSaveOutcome, ResourceStore, SCALE_MODES, SCALE_MODE_OPTIONS, SCROLL_STEP_BARS, SESSION_DOT, SESSION_LABEL, SESSION_STATE_TITLE, SPREAD_OPERATORS, type SaveConflictInfo, type ScaleMode, type ScaleUnitMenuRequest, type SearchClassFilter, SearchClassNode, type SearchController, type SearchControllerOptions, type SearchDisplayOptions, SearchPage, type SearchScope, type SearchState, type SelectedDrawing, type SemanticTheme, type SessionBandsPrimitive, type SessionLook, type SessionModel, type SessionSchedule, type SessionSegment, type SessionSource, type SessionState, type SessionTimeline, type SettingsMenuUi, ShadePrimitive, type SpreadOperator, type SpreadOperatorId, type SubsessionSource, SymbolInfo, type SymbolMarkPainter, type SymbolPriceFormat, SymbolRow, type SymbolSearchCache, type SymbolSearchHandle, type SymbolSearchOptions, THEME_ROLES, TIMEFRAME_MAX, TIMEFRAME_PRESETS, TIMEFRAME_PRESET_TOKENS, TIMEFRAME_UNITS, TIMEFRAME_UNIT_NAME, TIMEFRAME_UNIT_SECONDS, TIMEZONES, TOP_BAR_SLOTS, TemplateBody, TemplateMeta, TextDraft, TextEditFrame, type TextEditSession, type TextInlineEdit, type ThemeChangeListener, type ThemeController, type ThemeControllerOptions, type ThemeDeclaration, type ThemeDiagnostic, type ThemeDiagnosticCode, type ThemeMode, type ThemeOptions, type ThemeRole, type ThemeRoleFamily, type ThemeRoleId, type ThemeRoleKind, type ThemeRootStyle, type TimeLabelFormat, type TimeRange, type Timeframe, type TimeframeGroup, type TimeframePickerHandle, type TimeframePickerOptions, type TimeframeRestrictions, type TimeframeUnit, type TimezoneRow, type ToolbarButton, type ToolbarButtonOptions, type ToolbarButtonState, type TopBarSlot, type TopBarUi, type TouchOptions, type TransitionOptions, type UdfDatafeedOptions, type UdfSymbolResponse, type UiConfig, type VenueMarkPainter, type WidgetEvents, ZOOM_FACTOR, type ZoneClock, allowedTimeframes, applyBar, applyPlotOverrides, arrangementName, arrangementOf, attachCompare, attachDrawings, attachIndicators, autoTimeframeFor, buildManifestPlots, canvasTheme, canvasToBlob, chartContextMenu, chartDateSample, chartDictionaries, chartIconArtwork, chartSettingsDefaults, clipToWindow, coerceChartStyle, coerceScaleMode, compareTimeframes, composeFormingBar, composeImage, createChart, createChartI18n, createSearchController, createSessionBands, createSymbolSearchCache, createThemeController, createUdfDatafeed, effectivePlotColor, exchangeTimezoneText, formatChartDate, formatClock, formatDuration, formatTimeframe, frameRange, hasExtendedHours, imageFileName, imageHeaderRuns, imageLayoutHeaderRuns, imageTileRuns, indicatorHidden, isChartStyle, isCollapsed, isIntradayTimeframe, isSymbolPair, isTimezoneChoice, latestPlotValue, layerChartSettings, looksLikeSpread, makeCrosshairTimeFormatter, makeTickMarkFormatter, manifestInputDefaults, marketStatus, marketStatusFor, marketStatusText, marketStatusTitle, matchSegments, memoryChartStorage, memoryRecents, mountContextMenu, mountSymbolSearch, mountTimeframePicker, nextSessionChange, openInputsEditor, openSymbolSearch, openTimeframePicker, overriddenManifest, parseSessionModel, parseTimeframe, pickCompareColor, placeableByWidget, planPaneOp, promoteRecent, rangeAvailable, rangePresetTip, rangeSpanSeconds, readPartialChartSettings, resolveDisplayTimezone, resolveInitialTf, scrolledPosition, seriesTargetOf, sessionBreakTimes, sessionStateAt, sessionTimeline, spreadExpression, spreadSearchQuery, subTimeframesFor, subsessionBarFilter, tfSeconds, tfToUdfResolution, timeframeAllowed, timeframeGroupUnit, timeframeLabel, timeframeOrder, timeframeSeconds, timezoneCity, timezoneLabel, timezoneListing, toolName, tzOffsetLabel, tzOffsetMinutes, udfPriceFormat, udfResolutionToTf, udfSymbolInfo, valueShaped, withFoldedHistory, zoneClock, zoomedBarSpacing };
6633
+ export { ARRANGEMENTS, type AccessPolicy, type ActiveSubsession, type Arrangement, type AttachDrawingsOptions, BRAND_DOWN, BRAND_UP, BUILT_IN_INDICATORS, BUILT_IN_LOCALES, type BuiltInIndicator, CHART_DATE_FORMATS, CHART_FACTORY_COLORS, CHART_ICON_IDS, CHART_SETTINGS_SECTIONS, CHART_STYLES, COLLAPSED_H, COMPARE_COLORS, type CandleStyleSettings, type CanvasTheme, type Capabilities, type ChartBackgroundType, ChartBody, type ChartChrome, type ChartCompareApi, type ChartControlVisibility, type ChartCustomLocale, ChartDatafeed, type ChartDateFormat, type ChartDictionary, type ChartDrawingsApi, type ChartEvents, type ChartExtension, type ChartExtensionCapture, type ChartExtensionCaptureFrame, type ChartExtensionChart, type ChartExtensionCommand, type ChartExtensionContext, type ChartExtensionHandle, type ChartExtensionIcon, type ChartExtensionIconPath, type ChartExtensionLegendRow, type ChartExtensionMenuBuilder, type ChartExtensionMenuContext, type ChartExtensionMenuItem, type ChartExtensionPane, type ChartExtensionPriceLine, type ChartExtensionReplayState, type ChartExtensionScope, type ChartExtensionSeries, type ChartFactoryColors, type ChartHandle, type ChartHistoryApi, type ChartHoursFormat, type ChartI18n, type ChartI18nOptions, type ChartIconArtwork, type ChartIconContext, type ChartIconDiagnostic, type ChartIconFactory, type ChartIconFailure, type ChartIconId, type ChartIcons, type ChartLastValueMode, type ChartLegendRow, type ChartLineColorType, type ChartLocale, type ChartLocaleCode, type ChartMenuAction, type ChartMenuContext, type ChartMenuIcon, type ChartMenuRow, ChartMessageKey, ChartMeta, type ChartPaneSyncApi, type ChartPreferences, type ChartPriceFormatter, type ChartPricePrecision, type ChartPriceSource, type ChartReplayApi, ChartSaveLoadAdapter, type ChartSaveLoadApi, type ChartScalePlacement, type ChartSessionHours, type ChartSettings, type ChartSettingsContribution, type ChartSettingsControls, type ChartSettingsForm, type ChartSettingsIconPainter, type ChartSettingsOption, type ChartSettingsPageId, type ChartSettingsRowHandle, type ChartSettingsSection, type ChartSettingsTip, type ChartStorage, type ChartStrokeStyle, type ChartStyleId, type ChartTimezone, type ChartTitleSource, type ChartTranslate, type ChartWidget, type ChartWidgetOptions, type CommandRegistry, type CommandResult, type CommandScope, type CommandSpec, type CompareDeps, type CompareEntry, type CompareHandle, type ComparePlacement, type CompareSnapshot, type CompareSymbol, type ContextMenuHandle, type CrosshairUi, type CustomThemes, DEFAULT_SUBSESSION, DEFAULT_TIMEZONE, type DataSourceMarkPainter, DataStatus, DatafeedSearchOptions, type DrawingApplyOutcome, DrawingAssetPort, DrawingContextKind, type DrawingDocumentApi, type DrawingDocumentPort, type DrawingDocumentRefusal, type DrawingEvent, type DrawingInks, type DrawingOwner, DrawingPreferences, type DrawingPresets, type DrawingReadOutcome, type DrawingRejection, type DrawingRejectionReason, DrawingResourceContext, DrawingsBody, type DrawingsEvents, type DrawingsHandle, DrawingsMeta, type DrawingsWorkflow, EXCHANGE_TIMEZONE, type FeatureConfig, FeedBar, type FetchLike, FillBetweenPrimitive, type FullscreenApi, type FullscreenOptions, type HistoryChange, type HistoryEventState, IMAGE_HEADER_H, type ImageApi, type ImageEvent, type ImageHeader, type ImageOptions, type ImageTextRun, type ImageTile, type IndicatorCategory, type IndicatorDefinition, type IndicatorEvent, type IndicatorFill, type IndicatorInstance, type IndicatorLevel, type IndicatorManifest, type IndicatorOverrides, type IndicatorPickerAction, type IndicatorPickerBuiltInState, type IndicatorPickerCollection, type IndicatorPickerEmpty, type IndicatorPickerItem, type IndicatorPickerKind, type IndicatorPickerSource, type IndicatorPlot, type IndicatorPlots, type IndicatorsApi, type IndicatorsRenderer, LAYOUT_MENU_ROWS, type LayoutApi, LayoutBody, type LayoutEvent, LayoutMeta, type LayoutOptions, type LayoutSaveLoadApi, type LayoutSyncFlags, type LegendUi, type LineStyleSettings, type LogicalRange, MAIN_MIN_H, MIN_BAR_SPACING, MIRRORED_ICONS, type ManifestFill, type ManifestInput, type ManifestLevel, type ManifestPlot, type ManifestRun, MarkIconId, type MarkPainters, type MarketStatus, type MatchSegment, type MountedSymbolSearch, type MountedTimeframePicker, type OpenResource, PRICE_SCALE_MODE, type PaneOp, type PanePlan, type PaneRect, type PaneState, type PartialChartSettings, type PlacedImage, type PlotArea, type PlotPoint, PriceFormat, PriceFormatter, RANGE_PRESETS, RECENT_SYMBOLS_CAP, REPLAY_SPEEDS, type RangeFrameTarget, type RangePreset, type RangeSpan, type ReadChartSettings, type RecentsPort, type ReplayEventState, type ReplaySpeed, type ResourceLoadOutcome, ResourceRef, type ResourceRemoveOutcome, type ResourceSaveOutcome, ResourceStore, SCALE_MODES, SCALE_MODE_OPTIONS, SCROLL_STEP_BARS, SESSION_DOT, SESSION_LABEL, SESSION_STATE_TITLE, SPREAD_OPERATORS, type SaveConflictInfo, type ScaleMode, type ScaleUnitMenuRequest, type SearchClassFilter, SearchClassNode, type SearchController, type SearchControllerOptions, type SearchDisplayOptions, SearchPage, type SearchScope, type SearchState, type SelectedDrawing, type SemanticTheme, type SessionBandsPrimitive, type SessionLook, type SessionModel, type SessionSchedule, type SessionSegment, type SessionSource, type SessionState, type SessionTimeline, type SettingsMenuUi, ShadePrimitive, type SpreadOperator, type SpreadOperatorId, type SubsessionSource, SymbolInfo, type SymbolMarkPainter, type SymbolPriceFormat, SymbolRow, type SymbolSearchCache, type SymbolSearchHandle, type SymbolSearchOptions, THEME_ROLES, TIMEFRAME_MAX, TIMEFRAME_PRESETS, TIMEFRAME_PRESET_TOKENS, TIMEFRAME_UNITS, TIMEFRAME_UNIT_NAME, TIMEFRAME_UNIT_SECONDS, TIMEZONES, TOP_BAR_SLOTS, TemplateBody, TemplateMeta, TextDraft, TextEditFrame, type TextEditSession, type TextInlineEdit, type ThemeChangeListener, type ThemeController, type ThemeControllerOptions, type ThemeDeclaration, type ThemeDiagnostic, type ThemeDiagnosticCode, type ThemeMode, type ThemeOptions, type ThemeRole, type ThemeRoleFamily, type ThemeRoleId, type ThemeRoleKind, type ThemeRootStyle, type TimeLabelFormat, type TimeRange, type Timeframe, type TimeframeGroup, type TimeframePickerHandle, type TimeframePickerOptions, type TimeframeRestrictions, type TimeframeUnit, type TimezoneRow, type ToolbarButton, type ToolbarButtonOptions, type ToolbarButtonState, type TopBarSlot, type TopBarUi, type TouchOptions, type TransitionOptions, type UdfDatafeedOptions, type UdfSymbolResponse, type UiConfig, type VenueMarkPainter, type WidgetEvents, ZOOM_FACTOR, type ZoneClock, allowedTimeframes, applyBar, applyPlotOverrides, arrangementName, arrangementOf, attachCompare, attachDrawings, attachIndicators, autoTimeframeFor, buildManifestPlots, canvasTheme, canvasToBlob, chartContextMenu, chartDateSample, chartDictionaries, chartIconArtwork, chartSettingsDefaults, clipToWindow, coerceChartStyle, coerceScaleMode, compareTimeframes, composeFormingBar, composeImage, createChart, createChartI18n, createSearchController, createSessionBands, createSymbolSearchCache, createThemeController, createUdfDatafeed, effectivePlotColor, exchangeTimezoneText, formatChartDate, formatClock, formatDuration, formatTimeframe, frameRange, hasExtendedHours, imageFileName, imageHeaderRuns, imageLayoutHeaderRuns, imageTileRuns, indicatorHidden, isChartStyle, isCollapsed, isIntradayTimeframe, isSymbolPair, isTimezoneChoice, latestPlotValue, layerChartSettings, looksLikeSpread, makeCrosshairTimeFormatter, makeTickMarkFormatter, manifestInputDefaults, marketStatus, marketStatusFor, marketStatusText, marketStatusTitle, matchSegments, memoryChartStorage, memoryRecents, mountContextMenu, mountSymbolSearch, mountTimeframePicker, nextSessionChange, openInputsEditor, openSymbolSearch, openTimeframePicker, overriddenManifest, parseSessionModel, parseTimeframe, pickCompareColor, placeableByWidget, planPaneOp, promoteRecent, rangeAvailable, rangePresetTip, rangeSpanSeconds, readPartialChartSettings, resolveDisplayTimezone, resolveInitialTf, scrolledPosition, seriesTargetOf, sessionBreakTimes, sessionStateAt, sessionTimeline, spreadExpression, spreadSearchQuery, subTimeframesFor, subsessionBarFilter, tfSeconds, tfToUdfResolution, timeframeAllowed, timeframeGroupUnit, timeframeLabel, timeframeOrder, timeframeSeconds, timezoneCity, timezoneLabel, timezoneListing, toolName, tzOffsetLabel, tzOffsetMinutes, udfPriceFormat, udfResolutionToTf, udfSymbolInfo, valueShaped, withFoldedHistory, zoneClock, zoomedBarSpacing };
package/dist/index.js CHANGED
@@ -8299,15 +8299,15 @@ var drawable = (shape) => {
8299
8299
  if (rule !== void 0 && rule !== "nonzero" && rule !== "evenodd") return false;
8300
8300
  return width === void 0 || Number.isFinite(width) && width > 0 && width <= GLYPH_LIMITS.strokeWidth;
8301
8301
  };
8302
- function buildGlyph(icon) {
8302
+ function buildGlyph(icon, size = GRID) {
8303
8303
  try {
8304
8304
  const paths = icon && Array.isArray(icon.paths) ? icon.paths : [];
8305
8305
  if (paths.length === 0 || paths.length > GLYPH_LIMITS.shapes) return null;
8306
8306
  const shapes = paths.filter(drawable);
8307
8307
  if (shapes.length === 0) return null;
8308
8308
  const root = document.createElementNS(SVG_NS, "svg");
8309
- set(root, GLYPH_ATTRIBUTES.svg, "width", String(GRID));
8310
- set(root, GLYPH_ATTRIBUTES.svg, "height", String(GRID));
8309
+ set(root, GLYPH_ATTRIBUTES.svg, "width", String(size));
8310
+ set(root, GLYPH_ATTRIBUTES.svg, "height", String(size));
8311
8311
  set(root, GLYPH_ATTRIBUTES.svg, "viewBox", `0 0 ${GRID} ${GRID}`);
8312
8312
  set(root, GLYPH_ATTRIBUTES.svg, "fill", "none");
8313
8313
  set(root, GLYPH_ATTRIBUTES.svg, "aria-hidden", "true");
@@ -10205,6 +10205,9 @@ var ICONS = {
10205
10205
  /** The pickers' wide caret, on its native 16 by 8 grid: the trigger arrow, which
10206
10206
  * renders half size beside a picker's text. */
10207
10207
  menuArrowWide: { viewBox: "0 0 16 8", body: solid(polyline([[0.6, 0.7], [8, 7], [15.4, 0.7]], 1.8)) },
10208
+ /** The currency and unit box's caret, on its native 7 by 5 grid: a 1.2 stroke bent down at its
10209
+ * middle, drawn at its own size after the box's words. */
10210
+ scaleUnitArrow: { viewBox: "0 0 7 5", body: '<path d="M1 1.5l2.5 2 2.5-2" stroke="currentColor" stroke-width="1.2"/>' },
10208
10211
  // Hairline weight: these two sit beside a label rather than alone in a 38px cell. A tray taking an
10209
10212
  // arrow, and two sheets, the back one broken where the front lies over it.
10210
10213
  download: { viewBox: "0 0 28 28", body: solid(bend([[6.5, 17], [6.5, 22.5], [22.5, 22.5], [22.5, 17]], 1) + line2([14.5, 6], [14.5, 18]) + polyline([[10.5, 14.5], [14.5, 18.5], [18.5, 14.5]])) },
@@ -18195,7 +18198,7 @@ var CONTROL_ICONS = byMeaning({
18195
18198
  image: [ICONS.camera],
18196
18199
  download: [ICONS.download],
18197
18200
  copy: [ICONS.copy],
18198
- caret: [ICONS.menuArrowWide],
18201
+ caret: [ICONS.menuArrowWide, ICONS.scaleUnitArrow],
18199
18202
  info: [ICONS.info],
18200
18203
  // The legend.
18201
18204
  visible: [ICONS.legendEye],
@@ -20435,7 +20438,7 @@ function mountNavControls(deps) {
20435
20438
  }
20436
20439
 
20437
20440
  // src/ui/chrome/scaleControls.ts
20438
- var BUTTON = { width: 20, height: 22, gap: 15, foot: 4 };
20441
+ var BUTTON = { width: 20, height: 22, gap: 4, foot: 4 };
20439
20442
  var UNIT_BOX = { inset: 4 };
20440
20443
  function mountScaleControls(deps) {
20441
20444
  const t = deps.i18n.t;
@@ -20445,12 +20448,15 @@ function mountScaleControls(deps) {
20445
20448
  modes.append(auto, log);
20446
20449
  stopPointer(modes);
20447
20450
  const door = deps.openUnitMenu;
20448
- const unit = door ? h("button", { type: "button", class: "qc-scale-unit", "data-role": "scale-unit" }) : h("div", { class: "qc-scale-unit", "data-role": "scale-unit" });
20451
+ const unit = door ? h("button", { type: "button", class: "qc-scale-unit", "data-role": "scale-unit", "aria-haspopup": "menu", "aria-expanded": "false" }) : h("div", { class: "qc-scale-unit", "data-role": "scale-unit" });
20452
+ const unitText = h("span", {});
20453
+ unit.append(h("span", { class: "qc-scale-unit-row" }, unitText, door ? deps.icons.glyph(ICONS.scaleUnitArrow, { size: 7, height: 5, className: "qc-scale-unit-arrow" }) : null));
20449
20454
  if (door) {
20450
20455
  stopPointer(unit);
20456
+ const expanded = (open2) => unit.setAttribute("aria-expanded", String(open2 === true));
20451
20457
  unit.addEventListener("click", (event) => {
20452
20458
  const box2 = unit.getBoundingClientRect();
20453
- door({ left: box2.left, top: box2.top, right: box2.right, bottom: box2.bottom }, event.detail === 0);
20459
+ door({ left: box2.left, top: box2.top, right: box2.right, bottom: box2.bottom }, event.detail === 0, expanded);
20454
20460
  });
20455
20461
  }
20456
20462
  deps.chrome.appendChild(unit);
@@ -20569,7 +20575,7 @@ function mountScaleControls(deps) {
20569
20575
  const currency = named2?.currency?.trim() ?? "";
20570
20576
  const unitId = named2?.unit?.trim() ?? "";
20571
20577
  const text2 = currency && unitId ? t("chrome.currencyAndUnit", { currency, unit: unitId }) : currency || unitId;
20572
- unit.textContent = text2;
20578
+ unitText.textContent = text2;
20573
20579
  unit.dataset.qcVisibility = visibility;
20574
20580
  unit.hidden = text2 === "" || visibility === "never" || visibility === "hover" && !overScale && !overControls;
20575
20581
  unit.style.top = `${Math.round(box2.top + UNIT_BOX.inset)}px`;
@@ -21072,7 +21078,13 @@ function registerChartCommands(deps) {
21072
21078
  scope: "chart",
21073
21079
  label: "chrome.indicators",
21074
21080
  available: () => ui.indicatorPicker,
21075
- execute: (arg) => deps.indicatorsOpen(arg && typeof arg === "object" && "collection" in arg && typeof arg.collection === "string" ? arg.collection : void 0)
21081
+ execute: (arg) => {
21082
+ const field = (key) => {
21083
+ const value = arg && typeof arg === "object" ? arg[key] : void 0;
21084
+ return typeof value === "string" ? value : void 0;
21085
+ };
21086
+ return deps.indicatorsOpen(field("collection"), field("kind"));
21087
+ }
21076
21088
  });
21077
21089
  const isInstance = (arg) => !!arg && typeof arg === "object" && typeof arg.id === "string" && typeof arg.definition === "object";
21078
21090
  add({
@@ -22760,6 +22772,7 @@ function createChartInstance(deps) {
22760
22772
  chrome: chrome2,
22761
22773
  gestures,
22762
22774
  i18n,
22775
+ icons: deps.icons,
22763
22776
  box: priceScaleBox,
22764
22777
  modeButtons: () => eff.priceScale.scaleModeButtons,
22765
22778
  unitBox: () => eff.priceScale.currencyAndUnit,
@@ -22776,7 +22789,7 @@ function createChartInstance(deps) {
22776
22789
  openPriceMenu: (anchor2, keyboard) => {
22777
22790
  menu2?.raisePriceMenu(anchor2, keyboard);
22778
22791
  },
22779
- ...deps.scaleUnitMenu ? { openUnitMenu: (anchor2, keyboard) => deps.scaleUnitMenu?.({ chart: handle, anchor: anchor2, keyboard }) } : {}
22792
+ ...deps.scaleUnitMenu ? { openUnitMenu: (anchor2, keyboard, expanded) => deps.scaleUnitMenu?.({ chart: handle, anchor: anchor2, keyboard, expanded }) } : {}
22780
22793
  }) : null;
22781
22794
  scalePlus = scaleControls && menu2 ? attachScalePlus({
22782
22795
  chart,
@@ -23821,7 +23834,7 @@ function createChartInstance(deps) {
23821
23834
  crosshairLevel,
23822
23835
  formatter: () => symbolFormatter,
23823
23836
  compareOpen: (mode, changeFrom) => compare?.openDialog(mode, changeFrom),
23824
- indicatorsOpen: (collection) => deps.doors.showIndicatorPicker(collection),
23837
+ indicatorsOpen: (collection, kind) => deps.doors.showIndicatorPicker(collection, kind),
23825
23838
  symbolSearchOpen: () => deps.doors.openSearch({ mode: "search", chart: handle }),
23826
23839
  drawingVerbs: () => drawings2.verbs
23827
23840
  });
@@ -25596,13 +25609,21 @@ function actions(value) {
25596
25609
  }
25597
25610
  return unique(result.map((a) => a.id)) ? result : null;
25598
25611
  }
25612
+ function emptyState2(value) {
25613
+ if (!record2(value) || !text(value.title) || !optionalText(value.text)) return null;
25614
+ const action = value.action === void 0 ? [] : actions([value.action]);
25615
+ if (!action) return null;
25616
+ return { title: value.title, ...value.text !== void 0 ? { text: value.text } : {}, ...value.icon !== void 0 ? { icon: value.icon } : {}, ...action[0] ? { action: action[0] } : {} };
25617
+ }
25599
25618
  function pickerCollections(value) {
25600
25619
  try {
25601
25620
  if (!Array.isArray(value)) return null;
25602
25621
  const result = [];
25603
25622
  for (const row2 of value) {
25604
25623
  if (!record2(row2) || !text(row2.id) || ["builtin", "favorites"].includes(row2.id) || !text(row2.label) || !optionalText(row2.group) || row2.layout !== void 0 && row2.layout !== "list" && row2.layout !== "table") return null;
25605
- result.push({ id: row2.id, label: row2.label, ...row2.icon !== void 0 ? { icon: row2.icon } : {}, ...row2.group !== void 0 ? { group: row2.group } : {}, ...row2.layout !== void 0 ? { layout: row2.layout } : {} });
25624
+ const empty = row2.empty === void 0 ? void 0 : emptyState2(row2.empty);
25625
+ if (empty === null) return null;
25626
+ result.push({ id: row2.id, label: row2.label, ...row2.icon !== void 0 ? { icon: row2.icon } : {}, ...row2.group !== void 0 ? { group: row2.group } : {}, ...row2.layout !== void 0 ? { layout: row2.layout } : {}, ...empty ? { empty } : {} });
25606
25627
  }
25607
25628
  return unique(result.map((row2) => row2.id)) ? result : null;
25608
25629
  } catch {
@@ -25703,8 +25724,10 @@ function openIndicatorPicker(deps) {
25703
25724
  } catch {
25704
25725
  }
25705
25726
  let query = "";
25706
- let collection = deps.initialCollection === "favorites" || collections?.some((row2) => row2.id === deps.initialCollection) ? deps.initialCollection : "builtin";
25707
- let kind = null;
25727
+ let hostStarred = false;
25728
+ const starred = () => favorites.length > 0 || hostStarred;
25729
+ let collection = deps.initialCollection === "favorites" && starred() || collections?.some((row2) => row2.id === deps.initialCollection) ? deps.initialCollection : "builtin";
25730
+ let kind = deps.initialKind ?? null;
25708
25731
  let generation = 0;
25709
25732
  let controller = null;
25710
25733
  let busy = false;
@@ -25744,6 +25767,9 @@ function openIndicatorPicker(deps) {
25744
25767
  const strip = h("div", { class: "qc-search-classes" });
25745
25768
  const nav = h("nav", { class: "qc-picker-nav", "aria-label": t("picker.collections") });
25746
25769
  const list = h("div", { class: "qc-picker-list", role: "table", "aria-label": t("picker.title") });
25770
+ const vacant = h("div", { class: "qc-picker-empty" });
25771
+ vacant.hidden = true;
25772
+ let railFavorites = false;
25747
25773
  const status2 = h("div", { class: "qc-picker-status qc-secondary", role: "status", "aria-live": "polite" });
25748
25774
  let pendingFocus = null;
25749
25775
  const actionButton = (label3, content, run, disabled = false, focusKey, className = "qc-picker-action") => {
@@ -25843,7 +25869,7 @@ function openIndicatorPicker(deps) {
25843
25869
  else if (focused && focused !== document.body) pendingFocus = null;
25844
25870
  const selected = (collections ?? []).find((row2) => row2.id === collection);
25845
25871
  list.classList.toggle("qc-picker-list--personal", selected?.layout === "list");
25846
- list.classList.toggle("qc-picker-list--catalog", collection === "builtin");
25872
+ if (railFavorites !== (starred() || collection === "favorites")) renderNavigation();
25847
25873
  for (const button3 of nav.querySelectorAll("[data-picker-collection]")) button3.setAttribute("aria-pressed", String(button3.getAttribute("data-picker-collection") === collection));
25848
25874
  for (const chip of strip.querySelectorAll("[data-picker-kind]")) chip.setAttribute("aria-pressed", String((chip.getAttribute("data-picker-kind") || null) === kind));
25849
25875
  const headings = h("div", { role: "row", class: "qc-picker-headings" }, ...["", t("picker.name"), t("picker.author"), t("picker.favorites"), ""].map((label3) => h("span", { role: "columnheader" }, label3)));
@@ -25858,13 +25884,31 @@ function openIndicatorPicker(deps) {
25858
25884
  body.append(buildRow({ id: definition.id, kind: "builtin", title: t(definition.nameKey), description: t(definition.descriptionKey), favorite, count: metadata?.favoriteCount, hostedFavorite: metadata?.favorite !== void 0 || !!source3 && loading, actions: metadata?.actions ?? [], primary: () => add(definition), permitted: indicatorPermitted(deps.access, definition) && deps.commands.available("chart.indicators.add"), builtin: definition }));
25859
25885
  }
25860
25886
  }
25861
- if (collection !== "builtin") for (const item of rows2.items) {
25887
+ for (const item of rows2.items) {
25862
25888
  if (collection === "favorites" && item.favorite !== true) continue;
25863
25889
  if (!admitted(item.kind ?? INDICATOR_KIND)) continue;
25864
25890
  const primary = item.actions.find((action) => action.id === item.primaryAction);
25865
25891
  body.append(buildRow({ id: item.id, kind: "item", title: item.title, description: item.description, author: item.author, favorite: item.favorite, count: item.favoriteCount, hostedFavorite: true, actions: item.actions, primary: () => void act({ kind: "item", id: item.id }, primary.id), permitted: !busy && !loading && !primary.disabled }));
25866
25892
  }
25867
25893
  replace(list, headings, body);
25894
+ const filled = (cell2) => [...body.querySelectorAll(cell2)].some((node) => node.textContent !== "");
25895
+ list.classList.toggle("qc-picker-list--authors", filled(".qc-picker-author"));
25896
+ list.classList.toggle("qc-picker-list--counts", filled(".qc-picker-count"));
25897
+ const empty = selected?.empty && !loading && available && query.trim() === "" && rows2.items.length === 0 ? selected.empty : null;
25898
+ list.hidden = !!empty;
25899
+ vacant.hidden = !empty;
25900
+ strip.hidden = (kinds ?? []).length === 0 || !!empty;
25901
+ if (empty) {
25902
+ const action = empty.action;
25903
+ const mark = buildGlyph(empty.icon, 120);
25904
+ replace(
25905
+ vacant,
25906
+ mark ? h("span", { class: "qc-picker-empty-mark", "aria-hidden": "true" }, mark) : null,
25907
+ h("strong", { class: "qc-picker-empty-title" }, empty.title),
25908
+ empty.text ? h("p", { class: "qc-picker-empty-text" }, empty.text) : null,
25909
+ action ? button2({ label: action.label, text: action.label, className: "qc-button--primary qc-drawing-footer-button qc-picker-empty-action", disabled: busy || action.disabled === true, onClick: () => void act({ kind: "collection", id: collection }, action.id) }) : null
25910
+ );
25911
+ } else replace(vacant);
25868
25912
  if (pendingFocus) {
25869
25913
  const target = [...list.querySelectorAll("[data-picker-focus]")].find((button3) => button3.dataset.pickerFocus === pendingFocus);
25870
25914
  if (target && !target.disabled) target.focus();
@@ -25873,7 +25917,7 @@ function openIndicatorPicker(deps) {
25873
25917
  input.focus();
25874
25918
  }
25875
25919
  }
25876
- status2.textContent = error || (loading ? t("picker.loading") : body.childElementCount === 0 ? t("picker.noMatches") : "");
25920
+ status2.textContent = error || (loading ? t("picker.loading") : body.childElementCount === 0 && !empty ? t("picker.noMatches") : "");
25877
25921
  list.setAttribute("aria-busy", String(loading || busy));
25878
25922
  };
25879
25923
  const refresh = async () => {
@@ -25898,6 +25942,7 @@ function openIndicatorPicker(deps) {
25898
25942
  if (parsed) {
25899
25943
  rows2 = parsed;
25900
25944
  available = true;
25945
+ hostStarred = parsed.builtIns.some((row2) => row2.favorite === true) || parsed.items.some((item) => item.favorite === true);
25901
25946
  } else error = result?.kind === "unavailable" && typeof result.message === "string" && result.message.trim() ? result.message : t("picker.unavailable");
25902
25947
  } catch {
25903
25948
  if (dialog.open() && revision === generation) error = t("picker.unavailable");
@@ -25915,8 +25960,9 @@ function openIndicatorPicker(deps) {
25915
25960
  };
25916
25961
  const renderNavigation = () => {
25917
25962
  replace(nav);
25963
+ railFavorites = starred() || collection === "favorites";
25918
25964
  const personal = t("picker.personal");
25919
- const navigation = [{ id: "favorites", label: t("picker.favorites"), group: personal, icon: deps.icons.glyph(ICONS.pickerFavorites, { size: 28 }) }, ...(collections ?? []).map((row2) => ({ ...row2, icon: hostIcon(row2.icon) })), { id: "builtin", label: t("picker.technicals"), group: t("picker.builtin"), icon: deps.icons.glyph(ICONS.pickerTechnicals, { size: 28 }) }];
25965
+ const navigation = [...railFavorites ? [{ id: "favorites", label: t("picker.favorites"), group: personal, icon: deps.icons.glyph(ICONS.pickerFavorites, { size: 28 }) }] : [], ...(collections ?? []).map((row2) => ({ ...row2, icon: hostIcon(row2.icon) })), { id: "builtin", label: t("picker.technicals"), group: t("picker.builtin"), icon: deps.icons.glyph(ICONS.pickerTechnicals, { size: 28 }) }];
25920
25966
  let section = null;
25921
25967
  let group;
25922
25968
  for (const item of navigation) {
@@ -25958,7 +26004,7 @@ function openIndicatorPicker(deps) {
25958
26004
  input.focus();
25959
26005
  } else if (roveFocus(list, event)) event.preventDefault();
25960
26006
  });
25961
- box2.append(searchField(deps.icons, input, clear), strip, h("div", { class: "qc-picker-body" }, nav, h("div", { class: "qc-picker-content" }, list, status2)));
26007
+ box2.append(searchField(deps.icons, input, clear), strip, h("div", { class: "qc-picker-body" }, nav, h("div", { class: "qc-picker-content" }, list, vacant, status2)));
25962
26008
  renderKinds();
25963
26009
  renderNavigation();
25964
26010
  redraw = render;
@@ -30256,9 +30302,9 @@ function mountChrome(deps) {
30256
30302
  });
30257
30303
  deps.doors.notify = notify;
30258
30304
  let indicatorDialog = null;
30259
- deps.doors.showIndicatorPicker = (initialCollection) => {
30305
+ deps.doors.showIndicatorPicker = (initialCollection, initialKind) => {
30260
30306
  if (!ui.indicatorPicker || indicatorDialog?.open()) return;
30261
- indicatorDialog = openIndicatorPicker({ ...ctx, storage: deps.storage, indicatorPicker: deps.indicatorPicker, initialCollection });
30307
+ indicatorDialog = openIndicatorPicker({ ...ctx, storage: deps.storage, indicatorPicker: deps.indicatorPicker, initialCollection, initialKind });
30262
30308
  };
30263
30309
  disposers.push(() => {
30264
30310
  indicatorDialog?.close({ animate: false });