@trdrs/quickcharts 5.4.0 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 5.5.0
6
+
7
+ 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.
8
+
5
9
  ## 5.4.0
6
10
 
7
11
  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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.4.0",
2
+ "version": "5.5.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;
@@ -6612,4 +6627,4 @@ declare function mountTimeframePicker(options: TimeframePickerOptions & {
6612
6627
  container: HTMLElement;
6613
6628
  }): MountedTimeframePicker;
6614
6629
 
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 };
6630
+ 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");
@@ -21072,7 +21072,13 @@ function registerChartCommands(deps) {
21072
21072
  scope: "chart",
21073
21073
  label: "chrome.indicators",
21074
21074
  available: () => ui.indicatorPicker,
21075
- execute: (arg) => deps.indicatorsOpen(arg && typeof arg === "object" && "collection" in arg && typeof arg.collection === "string" ? arg.collection : void 0)
21075
+ execute: (arg) => {
21076
+ const field = (key) => {
21077
+ const value = arg && typeof arg === "object" ? arg[key] : void 0;
21078
+ return typeof value === "string" ? value : void 0;
21079
+ };
21080
+ return deps.indicatorsOpen(field("collection"), field("kind"));
21081
+ }
21076
21082
  });
21077
21083
  const isInstance = (arg) => !!arg && typeof arg === "object" && typeof arg.id === "string" && typeof arg.definition === "object";
21078
21084
  add({
@@ -23821,7 +23827,7 @@ function createChartInstance(deps) {
23821
23827
  crosshairLevel,
23822
23828
  formatter: () => symbolFormatter,
23823
23829
  compareOpen: (mode, changeFrom) => compare?.openDialog(mode, changeFrom),
23824
- indicatorsOpen: (collection) => deps.doors.showIndicatorPicker(collection),
23830
+ indicatorsOpen: (collection, kind) => deps.doors.showIndicatorPicker(collection, kind),
23825
23831
  symbolSearchOpen: () => deps.doors.openSearch({ mode: "search", chart: handle }),
23826
23832
  drawingVerbs: () => drawings2.verbs
23827
23833
  });
@@ -25596,13 +25602,21 @@ function actions(value) {
25596
25602
  }
25597
25603
  return unique(result.map((a) => a.id)) ? result : null;
25598
25604
  }
25605
+ function emptyState2(value) {
25606
+ if (!record2(value) || !text(value.title) || !optionalText(value.text)) return null;
25607
+ const action = value.action === void 0 ? [] : actions([value.action]);
25608
+ if (!action) return null;
25609
+ return { title: value.title, ...value.text !== void 0 ? { text: value.text } : {}, ...value.icon !== void 0 ? { icon: value.icon } : {}, ...action[0] ? { action: action[0] } : {} };
25610
+ }
25599
25611
  function pickerCollections(value) {
25600
25612
  try {
25601
25613
  if (!Array.isArray(value)) return null;
25602
25614
  const result = [];
25603
25615
  for (const row2 of value) {
25604
25616
  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 } : {} });
25617
+ const empty = row2.empty === void 0 ? void 0 : emptyState2(row2.empty);
25618
+ if (empty === null) return null;
25619
+ 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
25620
  }
25607
25621
  return unique(result.map((row2) => row2.id)) ? result : null;
25608
25622
  } catch {
@@ -25703,8 +25717,10 @@ function openIndicatorPicker(deps) {
25703
25717
  } catch {
25704
25718
  }
25705
25719
  let query = "";
25706
- let collection = deps.initialCollection === "favorites" || collections?.some((row2) => row2.id === deps.initialCollection) ? deps.initialCollection : "builtin";
25707
- let kind = null;
25720
+ let hostStarred = false;
25721
+ const starred = () => favorites.length > 0 || hostStarred;
25722
+ let collection = deps.initialCollection === "favorites" && starred() || collections?.some((row2) => row2.id === deps.initialCollection) ? deps.initialCollection : "builtin";
25723
+ let kind = deps.initialKind ?? null;
25708
25724
  let generation = 0;
25709
25725
  let controller = null;
25710
25726
  let busy = false;
@@ -25744,6 +25760,9 @@ function openIndicatorPicker(deps) {
25744
25760
  const strip = h("div", { class: "qc-search-classes" });
25745
25761
  const nav = h("nav", { class: "qc-picker-nav", "aria-label": t("picker.collections") });
25746
25762
  const list = h("div", { class: "qc-picker-list", role: "table", "aria-label": t("picker.title") });
25763
+ const vacant = h("div", { class: "qc-picker-empty" });
25764
+ vacant.hidden = true;
25765
+ let railFavorites = false;
25747
25766
  const status2 = h("div", { class: "qc-picker-status qc-secondary", role: "status", "aria-live": "polite" });
25748
25767
  let pendingFocus = null;
25749
25768
  const actionButton = (label3, content, run, disabled = false, focusKey, className = "qc-picker-action") => {
@@ -25843,7 +25862,7 @@ function openIndicatorPicker(deps) {
25843
25862
  else if (focused && focused !== document.body) pendingFocus = null;
25844
25863
  const selected = (collections ?? []).find((row2) => row2.id === collection);
25845
25864
  list.classList.toggle("qc-picker-list--personal", selected?.layout === "list");
25846
- list.classList.toggle("qc-picker-list--catalog", collection === "builtin");
25865
+ if (railFavorites !== (starred() || collection === "favorites")) renderNavigation();
25847
25866
  for (const button3 of nav.querySelectorAll("[data-picker-collection]")) button3.setAttribute("aria-pressed", String(button3.getAttribute("data-picker-collection") === collection));
25848
25867
  for (const chip of strip.querySelectorAll("[data-picker-kind]")) chip.setAttribute("aria-pressed", String((chip.getAttribute("data-picker-kind") || null) === kind));
25849
25868
  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 +25877,31 @@ function openIndicatorPicker(deps) {
25858
25877
  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
25878
  }
25860
25879
  }
25861
- if (collection !== "builtin") for (const item of rows2.items) {
25880
+ for (const item of rows2.items) {
25862
25881
  if (collection === "favorites" && item.favorite !== true) continue;
25863
25882
  if (!admitted(item.kind ?? INDICATOR_KIND)) continue;
25864
25883
  const primary = item.actions.find((action) => action.id === item.primaryAction);
25865
25884
  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
25885
  }
25867
25886
  replace(list, headings, body);
25887
+ const filled = (cell2) => [...body.querySelectorAll(cell2)].some((node) => node.textContent !== "");
25888
+ list.classList.toggle("qc-picker-list--authors", filled(".qc-picker-author"));
25889
+ list.classList.toggle("qc-picker-list--counts", filled(".qc-picker-count"));
25890
+ const empty = selected?.empty && !loading && available && query.trim() === "" && rows2.items.length === 0 ? selected.empty : null;
25891
+ list.hidden = !!empty;
25892
+ vacant.hidden = !empty;
25893
+ strip.hidden = (kinds ?? []).length === 0 || !!empty;
25894
+ if (empty) {
25895
+ const action = empty.action;
25896
+ const mark = buildGlyph(empty.icon, 120);
25897
+ replace(
25898
+ vacant,
25899
+ mark ? h("span", { class: "qc-picker-empty-mark", "aria-hidden": "true" }, mark) : null,
25900
+ h("strong", { class: "qc-picker-empty-title" }, empty.title),
25901
+ empty.text ? h("p", { class: "qc-picker-empty-text" }, empty.text) : null,
25902
+ 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
25903
+ );
25904
+ } else replace(vacant);
25868
25905
  if (pendingFocus) {
25869
25906
  const target = [...list.querySelectorAll("[data-picker-focus]")].find((button3) => button3.dataset.pickerFocus === pendingFocus);
25870
25907
  if (target && !target.disabled) target.focus();
@@ -25873,7 +25910,7 @@ function openIndicatorPicker(deps) {
25873
25910
  input.focus();
25874
25911
  }
25875
25912
  }
25876
- status2.textContent = error || (loading ? t("picker.loading") : body.childElementCount === 0 ? t("picker.noMatches") : "");
25913
+ status2.textContent = error || (loading ? t("picker.loading") : body.childElementCount === 0 && !empty ? t("picker.noMatches") : "");
25877
25914
  list.setAttribute("aria-busy", String(loading || busy));
25878
25915
  };
25879
25916
  const refresh = async () => {
@@ -25898,6 +25935,7 @@ function openIndicatorPicker(deps) {
25898
25935
  if (parsed) {
25899
25936
  rows2 = parsed;
25900
25937
  available = true;
25938
+ hostStarred = parsed.builtIns.some((row2) => row2.favorite === true) || parsed.items.some((item) => item.favorite === true);
25901
25939
  } else error = result?.kind === "unavailable" && typeof result.message === "string" && result.message.trim() ? result.message : t("picker.unavailable");
25902
25940
  } catch {
25903
25941
  if (dialog.open() && revision === generation) error = t("picker.unavailable");
@@ -25915,8 +25953,9 @@ function openIndicatorPicker(deps) {
25915
25953
  };
25916
25954
  const renderNavigation = () => {
25917
25955
  replace(nav);
25956
+ railFavorites = starred() || collection === "favorites";
25918
25957
  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 }) }];
25958
+ 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
25959
  let section = null;
25921
25960
  let group;
25922
25961
  for (const item of navigation) {
@@ -25958,7 +25997,7 @@ function openIndicatorPicker(deps) {
25958
25997
  input.focus();
25959
25998
  } else if (roveFocus(list, event)) event.preventDefault();
25960
25999
  });
25961
- box2.append(searchField(deps.icons, input, clear), strip, h("div", { class: "qc-picker-body" }, nav, h("div", { class: "qc-picker-content" }, list, status2)));
26000
+ 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
26001
  renderKinds();
25963
26002
  renderNavigation();
25964
26003
  redraw = render;
@@ -30256,9 +30295,9 @@ function mountChrome(deps) {
30256
30295
  });
30257
30296
  deps.doors.notify = notify;
30258
30297
  let indicatorDialog = null;
30259
- deps.doors.showIndicatorPicker = (initialCollection) => {
30298
+ deps.doors.showIndicatorPicker = (initialCollection, initialKind) => {
30260
30299
  if (!ui.indicatorPicker || indicatorDialog?.open()) return;
30261
- indicatorDialog = openIndicatorPicker({ ...ctx, storage: deps.storage, indicatorPicker: deps.indicatorPicker, initialCollection });
30300
+ indicatorDialog = openIndicatorPicker({ ...ctx, storage: deps.storage, indicatorPicker: deps.indicatorPicker, initialCollection, initialKind });
30262
30301
  };
30263
30302
  disposers.push(() => {
30264
30303
  indicatorDialog?.close({ animate: false });