@matchstick-trading/primitives 0.0.10
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/AGENTS.md +44 -0
- package/CHANGELOG.md +19 -0
- package/LICENSE +201 -0
- package/README.md +636 -0
- package/dist/Chart.d.ts +18 -0
- package/dist/Chart.js +6 -0
- package/dist/ChartParts.d.ts +151 -0
- package/dist/ChartParts.js +389 -0
- package/dist/CsvDrop.d.ts +8 -0
- package/dist/CsvDrop.js +5 -0
- package/dist/CsvDropParts.d.ts +33 -0
- package/dist/CsvDropParts.js +77 -0
- package/dist/Cursor.d.ts +6 -0
- package/dist/Cursor.js +5 -0
- package/dist/CursorParts.d.ts +51 -0
- package/dist/CursorParts.js +40 -0
- package/dist/DepthProfile.d.ts +13 -0
- package/dist/DepthProfile.js +5 -0
- package/dist/DepthProfileParts.d.ts +45 -0
- package/dist/DepthProfileParts.js +96 -0
- package/dist/DiffTable.d.ts +13 -0
- package/dist/DiffTable.js +5 -0
- package/dist/DiffTableParts.d.ts +57 -0
- package/dist/DiffTableParts.js +103 -0
- package/dist/Drawings.d.ts +13 -0
- package/dist/Drawings.js +5 -0
- package/dist/DrawingsParts.d.ts +194 -0
- package/dist/DrawingsParts.js +775 -0
- package/dist/Fullscreen.d.ts +7 -0
- package/dist/Fullscreen.js +5 -0
- package/dist/FullscreenParts.d.ts +54 -0
- package/dist/FullscreenParts.js +250 -0
- package/dist/Ladder.d.ts +13 -0
- package/dist/Ladder.js +5 -0
- package/dist/LadderParts.d.ts +49 -0
- package/dist/LadderParts.js +56 -0
- package/dist/Menu.d.ts +11 -0
- package/dist/Menu.js +5 -0
- package/dist/MenuParts.d.ts +52 -0
- package/dist/MenuParts.js +202 -0
- package/dist/Notice.d.ts +18 -0
- package/dist/Notice.js +9 -0
- package/dist/Panels.d.ts +9 -0
- package/dist/Panels.js +5 -0
- package/dist/PanelsParts.d.ts +62 -0
- package/dist/PanelsParts.js +387 -0
- package/dist/Receipt.d.ts +11 -0
- package/dist/Receipt.js +5 -0
- package/dist/ReceiptParts.d.ts +45 -0
- package/dist/ReceiptParts.js +71 -0
- package/dist/Scrubber.d.ts +9 -0
- package/dist/Scrubber.js +5 -0
- package/dist/ScrubberParts.d.ts +74 -0
- package/dist/ScrubberParts.js +126 -0
- package/dist/Selection.d.ts +14 -0
- package/dist/Selection.js +7 -0
- package/dist/SelectionParts.d.ts +63 -0
- package/dist/SelectionParts.js +208 -0
- package/dist/Studies.d.ts +9 -0
- package/dist/Studies.js +5 -0
- package/dist/StudiesParts.d.ts +45 -0
- package/dist/StudiesParts.js +153 -0
- package/dist/Submenu.d.ts +7 -0
- package/dist/Submenu.js +4 -0
- package/dist/SymbolSearch.d.ts +10 -0
- package/dist/SymbolSearch.js +5 -0
- package/dist/SymbolSearchParts.d.ts +39 -0
- package/dist/SymbolSearchParts.js +86 -0
- package/dist/Tape.d.ts +15 -0
- package/dist/Tape.js +5 -0
- package/dist/TapeParts.d.ts +69 -0
- package/dist/TapeParts.js +139 -0
- package/dist/Toolbar.d.ts +8 -0
- package/dist/Toolbar.js +5 -0
- package/dist/ToolbarParts.d.ts +61 -0
- package/dist/ToolbarParts.js +122 -0
- package/dist/Transport.d.ts +15 -0
- package/dist/Transport.js +5 -0
- package/dist/TransportParts.d.ts +52 -0
- package/dist/TransportParts.js +47 -0
- package/dist/VolumeProfile.d.ts +7 -0
- package/dist/VolumeProfile.js +5 -0
- package/dist/VolumeProfileParts.d.ts +37 -0
- package/dist/VolumeProfileParts.js +57 -0
- package/dist/accessible-name.d.ts +26 -0
- package/dist/accessible-name.js +14 -0
- package/dist/attributes.d.ts +8 -0
- package/dist/attributes.js +9 -0
- package/dist/core/adapter.d.ts +38 -0
- package/dist/core/adapter.js +64 -0
- package/dist/core/attributes.d.ts +36 -0
- package/dist/core/attributes.js +22 -0
- package/dist/core/candles.d.ts +6 -0
- package/dist/core/candles.js +19 -0
- package/dist/core/chart-gesture.d.ts +109 -0
- package/dist/core/chart-gesture.js +161 -0
- package/dist/core/chart-scale.d.ts +141 -0
- package/dist/core/chart-scale.js +302 -0
- package/dist/core/csv-bars.d.ts +54 -0
- package/dist/core/csv-bars.js +325 -0
- package/dist/core/depth-profile.d.ts +43 -0
- package/dist/core/depth-profile.js +66 -0
- package/dist/core/diff-table.d.ts +57 -0
- package/dist/core/diff-table.js +77 -0
- package/dist/core/drawing-fields.d.ts +11 -0
- package/dist/core/drawing-fields.js +15 -0
- package/dist/core/drawings.d.ts +194 -0
- package/dist/core/drawings.js +403 -0
- package/dist/core/fullscreen.d.ts +32 -0
- package/dist/core/fullscreen.js +16 -0
- package/dist/core/index.d.ts +41 -0
- package/dist/core/index.js +23 -0
- package/dist/core/ladder-keys.d.ts +35 -0
- package/dist/core/ladder-keys.js +43 -0
- package/dist/core/ladder.d.ts +65 -0
- package/dist/core/ladder.js +93 -0
- package/dist/core/panels.d.ts +72 -0
- package/dist/core/panels.js +151 -0
- package/dist/core/receipt-rules.d.ts +42 -0
- package/dist/core/receipt-rules.js +20 -0
- package/dist/core/scrubber-gesture.d.ts +66 -0
- package/dist/core/scrubber-gesture.js +69 -0
- package/dist/core/selection.d.ts +24 -0
- package/dist/core/selection.js +33 -0
- package/dist/core/series.d.ts +161 -0
- package/dist/core/series.js +331 -0
- package/dist/core/studies.d.ts +80 -0
- package/dist/core/studies.js +237 -0
- package/dist/core/symbol-search.d.ts +89 -0
- package/dist/core/symbol-search.js +223 -0
- package/dist/core/tape.d.ts +77 -0
- package/dist/core/tape.js +136 -0
- package/dist/core/volume-profile.d.ts +47 -0
- package/dist/core/volume-profile.js +86 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +42 -0
- package/dist/ladder-keys.d.ts +16 -0
- package/dist/ladder-keys.js +86 -0
- package/dist/panels-context.d.ts +47 -0
- package/dist/panels-context.js +3 -0
- package/dist/selection-context.d.ts +41 -0
- package/dist/selection-context.js +4 -0
- package/examples/csv-to-chart-frame.mjs +17 -0
- package/examples/studies.mjs +12 -0
- package/llms.txt +16 -0
- package/package.json +67 -0
- package/src/Chart.tsx +7 -0
- package/src/ChartParts.tsx +529 -0
- package/src/CsvDrop.tsx +6 -0
- package/src/CsvDropParts.tsx +128 -0
- package/src/Cursor.tsx +6 -0
- package/src/CursorParts.tsx +77 -0
- package/src/DepthProfile.tsx +6 -0
- package/src/DepthProfileParts.tsx +154 -0
- package/src/DiffTable.tsx +6 -0
- package/src/DiffTableParts.tsx +160 -0
- package/src/Drawings.tsx +6 -0
- package/src/DrawingsParts.tsx +1080 -0
- package/src/Fullscreen.tsx +6 -0
- package/src/FullscreenParts.tsx +318 -0
- package/src/Ladder.tsx +6 -0
- package/src/LadderParts.tsx +114 -0
- package/src/Menu.tsx +6 -0
- package/src/MenuParts.tsx +364 -0
- package/src/Notice.tsx +27 -0
- package/src/Panels.tsx +6 -0
- package/src/PanelsParts.tsx +454 -0
- package/src/Receipt.tsx +6 -0
- package/src/ReceiptParts.tsx +118 -0
- package/src/Scrubber.tsx +6 -0
- package/src/ScrubberParts.tsx +207 -0
- package/src/Selection.tsx +12 -0
- package/src/SelectionParts.tsx +251 -0
- package/src/Studies.tsx +6 -0
- package/src/StudiesParts.tsx +226 -0
- package/src/Submenu.tsx +5 -0
- package/src/SymbolSearch.tsx +6 -0
- package/src/SymbolSearchParts.tsx +166 -0
- package/src/Tape.tsx +6 -0
- package/src/TapeParts.tsx +208 -0
- package/src/Toolbar.tsx +6 -0
- package/src/ToolbarParts.tsx +179 -0
- package/src/Transport.tsx +6 -0
- package/src/TransportParts.tsx +128 -0
- package/src/VolumeProfile.tsx +6 -0
- package/src/VolumeProfileParts.tsx +106 -0
- package/src/accessible-name.tsx +34 -0
- package/src/attributes.ts +12 -0
- package/src/core/adapter.ts +91 -0
- package/src/core/attributes.ts +51 -0
- package/src/core/candles.ts +22 -0
- package/src/core/chart-gesture.ts +228 -0
- package/src/core/chart-scale.ts +368 -0
- package/src/core/csv-bars.ts +328 -0
- package/src/core/depth-profile.ts +84 -0
- package/src/core/diff-table.ts +105 -0
- package/src/core/drawing-fields.ts +17 -0
- package/src/core/drawings.ts +478 -0
- package/src/core/fullscreen.ts +32 -0
- package/src/core/index.ts +42 -0
- package/src/core/ladder-keys.ts +61 -0
- package/src/core/ladder.ts +156 -0
- package/src/core/panels.ts +177 -0
- package/src/core/receipt-rules.ts +45 -0
- package/src/core/scrubber-gesture.ts +102 -0
- package/src/core/selection.ts +41 -0
- package/src/core/series.ts +374 -0
- package/src/core/studies.ts +260 -0
- package/src/core/symbol-search.ts +256 -0
- package/src/core/tape.ts +159 -0
- package/src/core/volume-profile.ts +116 -0
- package/src/index.ts +83 -0
- package/src/ladder-keys.ts +83 -0
- package/src/panels-context.ts +46 -0
- package/src/selection-context.ts +38 -0
- package/src/tokens.css +235 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export { numericWidth, primitiveAttributes } from './attributes.js';
|
|
2
|
+
export type { Change, CursorMark, DiffStatus, PrimitiveAttributes, PrimitiveState, Quality, Side } from './attributes.js';
|
|
3
|
+
export { Notice } from './Notice.js';
|
|
4
|
+
export type { NoticeKind, NoticeProps } from './Notice.js';
|
|
5
|
+
export { useLadderKeys } from './ladder-keys.js';
|
|
6
|
+
export { LADDER_ROW_ATTRIBUTE, nextLadderRow, resolveLadderKey } from './core/ladder-keys.js';
|
|
7
|
+
export type { LadderKeyAction } from './ladder-keys.js';
|
|
8
|
+
export { Transport } from './Transport.js';
|
|
9
|
+
export type { TransportRootProps, TransportSpeedProps } from './Transport.js';
|
|
10
|
+
export { CURSOR_START, Cursor, sameCursor, useCursor } from './Cursor.js';
|
|
11
|
+
export type { CursorBoundary, CursorRootProps, CursorState, CursorValue } from './Cursor.js';
|
|
12
|
+
export { Scrubber, useScrubber } from './Scrubber.js';
|
|
13
|
+
export type { ScrubberMarkProps, ScrubberRootProps, ScrubberThumbProps } from './Scrubber.js';
|
|
14
|
+
export { clampFraction, fractionFromPointer, isActiveScrubPointer, isPrimaryScrubPointer, reduceScrubGesture, resolveScrubKey } from './core/scrubber-gesture.js';
|
|
15
|
+
export type { ScrubGestureEvent, ScrubGestureResult, ScrubKeyAction, ScrubPointer } from './core/scrubber-gesture.js';
|
|
16
|
+
export { DepthProfile } from './DepthProfile.js';
|
|
17
|
+
export type { DepthProfileRootProps } from './DepthProfile.js';
|
|
18
|
+
export { depthGeometry, depthLevelId, nextDepthIndex, resolveDepthKey } from './core/depth-profile.js';
|
|
19
|
+
export type { DepthGeometry, DepthKeyAction, DepthLevel } from './core/depth-profile.js';
|
|
20
|
+
export { DiffTable } from './DiffTable.js';
|
|
21
|
+
export type { DiffTableRootProps } from './DiffTable.js';
|
|
22
|
+
export { DIFF_CHANGE_LABEL, compareExact, diffRowId, holdDiffOrder, nextDiffIndex, nextDiffSort, resolveDiffKey, signedDelta, sortDiffRows } from './core/diff-table.js';
|
|
23
|
+
export type { DiffChange, DiffKeyAction, DiffMove, DiffSort, DiffTableRow } from './core/diff-table.js';
|
|
24
|
+
export { Tape } from './Tape.js';
|
|
25
|
+
export type { TapeRootProps } from './Tape.js';
|
|
26
|
+
export { TAPE_SIDE_LABEL, holdTape, newestFirst, nextTapeIndex, readTape, resolveTapeKey, tapeSummary, tapeTime } from './core/tape.js';
|
|
27
|
+
export type { TapeIssue, TapeKeyAction, TapeMove, TapeRead, TapeRow, TapeSide, TapeTrade } from './core/tape.js';
|
|
28
|
+
export { Ladder } from './Ladder.js';
|
|
29
|
+
export type { LadderRootProps } from './Ladder.js';
|
|
30
|
+
export { buildLadder } from './core/ladder.js';
|
|
31
|
+
export type { LadderBuilt, LadderInput, LadderIssue, LadderLevelIn, LadderRow, LadderSide } from './core/ladder.js';
|
|
32
|
+
export { Receipt } from './Receipt.js';
|
|
33
|
+
export type { ReceiptRootProps } from './Receipt.js';
|
|
34
|
+
export { receiptHash, receiptVerdict, resolveReceiptKey } from './core/receipt-rules.js';
|
|
35
|
+
export type { ReceiptData, ReceiptHashOf, ReceiptVerdict } from './core/receipt-rules.js';
|
|
36
|
+
export { SymbolSearch } from './SymbolSearch.js';
|
|
37
|
+
export type { SymbolSearchRootProps } from './SymbolSearch.js';
|
|
38
|
+
export { buildSymbolIndex, nextSymbolIndex, normalizeSymbolText, resolveSymbolKey, searchSymbols } from './core/symbol-search.js';
|
|
39
|
+
export type { Instrument, MatchHow, MatchedOn, SearchOptions, SymbolIndex, SymbolKeyAction, SymbolMatch } from './core/symbol-search.js';
|
|
40
|
+
export { Chart, useChart } from './Chart.js';
|
|
41
|
+
export { heikinAshi } from './core/candles.js';
|
|
42
|
+
export type { CandleStyle, ChartContext, ChartRootProps, TimeAxisProps } from './Chart.js';
|
|
43
|
+
export { barInterval, chartFrame, clampPriceRange, dataPriceSpan, growViewport, indexOfTime, lastBars, panPriceRange, panViewport, priceTicks, resolveChartKey, tickDecimals, timeOfIndex, zoomPriceRange, zoomViewport } from './core/chart-scale.js';
|
|
44
|
+
export type { CandleBar, ChartFrame, ChartFrameOptions, ChartInclude, PriceSpan, ChartKeyAction, ChartSize, ChartViewport } from './core/chart-scale.js';
|
|
45
|
+
export { Study } from './Studies.js';
|
|
46
|
+
export type { StudyBandProps, StudyLegendProps, StudyLineProps } from './Studies.js';
|
|
47
|
+
export { atr, bollinger, ema, rsi, sma, sourcePrice, studyRange, visibleIndexes, vwap, wma } from './core/studies.js';
|
|
48
|
+
export type { BollingerBands, StudySource, VwapBand, VwapOptions, VwapResult } from './core/studies.js';
|
|
49
|
+
export { VolumeProfile } from './VolumeProfile.js';
|
|
50
|
+
export type { VolumeProfileHistogramProps, VolumeProfileOptionsProps } from './VolumeProfile.js';
|
|
51
|
+
export { indexRangeOfTime, volumeProfile } from './core/volume-profile.js';
|
|
52
|
+
export type { ProfileRow, VolumeProfileOptions, VolumeProfileResult } from './core/volume-profile.js';
|
|
53
|
+
export type { NameProps } from './accessible-name.js';
|
|
54
|
+
export { Toolbar } from './Toolbar.js';
|
|
55
|
+
export type { ToolbarButtonProps, ToolbarRootProps } from './Toolbar.js';
|
|
56
|
+
export { Menu } from './Menu.js';
|
|
57
|
+
export type { MenuItemProps, MenuListProps, MenuRadioItemProps, MenuRootProps, MenuTriggerProps } from './Menu.js';
|
|
58
|
+
export { Submenu } from './Submenu.js';
|
|
59
|
+
export { Drawings, useDrawings } from './Drawings.js';
|
|
60
|
+
export type { DrawingsEditProps, DrawingsListProps, DrawingsLockProps, DrawingsRemoveProps, DrawingsRootProps, DrawingsToolbarProps, DrawingsUndoProps } from './Drawings.js';
|
|
61
|
+
export { ATTACH_LABELS, ATTACH_MODES, DRAWING_TOOLS, DRAWING_TOOL_LABELS, FIB_RATIOS, anchorCount, attachOf, barTime, barsFromFirst, barsFromLast, timeOfBarFromLast, describeAnchor, describeDrawing, drawingGeometry, drawingPriceRanges, editDrawing, hitTest, moveAnchor, moveDrawing, nextDrawingId, nudgeAmount, resolveDrawingKey, snapToBar } from './core/drawings.js';
|
|
62
|
+
export type { AttachMode, Drawing, DrawingAnchor, DrawingGeometry, DrawingHit, DrawingKeyAction, DrawingTool, SnapMode } from './core/drawings.js';
|
|
63
|
+
export { Selection, Series } from './Selection.js';
|
|
64
|
+
export type { SelectionRootProps, SeriesRootProps } from './SelectionParts.js';
|
|
65
|
+
export { describeSelection, sameSelection, selectionAfterClearTap, selectionAfterEscape, selectionAfterTap } from './core/selection.js';
|
|
66
|
+
export type { ChartSelection, SelectionNames } from './core/selection.js';
|
|
67
|
+
export { CsvDrop } from './CsvDrop.js';
|
|
68
|
+
export type { CsvDropLoad, CsvDropRootProps } from './CsvDrop.js';
|
|
69
|
+
export { describeBarsCsv, parseBarsCsv } from './core/csv-bars.js';
|
|
70
|
+
export type { CsvBarsError, CsvBarsNote, CsvBarsOptions, CsvBarsResult, CsvExtraColumn } from './core/csv-bars.js';
|
|
71
|
+
export { Fullscreen, useFullscreen } from './Fullscreen.js';
|
|
72
|
+
export type { FullscreenFrameProps, FullscreenState, FullscreenToggleProps } from './Fullscreen.js';
|
|
73
|
+
export { FULLSCREEN_LABEL, FULLSCREEN_MESSAGE, resolveFullscreenEscape } from './core/fullscreen.js';
|
|
74
|
+
export type { FullscreenEscape } from './core/fullscreen.js';
|
|
75
|
+
export { Panels, usePanels } from './Panels.js';
|
|
76
|
+
export type { PanelsListProps, PanelsMoveProps, PanelsRootProps } from './PanelsParts.js';
|
|
77
|
+
export type { PanelSeriesData } from './panels-context.js';
|
|
78
|
+
export { AXIS_BOTTOM, MAIN_PANEL, describeMove, moveSeries, moveTargets, normalizeLayout, panelBands, panelOf, reconcileLayout } from './core/panels.js';
|
|
79
|
+
export type { MoveDestination, MoveTarget, PanelBand, PanelLayout, PanelSeriesRequest, PanelSpec } from './core/panels.js';
|
|
80
|
+
export { POINT_KINDS, alignSeries, csvAdapter, duplicateIds, pointsFromValues, report, resolveSeries, seriesSetSchema, toSeriesSet, validateSeriesSet } from './core/index.js';
|
|
81
|
+
export type { AdapterIssue, AdapterResult, AlignMode, AlignOptions, AlignedSeries, AlignedState, CsvAdapterOptions, DataAdapter, DataSeries, FindingKind, PointKind, ResolvedSeries, SeriesCalendar, SeriesFinding, SeriesInput, SeriesIssue, SeriesPoint, SeriesSet, SeriesValidation } from './core/index.js';
|
|
82
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export { numericWidth, primitiveAttributes } from './attributes.js';
|
|
2
|
+
export { Notice } from './Notice.js';
|
|
3
|
+
export { useLadderKeys } from './ladder-keys.js';
|
|
4
|
+
export { LADDER_ROW_ATTRIBUTE, nextLadderRow, resolveLadderKey } from './core/ladder-keys.js';
|
|
5
|
+
export { Transport } from './Transport.js';
|
|
6
|
+
export { CURSOR_START, Cursor, sameCursor, useCursor } from './Cursor.js';
|
|
7
|
+
export { Scrubber, useScrubber } from './Scrubber.js';
|
|
8
|
+
export { clampFraction, fractionFromPointer, isActiveScrubPointer, isPrimaryScrubPointer, reduceScrubGesture, resolveScrubKey } from './core/scrubber-gesture.js';
|
|
9
|
+
export { DepthProfile } from './DepthProfile.js';
|
|
10
|
+
export { depthGeometry, depthLevelId, nextDepthIndex, resolveDepthKey } from './core/depth-profile.js';
|
|
11
|
+
export { DiffTable } from './DiffTable.js';
|
|
12
|
+
export { DIFF_CHANGE_LABEL, compareExact, diffRowId, holdDiffOrder, nextDiffIndex, nextDiffSort, resolveDiffKey, signedDelta, sortDiffRows } from './core/diff-table.js';
|
|
13
|
+
export { Tape } from './Tape.js';
|
|
14
|
+
export { TAPE_SIDE_LABEL, holdTape, newestFirst, nextTapeIndex, readTape, resolveTapeKey, tapeSummary, tapeTime } from './core/tape.js';
|
|
15
|
+
export { Ladder } from './Ladder.js';
|
|
16
|
+
export { buildLadder } from './core/ladder.js';
|
|
17
|
+
export { Receipt } from './Receipt.js';
|
|
18
|
+
export { receiptHash, receiptVerdict, resolveReceiptKey } from './core/receipt-rules.js';
|
|
19
|
+
export { SymbolSearch } from './SymbolSearch.js';
|
|
20
|
+
export { buildSymbolIndex, nextSymbolIndex, normalizeSymbolText, resolveSymbolKey, searchSymbols } from './core/symbol-search.js';
|
|
21
|
+
export { Chart, useChart } from './Chart.js';
|
|
22
|
+
export { heikinAshi } from './core/candles.js';
|
|
23
|
+
export { barInterval, chartFrame, clampPriceRange, dataPriceSpan, growViewport, indexOfTime, lastBars, panPriceRange, panViewport, priceTicks, resolveChartKey, tickDecimals, timeOfIndex, zoomPriceRange, zoomViewport } from './core/chart-scale.js';
|
|
24
|
+
export { Study } from './Studies.js';
|
|
25
|
+
export { atr, bollinger, ema, rsi, sma, sourcePrice, studyRange, visibleIndexes, vwap, wma } from './core/studies.js';
|
|
26
|
+
export { VolumeProfile } from './VolumeProfile.js';
|
|
27
|
+
export { indexRangeOfTime, volumeProfile } from './core/volume-profile.js';
|
|
28
|
+
export { Toolbar } from './Toolbar.js';
|
|
29
|
+
export { Menu } from './Menu.js';
|
|
30
|
+
export { Submenu } from './Submenu.js';
|
|
31
|
+
export { Drawings, useDrawings } from './Drawings.js';
|
|
32
|
+
export { ATTACH_LABELS, ATTACH_MODES, DRAWING_TOOLS, DRAWING_TOOL_LABELS, FIB_RATIOS, anchorCount, attachOf, barTime, barsFromFirst, barsFromLast, timeOfBarFromLast, describeAnchor, describeDrawing, drawingGeometry, drawingPriceRanges, editDrawing, hitTest, moveAnchor, moveDrawing, nextDrawingId, nudgeAmount, resolveDrawingKey, snapToBar } from './core/drawings.js';
|
|
33
|
+
export { Selection, Series } from './Selection.js';
|
|
34
|
+
export { describeSelection, sameSelection, selectionAfterClearTap, selectionAfterEscape, selectionAfterTap } from './core/selection.js';
|
|
35
|
+
export { CsvDrop } from './CsvDrop.js';
|
|
36
|
+
export { describeBarsCsv, parseBarsCsv } from './core/csv-bars.js';
|
|
37
|
+
export { Fullscreen, useFullscreen } from './Fullscreen.js';
|
|
38
|
+
export { FULLSCREEN_LABEL, FULLSCREEN_MESSAGE, resolveFullscreenEscape } from './core/fullscreen.js';
|
|
39
|
+
export { Panels, usePanels } from './Panels.js';
|
|
40
|
+
export { AXIS_BOTTOM, MAIN_PANEL, describeMove, moveSeries, moveTargets, normalizeLayout, panelBands, panelOf, reconcileLayout } from './core/panels.js';
|
|
41
|
+
// The series contract and the adapters (also under ./core): points with a clock, the boundary check, the report, the CSV adapter.
|
|
42
|
+
export { POINT_KINDS, alignSeries, csvAdapter, duplicateIds, pointsFromValues, report, resolveSeries, seriesSetSchema, toSeriesSet, validateSeriesSet } from './core/index.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type KeyboardEvent } from 'react';
|
|
2
|
+
export { LADDER_ROW_ATTRIBUTE, nextLadderRow, resolveLadderKey, type LadderKeyAction, type LadderKeyInput } from './core/ladder-keys.js';
|
|
3
|
+
/**
|
|
4
|
+
* Roving focus for the ladder rows. Spread `containerProps` on the element wrapping every row, give each row `data-ladder-row={id}` and
|
|
5
|
+
* `tabIndex={id === tabStop(ids, bestBidId) ? 0 : -1}`, where `id` is the row's price level (identity is the price, not the index).
|
|
6
|
+
*/
|
|
7
|
+
export declare function useLadderKeys(): {
|
|
8
|
+
containerProps: {
|
|
9
|
+
ref: (node: HTMLElement | null) => void;
|
|
10
|
+
onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
|
|
11
|
+
onFocus: (event: React.FocusEvent<HTMLElement>) => void;
|
|
12
|
+
};
|
|
13
|
+
/** The id of the one row that is a tab stop: the focused row while it is still on screen, else `fallback` (the best bid, or the best ask when there are no bids). */
|
|
14
|
+
tabStop: (ids: readonly string[], fallback: string | undefined) => string | undefined;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=ladder-keys.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { isRowShown, LADDER_ROW_ATTRIBUTE, nextLadderRow, resolveLadderKey } from './core/ladder-keys.js';
|
|
4
|
+
// The pure contract lives in the core (no React); the hook below is the React layer over it.
|
|
5
|
+
export { LADDER_ROW_ATTRIBUTE, nextLadderRow, resolveLadderKey } from './core/ladder-keys.js';
|
|
6
|
+
/**
|
|
7
|
+
* Roving focus for the ladder rows. Spread `containerProps` on the element wrapping every row, give each row `data-ladder-row={id}` and
|
|
8
|
+
* `tabIndex={id === tabStop(ids, bestBidId) ? 0 : -1}`, where `id` is the row's price level (identity is the price, not the index).
|
|
9
|
+
*/
|
|
10
|
+
export function useLadderKeys() {
|
|
11
|
+
const container = useRef(null);
|
|
12
|
+
const [active, setActive] = useState(null);
|
|
13
|
+
const onKeyDown = useCallback((event) => {
|
|
14
|
+
if (!(event.target instanceof HTMLElement))
|
|
15
|
+
return;
|
|
16
|
+
const action = resolveLadderKey(event);
|
|
17
|
+
// A read-only row is a plain div with no activation of its own: Space on it does nothing, and must not scroll the page
|
|
18
|
+
// or reach the transport's play/pause. (A seeking row is a button, which handles Space itself.)
|
|
19
|
+
const row = event.target.closest(`[${LADDER_ROW_ATTRIBUTE}]`);
|
|
20
|
+
if (event.key === ' ' && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey && row && row.tagName !== 'BUTTON') {
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
event.stopPropagation();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!action) {
|
|
26
|
+
// A modified Home or End has no ladder meaning, but must not reach the global transport jump either.
|
|
27
|
+
if ((event.key === 'Home' || event.key === 'End') && event.target.closest(`[${LADDER_ROW_ATTRIBUTE}]`))
|
|
28
|
+
event.stopPropagation();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const host = container.current;
|
|
32
|
+
if (!host)
|
|
33
|
+
return;
|
|
34
|
+
// Rows inside a closed disclosure are in the DOM but not on screen: they are not part of the walk.
|
|
35
|
+
const rows = Array.from(host.querySelectorAll(`[${LADDER_ROW_ATTRIBUTE}]`)).filter(isRowShown);
|
|
36
|
+
const current = event.target.closest(`[${LADDER_ROW_ATTRIBUTE}]`);
|
|
37
|
+
if (!current)
|
|
38
|
+
return;
|
|
39
|
+
event.preventDefault();
|
|
40
|
+
event.stopPropagation(); // Home and End must not reach the global transport shortcuts from here
|
|
41
|
+
const target = nextLadderRow(rows, current, action);
|
|
42
|
+
if (!target)
|
|
43
|
+
return;
|
|
44
|
+
setActive(target.getAttribute(LADDER_ROW_ATTRIBUTE));
|
|
45
|
+
target.focus();
|
|
46
|
+
}, []);
|
|
47
|
+
const onFocus = useCallback((event) => {
|
|
48
|
+
const row = event.target.closest(`[${LADDER_ROW_ATTRIBUTE}]`);
|
|
49
|
+
if (row)
|
|
50
|
+
setActive(row.getAttribute(LADDER_ROW_ATTRIBUTE));
|
|
51
|
+
}, []);
|
|
52
|
+
// The row that holds the tab stop can also leave the screen without a toggle: a replay update can push it past the visible
|
|
53
|
+
// levels into a closed disclosure. After each render, hand the stop back if it is no longer shown (it sets state only then).
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const host = container.current;
|
|
56
|
+
if (!host || active === null)
|
|
57
|
+
return;
|
|
58
|
+
const stop = Array.from(host.querySelectorAll(`[${LADDER_ROW_ATTRIBUTE}]`)).find((r) => r.getAttribute(LADDER_ROW_ATTRIBUTE) === active);
|
|
59
|
+
if (!stop || !isRowShown(stop))
|
|
60
|
+
setActive(null);
|
|
61
|
+
});
|
|
62
|
+
// A disclosure that closes hides the row that held the tab stop; `toggle` does not bubble, so listen in the capture phase.
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const host = container.current;
|
|
65
|
+
if (!host)
|
|
66
|
+
return;
|
|
67
|
+
const onToggle = () => {
|
|
68
|
+
const stop = host.querySelector(`[${LADDER_ROW_ATTRIBUTE}][tabindex="0"]`);
|
|
69
|
+
if (stop && !isRowShown(stop))
|
|
70
|
+
setActive(null);
|
|
71
|
+
};
|
|
72
|
+
host.addEventListener('toggle', onToggle, true);
|
|
73
|
+
return () => host.removeEventListener('toggle', onToggle, true);
|
|
74
|
+
}, []);
|
|
75
|
+
return {
|
|
76
|
+
containerProps: {
|
|
77
|
+
ref: (node) => {
|
|
78
|
+
container.current = node;
|
|
79
|
+
},
|
|
80
|
+
onKeyDown,
|
|
81
|
+
onFocus,
|
|
82
|
+
},
|
|
83
|
+
/** The id of the one row that is a tab stop: the focused row while it is still on screen, else `fallback` (the best bid, or the best ask when there are no bids). */
|
|
84
|
+
tabStop: (ids, fallback) => active !== null && ids.includes(active) ? active : fallback,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { CandleBar, PriceSpan } from './core/chart-scale.js';
|
|
2
|
+
import type { MoveDestination, PanelLayout } from './core/panels.js';
|
|
3
|
+
import type { ResolvedSeries, SeriesPoint } from './core/series.js';
|
|
4
|
+
/**
|
|
5
|
+
* One series a host puts on the chart besides its bars. Give it `points` (a time and a value or a reason for none, see
|
|
6
|
+
* `core/series`); it is placed on the bars by time. `values` (one number per bar, by position) still works for now and is
|
|
7
|
+
* removed in 0.0.7.
|
|
8
|
+
*/
|
|
9
|
+
export interface PanelSeriesData {
|
|
10
|
+
/** The selection id. Unique on the chart. */
|
|
11
|
+
id: string;
|
|
12
|
+
/** What the series is called: button names, the list and the live-region text. */
|
|
13
|
+
label: string;
|
|
14
|
+
/** The series on its own clock. Placed on the bars by time (`align` on `Panels.Root`; exact by default). */
|
|
15
|
+
points?: ReadonlyArray<SeriesPoint>;
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated One value per bar by position, null for none. A length that differs from the bars is shown as a problem
|
|
18
|
+
* in `Panels.List`. Removed in 0.0.7; use `points` (for a study, `pointsFromValues` from the core makes them).
|
|
19
|
+
*/
|
|
20
|
+
values?: ReadonlyArray<number | null>;
|
|
21
|
+
/** A fixed vertical range `[min, max]` for the band the series is in (an oscillator bounded 0 to 100). Ignored in `main`. */
|
|
22
|
+
range?: readonly [number, number];
|
|
23
|
+
/** Horizontal reference lines in the band, for example `[30, 70]`. Ignored in `main`. */
|
|
24
|
+
levels?: readonly number[];
|
|
25
|
+
/** `line` (default), or `histogram`: bars from zero, for a signed series. */
|
|
26
|
+
style?: 'line' | 'histogram';
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The context behind Panels, in a module of its own so Chart can read the layout without importing the parts (which
|
|
30
|
+
* import Chart).
|
|
31
|
+
*/
|
|
32
|
+
export interface PanelsContextValue {
|
|
33
|
+
series: readonly PanelSeriesData[];
|
|
34
|
+
layout: PanelLayout;
|
|
35
|
+
move: (seriesId: string, destination: MoveDestination) => void;
|
|
36
|
+
/** Prices of the series sitting in `main`, so the main scale keeps them in view. */
|
|
37
|
+
mainInclude: (visible: {
|
|
38
|
+
first: number;
|
|
39
|
+
last: number;
|
|
40
|
+
}, bars: readonly CandleBar[]) => readonly PriceSpan[];
|
|
41
|
+
/** A series on these bars: the value at each bar and the problems with the input. Cached per bars array and series. */
|
|
42
|
+
resolve: (item: PanelSeriesData, bars: readonly CandleBar[]) => ResolvedSeries;
|
|
43
|
+
/** Problems that belong to the set, not one series (an id used twice). */
|
|
44
|
+
problems: readonly string[];
|
|
45
|
+
}
|
|
46
|
+
export declare const PanelsContext: import("react").Context<PanelsContextValue | null>;
|
|
47
|
+
//# sourceMappingURL=panels-context.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type MutableRefObject } from 'react';
|
|
2
|
+
import type { ChartSelection } from './core/selection.js';
|
|
3
|
+
/**
|
|
4
|
+
* The contexts behind Selection and Series, in a module of their own so Chart, Drawings and Studies can read them
|
|
5
|
+
* without importing the parts (which import Chart).
|
|
6
|
+
*/
|
|
7
|
+
/** What Drawings.Layer tells the Selection.Layer so a press on a drawing, or while a tool is in use, is not read as a tap on clear chart. */
|
|
8
|
+
export interface SelectionGuard {
|
|
9
|
+
/** True when a press here belongs to a drawing or to a tool in use. */
|
|
10
|
+
owns: (clientX: number, clientY: number, pointerType: string) => boolean;
|
|
11
|
+
/** True while a tool is armed or a drawing is half placed: Escape then cancels that first. */
|
|
12
|
+
busy: () => boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface SelectionContextValue {
|
|
15
|
+
/** The selection now. */
|
|
16
|
+
selection: ChartSelection;
|
|
17
|
+
/** Change the selection. Setting what is already selected does nothing, so two parts agreeing on a tap report once. */
|
|
18
|
+
select: (next: ChartSelection) => void;
|
|
19
|
+
/** The selection as of the last change, even before the next render. */
|
|
20
|
+
current: () => ChartSelection;
|
|
21
|
+
/** The series a Series.Root mounted, or null. A tap on clear chart selects it. */
|
|
22
|
+
series: {
|
|
23
|
+
id: string;
|
|
24
|
+
label: string;
|
|
25
|
+
} | null;
|
|
26
|
+
registerSeries: (series: {
|
|
27
|
+
id: string;
|
|
28
|
+
label: string;
|
|
29
|
+
}) => () => void;
|
|
30
|
+
/** A name for the live region; the id is used when none is set. Returns the cleanup. */
|
|
31
|
+
setName: (kind: 'drawing' | 'series' | 'study', id: string, name: string) => () => void;
|
|
32
|
+
guard: MutableRefObject<SelectionGuard | null>;
|
|
33
|
+
}
|
|
34
|
+
export declare const SelectionContext: import("react").Context<SelectionContextValue | null>;
|
|
35
|
+
export interface SeriesContextValue {
|
|
36
|
+
id: string;
|
|
37
|
+
label: string;
|
|
38
|
+
selected: boolean;
|
|
39
|
+
}
|
|
40
|
+
export declare const SeriesContext: import("react").Context<SeriesContextValue | null>;
|
|
41
|
+
//# sourceMappingURL=selection-context.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Core without React: parse a bars CSV, then compute the chart frame a renderer would draw.
|
|
2
|
+
// Synthetic data only. Run: node examples/csv-to-chart-frame.mjs
|
|
3
|
+
import { parseBarsCsv, describeBarsCsv, chartFrame, lastBars } from '@matchstick-trading/primitives/core';
|
|
4
|
+
|
|
5
|
+
const csv = [
|
|
6
|
+
'timestamp,open,high,low,close,volume',
|
|
7
|
+
'1700000000000,100,102,99,101,1200',
|
|
8
|
+
'1700000060000,101,103,100,102,900',
|
|
9
|
+
'1700000120000,102,102.5,98,99,1500',
|
|
10
|
+
'1700000180000,99,101,98.5,100.5,700',
|
|
11
|
+
].join('\n');
|
|
12
|
+
|
|
13
|
+
const result = parseBarsCsv(csv);
|
|
14
|
+
console.log(describeBarsCsv(result, 'synthetic.csv'));
|
|
15
|
+
|
|
16
|
+
const frame = chartFrame(result.bars, lastBars(result.bars.length, 4), { width: 600, height: 300 });
|
|
17
|
+
console.log('visible bars:', frame.first, 'to', frame.last, 'price', frame.priceMin, 'to', frame.priceMax);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Core without React: indicator series on synthetic bars. Run: node examples/studies.mjs
|
|
2
|
+
import { sma, ema, rsi } from '@matchstick-trading/primitives/core';
|
|
3
|
+
|
|
4
|
+
const bars = Array.from({ length: 30 }, (_, i) => {
|
|
5
|
+
const close = 100 + Math.sin(i / 3) * 5 + i * 0.2;
|
|
6
|
+
return { timestamp: 1700000000000 + i * 60000, open: close - 0.4, high: close + 1, low: close - 1, close, volume: 1000 + i * 10 };
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const last = (series) => series[series.length - 1];
|
|
10
|
+
console.log('sma(10):', last(sma(bars, 10)));
|
|
11
|
+
console.log('ema(10):', last(ema(bars, 10)));
|
|
12
|
+
console.log('rsi(14):', last(rsi(bars, 14)));
|
package/llms.txt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Matchstick Primitives
|
|
2
|
+
|
|
3
|
+
> Headless, keyboard-first React parts for trading screens, with a plain-TypeScript core. Developer preview 0.0.10. Every example uses synthetic data.
|
|
4
|
+
|
|
5
|
+
- [README.md](README.md): the parts, a first chart, the core, your own data.
|
|
6
|
+
- [AGENTS.md](AGENTS.md): what an agent may do with this package, what to ask first, what not to do.
|
|
7
|
+
- [dist/index.d.ts](dist/index.d.ts): every part, prop and type, with doc comments.
|
|
8
|
+
- [dist/core/index.d.ts](dist/core/index.d.ts): the React-free core (geometry, studies, drawing model, CSV reader, key maps).
|
|
9
|
+
- [src/tokens.css](src/tokens.css): design tokens (`--mt-*`), imported as `@matchstick-trading/primitives/tokens.css`.
|
|
10
|
+
- Docs: https://ui.matchstick.trading/docs/getting-started
|
|
11
|
+
- Licence: Apache-2.0 (LICENSE). Source is in src/. Free building blocks for trading screens; issues are open at https://github.com/matchstick-trading/primitives/issues.
|
|
12
|
+
- Live demo: https://ui.matchstick.trading/docs/live (made-up data).
|
|
13
|
+
- Full screen: `Fullscreen.Frame` wraps the chart and `Fullscreen.Toggle` (inside it) enters and leaves; the browser's full screen where there is one, a full-page fallback otherwise (README, "Full screen"). Escape clears the chart's crosshair or selection first, then leaves.
|
|
14
|
+
- Selection: `Selection.Root`, `Selection.Layer`, `Series.Root`, `Series.Select`, `Series.Options` and an `id` on `Study.Line` / `Study.Band` give one selection (drawing, series or study). Rules and parts are in README.md, "Select the series and studies". Series options are the host's to fill.
|
|
15
|
+
- Series: a series is `{ id, label, points[] }` with `{ t, kind, v? }` points (ISO-8601 UTC `t`; kinds `value`, `missing`, `market-closed`, `not-applicable`, `halted`, `unknown`); `Panels.Root` and `Study.Line` take `points`; bare `values` is a shim that is still accepted in this version and will be removed in a later one. `csvAdapter`, `validateSeriesSet`, `report` are in the core. See README.md, "Give a series a clock".
|
|
16
|
+
- Panels: `Panels.Root` (series and bands), `Panels.Layer` (inside `Chart.Plot`), `Panels.List` and `Panels.Move` put more than one series on a chart in bands with their own price scales, and move a series between bands by buttons, not a drag. The bars, volume and drawings stay in the first band. Rules and parts are in README.md, "Panels and several series".
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@matchstick-trading/primitives",
|
|
3
|
+
"version": "0.0.10",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/matchstick-trading/primitives.git",
|
|
8
|
+
"directory": "packages/primitives"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://ui.matchstick.trading",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/matchstick-trading/primitives/issues"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"description": "Matchstick Primitives: composable, headless chart and replay parts (developer preview)",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"module": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"sideEffects": [
|
|
23
|
+
"**/*.css"
|
|
24
|
+
],
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./core": {
|
|
31
|
+
"types": "./dist/core/index.d.ts",
|
|
32
|
+
"import": "./dist/core/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./tokens.css": "./src/tokens.css"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"!dist/**/*.map",
|
|
39
|
+
"src",
|
|
40
|
+
"!src/**/*.test.*",
|
|
41
|
+
"LICENSE",
|
|
42
|
+
"README.md",
|
|
43
|
+
"CHANGELOG.md",
|
|
44
|
+
"AGENTS.md",
|
|
45
|
+
"llms.txt",
|
|
46
|
+
"examples"
|
|
47
|
+
],
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc && node scripts/add-use-client.mjs",
|
|
50
|
+
"dev": "tsc --watch",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"clean": "rm -rf dist",
|
|
53
|
+
"typecheck": "tsc --noEmit && node scripts/check-core.mjs",
|
|
54
|
+
"check:core": "node scripts/check-core.mjs",
|
|
55
|
+
"check:pack": "node scripts/check-pack.mjs",
|
|
56
|
+
"prepublishOnly": "npm run build && npm run check:pack"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/react": "^19.0.0",
|
|
60
|
+
"react": "^19.2.0",
|
|
61
|
+
"typescript": "~5.8.2",
|
|
62
|
+
"vitest": "^2.1.4"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/Chart.tsx
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Root, Plot, Grid, Candles, Volume, PriceAxis, TimeAxis, Crosshair, Readout, Reset, Autoscale, Table } from './ChartParts.js';
|
|
2
|
+
|
|
3
|
+
// The parts live in ChartParts.js (a client module). The namespace object is built here, outside it, so a server
|
|
4
|
+
// component can write `Chart.Root`: a property of an object exported from a client module is not reachable there.
|
|
5
|
+
export * from './ChartParts.js';
|
|
6
|
+
export { heikinAshi } from './core/candles.js';
|
|
7
|
+
export const Chart = { Root, Plot, Grid, Candles, Volume, PriceAxis, TimeAxis, Crosshair, Readout, Reset, Autoscale, Table };
|