@markput/react 0.14.0 → 0.14.2

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/index.d.ts CHANGED
@@ -94,12 +94,6 @@ interface MarkToken {
94
94
  };
95
95
  children: Token[];
96
96
  }
97
- interface ParseOptions {
98
- /** Return only MarkTokens, drop all TextTokens */
99
- marksOnly?: boolean;
100
- /** Drop zero-length TextTokens (where start === end) */
101
- skipEmptyText?: boolean;
102
- }
103
97
  /**
104
98
  * Template literal types for markup placeholders
105
99
  */
@@ -118,6 +112,60 @@ type SlotMarkup = `${string}${typeof PLACEHOLDER.Slot}${string}`;
118
112
  */
119
113
  type Markup = ValueMarkup | `${ValueMarkup}${MetaMarkup}` | `${ValueMarkup}${MetaMarkup}${SlotMarkup}` | `${ValueMarkup}${SlotMarkup}` | `${ValueMarkup}${SlotMarkup}${MetaMarkup}` | SlotMarkup | `${SlotMarkup}${MetaMarkup}` | `${SlotMarkup}${MetaMarkup}${ValueMarkup}` | `${SlotMarkup}${ValueMarkup}` | `${SlotMarkup}${ValueMarkup}${MetaMarkup}` | `${MetaMarkup}${ValueMarkup}` | `${MetaMarkup}${ValueMarkup}${SlotMarkup}` | `${MetaMarkup}${SlotMarkup}` | `${MetaMarkup}${SlotMarkup}${ValueMarkup}`;
120
114
  //#endregion
115
+ //#region ../../core/src/shared/editorContracts.d.ts
116
+ type TokenPath = readonly number[];
117
+ type TokenAddress = {
118
+ readonly path: TokenPath;
119
+ readonly token: Token;
120
+ };
121
+ type Result<T, Reason extends string> = {
122
+ ok: true;
123
+ value: T;
124
+ } | {
125
+ ok: false;
126
+ reason: Reason;
127
+ };
128
+ type DomRef = (element: HTMLElement | null) => void;
129
+ type Range$1 = {
130
+ readonly start: number;
131
+ readonly end: number;
132
+ };
133
+ type RawSelection = {
134
+ readonly range: Range$1;
135
+ readonly direction?: 'forward' | 'backward';
136
+ };
137
+ type NodeLocationResult = Result<{
138
+ readonly address: TokenAddress;
139
+ readonly tokenElement: HTMLElement;
140
+ readonly textElement?: HTMLElement;
141
+ readonly rowElement?: HTMLElement;
142
+ }, 'notIndexed' | 'outsideEditor' | 'control'>;
143
+ type RawSelectionResult = Result<RawSelection, 'notIndexed' | 'outsideEditor' | 'control' | 'mixedBoundary' | 'invalidBoundary'>;
144
+ type BoundaryPositionResult = Result<number, 'notIndexed' | 'outsideEditor' | 'control' | 'invalidBoundary' | 'composing'>;
145
+ type OptionalMarkFieldPatch = {
146
+ readonly kind: 'set';
147
+ readonly value: string;
148
+ } | {
149
+ readonly kind: 'clear';
150
+ };
151
+ type MarkPatch = {
152
+ readonly value?: string;
153
+ readonly meta?: OptionalMarkFieldPatch;
154
+ readonly slot?: OptionalMarkFieldPatch;
155
+ };
156
+ type MarkSnapshot = {
157
+ readonly value: string;
158
+ readonly meta: string | undefined;
159
+ readonly slot: string | undefined;
160
+ readonly readOnly: boolean;
161
+ };
162
+ type MarkInfo = {
163
+ readonly address: TokenAddress;
164
+ readonly depth: number;
165
+ readonly hasNestedMarks: boolean;
166
+ readonly key: string;
167
+ };
168
+ //#endregion
121
169
  //#region ../../../node_modules/.pnpm/csstype@3.2.3/node_modules/csstype/index.d.ts
122
170
  interface StandardLonghandProperties<TLength = (string & {}) | 0, TTime = string & {}> {
123
171
  /**
@@ -10547,181 +10595,277 @@ declare namespace DataType {
10547
10595
  type VisualBox = "border-box" | "content-box" | "padding-box";
10548
10596
  }
10549
10597
  //#endregion
10550
- //#region ../../core/src/features/parsing/parser/Parser.d.ts
10598
+ //#region ../../core/src/shared/types.d.ts
10551
10599
  /**
10552
- * Parser - High-performance tree-based markup parser
10600
+ * Registry interface used as a module-augmentation target. Framework packages
10601
+ * add a `default` property whose type is the framework's component type.
10553
10602
  *
10554
- * Parses text with markup patterns into a nested token tree structure.
10555
- * Supports complex patterns with metadata, nesting, and HTML-like constructs.
10603
+ * @example React augmentation
10604
+ * declare module '@markput/core' {
10605
+ * interface SlotRegistry {
10606
+ * default: import('react').ElementType
10607
+ * }
10608
+ * }
10556
10609
  *
10557
- * @example
10558
- * ```typescript
10559
- * const parser = new Parser(['@[__value__](__meta__)', '#[__slot__]'])
10560
- * const tokens = parser.parse('Hello @[world](test) and #[tag]')
10561
- * const text = parser.stringify(tokens)
10562
- * ```
10610
+ * Without augmentation, `Slot` falls back to `unknown`.
10563
10611
  */
10564
- declare class Parser {
10565
- private readonly registry;
10566
- private readonly segmentMatcher;
10567
- private readonly patternMatcher;
10568
- private readonly treeBuilder;
10569
- private readonly parseOptions;
10570
- /**
10571
- * Creates a new Parser instance with the specified markup patterns
10572
- *
10573
- * @param markups - Array of markup pattern strings with placeholders (can include undefined values):
10574
- * - `__value__` - main content (plain text, no nesting)
10575
- * - `__meta__` - metadata (plain text, no nesting)
10576
- * - `__slot__` - content supporting nested structures
10577
- * - `undefined` - skipped, but original array indices are preserved for descriptor matching
10578
- * @param options - Optional parse options to control token output:
10579
- * - `marksOnly` - return only MarkTokens, drop all TextTokens
10580
- * - `skipEmptyText` - drop zero-length TextTokens (where start === end)
10581
- *
10582
- * @example
10583
- * ```typescript
10584
- * const parser = new Parser([
10585
- * '@[__value__](__meta__)', // @[label](value) - descriptor.index = 0
10586
- * undefined, // skipped
10587
- * '#[__slot__]', // #[nested content] - descriptor.index = 2
10588
- * '**__slot__**' // **bold text** - descriptor.index = 3
10589
- * ])
10590
- * ```
10591
- */
10592
- constructor(markups: (Markup | undefined)[], options?: ParseOptions);
10612
+ interface SlotRegistry {}
10613
+ /** Framework-provided component type. Resolves to `unknown` unless `SlotRegistry` is augmented. */
10614
+ type Slot = keyof SlotRegistry extends never ? unknown : SlotRegistry[keyof SlotRegistry];
10615
+ /**
10616
+ * Core option for markups - Framework-agnostic configuration.
10617
+ * Extended by framework-specific Option types (e.g., React Option).
10618
+ *
10619
+ * Architecture:
10620
+ * - CoreOption: Contains only markup pattern (framework-independent)
10621
+ * - trigger configuration: Handled by framework layer via getTrigger function in TriggerFinder
10622
+ * - Separation of concerns: Core focuses on markup tokens, framework handles overlay triggers
10623
+ */
10624
+ interface CoreOption {
10593
10625
  /**
10594
- * Parses text into tokens (static convenience method)
10626
+ * Template string in which the mark is rendered.
10627
+ * Must contain placeholders: `__value__`, `__meta__`, and/or `__slot__`
10595
10628
  *
10596
- * @param value - Text to parse
10597
- * @param options - Options with markup patterns and token filtering
10598
- * @returns Array of tokens (TextToken and MarkToken)
10629
+ * Placeholder types:
10630
+ * - `__value__` - main content (plain text, no nesting)
10631
+ * - `__meta__` - additional metadata (plain text, no nesting)
10632
+ * - `__slot__` - content supporting nested structures
10599
10633
  *
10600
10634
  * @example
10601
- * ```typescript
10602
- * const tokens = Parser.parse('Hello @[world]', {
10603
- * markup: ['@[__value__]']
10604
- * })
10605
- * ```
10606
- */
10607
- static parse(value: string, options?: {
10608
- markup: Markup[];
10609
- } & ParseOptions): Token[];
10610
- /**
10611
- * Converts tokens back to text (static convenience method)
10635
+ * // Simple value
10636
+ * "@[__value__]"
10612
10637
  *
10613
- * @param tokens - Array of tokens to convert
10614
- * @returns Reconstructed text string
10638
+ * @example
10639
+ * // Value with metadata
10640
+ * "@[__value__](__meta__)"
10615
10641
  *
10616
10642
  * @example
10617
- * ```typescript
10618
- * const text = Parser.stringify(tokens)
10619
- * ```
10643
+ * // Nested content support
10644
+ * "@[__slot__]"
10620
10645
  */
10621
- static stringify(tokens: Token[]): string;
10646
+ markup?: Markup;
10647
+ overlay?: {
10648
+ trigger?: string;
10649
+ };
10650
+ }
10651
+ type OverlayMatch<TOption = CoreOption> = {
10622
10652
  /**
10623
- * Parses text into a nested token tree
10624
- *
10625
- * This is the main parsing method. It processes the input text through
10626
- * three stages:
10627
- * 1. Segment matching - finds all markup segments (O(N + M))
10628
- * 2. Pattern matching - builds complete patterns from segments (O(M))
10629
- * 3. Tree building - constructs nested token tree (O(M·D))
10630
- *
10631
- * @param value - Text to parse
10632
- * @returns Array of tokens representing the parsed structure
10633
- *
10634
- * @example
10635
- * ```typescript
10636
- * const parser = new Parser(['@[__value__](__meta__)'])
10637
- * const tokens = parser.parse('Hello @[world](test)')
10638
- * // Returns: [
10639
- * // TextToken('Hello '),
10640
- * // MarkToken('@[world](test)', value='world', meta='test'),
10641
- * // TextToken('')
10642
- * // ]
10643
- * ```
10653
+ * Found value via a overlayMatch
10644
10654
  */
10645
- parse(value: string): Token[];
10655
+ value: string;
10646
10656
  /**
10647
- * Converts tokens back to the original text
10648
- *
10649
- * This is the inverse operation of parse(). It reconstructs the original
10650
- * text from a token tree, preserving all markup and structure.
10651
- *
10652
- * @param tokens - Array of tokens to convert
10653
- * @returns Reconstructed text string
10654
- *
10655
- * @example
10656
- * ```typescript
10657
- * const text = 'Hello @[world](test)'
10658
- * const tokens = parser.parse(text)
10659
- * const reconstructed = parser.stringify(tokens)
10660
- * console.log(reconstructed === text) // true
10661
- * ```
10657
+ * Triggered value
10662
10658
  */
10663
- stringify(tokens: Token[]): string;
10659
+ source: string;
10664
10660
  /**
10665
- * Transforms annotated text by processing all mark tokens with a callback
10666
- *
10667
- * This method parses the text, recursively processes all MarkTokens
10668
- * (including nested ones) with the provided callback, and returns
10669
- * the transformed text.
10670
- *
10671
- * @param value - Annotated text to process
10672
- * @param callback - Function to transform each MarkToken
10673
- * @returns Transformed text
10674
- *
10675
- * @example
10676
- * ```typescript
10677
- * // Extract all values
10678
- * const text = '@[Hello](world) and #[tag]'
10679
- * const result = parser.transform(text, mark => mark.value)
10680
- * // Returns: 'Hello and tag'
10681
- *
10682
- * // Custom transformation
10683
- * const result = parser.transform(text, mark =>
10684
- * mark.meta ? `${mark.value}:${mark.meta}` : mark.value
10685
- * )
10686
- * // Returns: 'Hello:world and tag'
10687
- * ```
10661
+ * Piece of text, in which was a overlayMatch
10688
10662
  */
10689
- transform(value: string, callback: (mark: MarkToken) => string): string;
10663
+ span: string;
10690
10664
  /**
10691
- * Escapes markup segments in the given text using backslash
10692
- *
10693
- * This method uses the registry's unique segments and escapes them by adding
10694
- * a backslash before each character of each segment, preventing them from being
10695
- * parsed as markup when the text is processed again.
10696
- *
10697
- * @param text - Text to escape segments in
10698
- * @returns Text with escaped segments
10699
- *
10700
- * @example
10701
- * ```typescript
10702
- * const parser = new Parser(['**__slot__**', '@[__value__]'])
10703
- * const escaped = parser.escape('Hello **world** and @[user]')
10704
- * // Returns: 'Hello \*\*world\*\* and \@[user]'
10705
- * ```
10665
+ * Html element, in which was a overlayMatch
10706
10666
  */
10707
- escape(text: string): string;
10667
+ node: Node;
10668
+ range: Range$1;
10708
10669
  /**
10709
- * Unescapes markup patterns in the given text
10710
- *
10711
- * This method removes escape characters from segments that were previously
10712
- * escaped using escape(), allowing the patterns to be parsed normally.
10713
- *
10714
- * @param text - Text to unescape patterns in
10715
- * @returns Text with unescaped patterns
10716
- *
10717
- * @example
10718
- * ```typescript
10719
- * const parser = new Parser(['**__slot__**', '@[__value__]'])
10720
- * const unescaped = parser.unescape('Hello \*\*world\*\* and \@[user]')
10721
- * // Returns: 'Hello **world** and @[user]'
10722
- * ```
10670
+ * OverlayMatch's option
10671
+ */
10672
+ option: TOption;
10673
+ };
10674
+ type OverlayTrigger = Array<'change' | 'selectionChange'> | 'change' | 'selectionChange' | 'none';
10675
+ type CSSProperties$1 = Properties<string | number>;
10676
+ type DataAttributes = Record<`data${Capitalize<string>}`, string | number | boolean | undefined>;
10677
+ interface CoreSlots {
10678
+ container?: Slot;
10679
+ block?: Slot;
10680
+ }
10681
+ interface CoreSlotProps {
10682
+ container?: Record<string, unknown> & {
10683
+ className?: string;
10684
+ style?: CSSProperties$1;
10685
+ };
10686
+ block?: Record<string, unknown> & {
10687
+ className?: string;
10688
+ style?: CSSProperties$1;
10689
+ };
10690
+ }
10691
+ interface DraggableConfig {
10692
+ alwaysShowHandle?: boolean;
10693
+ }
10694
+ type DragAction = {
10695
+ type: 'reorder';
10696
+ source: number;
10697
+ target: number;
10698
+ } | {
10699
+ type: 'add';
10700
+ afterIndex: number;
10701
+ } | {
10702
+ type: 'delete';
10703
+ index: number;
10704
+ } | {
10705
+ type: 'duplicate';
10706
+ index: number;
10707
+ };
10708
+ interface DragActions {
10709
+ action: {
10710
+ (action: DragAction): void;
10711
+ };
10712
+ }
10713
+ //#endregion
10714
+ //#region ../../core/src/shared/signals/signal.d.ts
10715
+ interface Signal<T> {
10716
+ (): T;
10717
+ (value: T | undefined): boolean;
10718
+ }
10719
+ type SignalValues<T> = { [K in keyof T]: T[K] extends Signal<infer V> | Computed<infer V> ? V : T[K] };
10720
+ type ComputedRecord<C> = { readonly [K in keyof C]: C[K] extends (() => infer R) ? Computed<R> : never };
10721
+ interface Computed<T> {
10722
+ (): T;
10723
+ }
10724
+ interface Event<T = void> {
10725
+ (payload: T): void;
10726
+ read(): T | undefined;
10727
+ }
10728
+ //#endregion
10729
+ //#region ../../core/src/features/state/PropsModel.d.ts
10730
+ declare class PropsModel {
10731
+ readonly value: Signal<string | undefined>;
10732
+ readonly defaultValue: Signal<string | undefined>;
10733
+ readonly onChange: Signal<((value: string) => void) | undefined>;
10734
+ readonly options: Signal<CoreOption[]>;
10735
+ readonly readOnly: Signal<boolean>;
10736
+ readonly layout: Signal<"inline" | "block"> & ComputedRecord<{
10737
+ isBlock: () => boolean;
10738
+ }>;
10739
+ readonly draggable: Signal<boolean | DraggableConfig>;
10740
+ readonly showOverlayOn: Signal<OverlayTrigger>;
10741
+ readonly Span: Signal<_$react.ElementType | undefined>;
10742
+ readonly Mark: Signal<_$react.ElementType | undefined>;
10743
+ readonly Overlay: Signal<_$react.ElementType | undefined>;
10744
+ readonly className: Signal<string | undefined>;
10745
+ readonly style: Signal<CSSProperties$1 | undefined>;
10746
+ readonly slots: Signal<CoreSlots | undefined>;
10747
+ readonly slotProps: Signal<CoreSlotProps | undefined>;
10748
+ set(values: Partial<SignalValues<typeof this>>): void;
10749
+ }
10750
+ //#endregion
10751
+ //#region ../../core/src/features/state/ValueModel.d.ts
10752
+ declare class ValueModel {
10753
+ private readonly props;
10754
+ readonly current: Signal<string>;
10755
+ constructor(props: PropsModel);
10756
+ /**
10757
+ * Attempts to replace `range` with `replacement`. Returns `true` when the
10758
+ * edit was accepted (range valid and not read-only), `false` otherwise.
10759
+ * Callers use the return value to gate downstream side effects such as
10760
+ * caret placement.
10761
+ */
10762
+ replace(range: Range$1, replacement: string): boolean;
10763
+ }
10764
+ //#endregion
10765
+ //#region ../../core/src/features/parsing/tokenIndex.d.ts
10766
+ type TokenIndex = {
10767
+ pathFor(token: Token): TokenPath | undefined;
10768
+ addressFor(path: TokenPath): TokenAddress | undefined;
10769
+ resolve(path: TokenPath): Token | undefined;
10770
+ resolveAddress(address: TokenAddress): Result<Token, 'stale'>;
10771
+ key(path: TokenPath): string;
10772
+ };
10773
+ //#endregion
10774
+ //#region ../../core/src/features/parsing/TokenModel.d.ts
10775
+ declare class TokenModel {
10776
+ #private;
10777
+ private readonly value;
10778
+ private readonly props;
10779
+ readonly current: Computed<Token[]>;
10780
+ readonly index: Computed<TokenIndex>;
10781
+ constructor(value: ValueModel, props: PropsModel);
10782
+ }
10783
+ //#endregion
10784
+ //#region ../../core/src/features/state/Lifecycle.d.ts
10785
+ declare class Lifecycle {
10786
+ readonly mounted: Event<void>;
10787
+ readonly unmounted: Event<void>;
10788
+ readonly rendered: Event<void>;
10789
+ /**
10790
+ * Run `setup` when the editor is mounted. Any reactive subscription
10791
+ * created inside `setup` (`watch`, `listen`, `effect`, nested
10792
+ * `effectScope`) is automatically disposed on `unmounted` and re-created
10793
+ * on the next `mounted`.
10723
10794
  */
10724
- unescape(text: string): string;
10795
+ onMounted(setup: () => void): void;
10796
+ }
10797
+ //#endregion
10798
+ //#region ../../core/src/features/dom/DomIndexer.d.ts
10799
+ type PathElements = {
10800
+ path: TokenPath;
10801
+ address: TokenAddress;
10802
+ rowElement?: HTMLElement;
10803
+ tokenElement: HTMLElement;
10804
+ textElement?: HTMLElement;
10805
+ };
10806
+ //#endregion
10807
+ //#region ../../core/src/features/dom/DomModel.d.ts
10808
+ declare class DomModel {
10809
+ #private;
10810
+ readonly container: Signal<HTMLElement | null>;
10811
+ readonly indexed: Event<void>;
10812
+ readonly isUserSelecting: Signal<boolean>;
10813
+ readonly isIndexed: Signal<boolean>;
10814
+ constructor(lifecycle: Lifecycle, props: PropsModel, tokens: TokenModel);
10815
+ compositionStarted(): void;
10816
+ compositionEnded(): void;
10817
+ controlFor(ownerPath?: TokenPath): DomRef;
10818
+ childrenFor(ownerPath: TokenPath): DomRef;
10819
+ reconcile(): void;
10820
+ locateNode(node: Node): NodeLocationResult;
10821
+ pathElements(): IterableIterator<PathElements>;
10822
+ pathElementsFor(address: TokenAddress): PathElements | undefined;
10823
+ rawPositionFromBoundary(node: Node, offset: number, affinity?: 'before' | 'after'): BoundaryPositionResult;
10824
+ readRawSelection(): RawSelectionResult;
10825
+ readSelectedContent(): {
10826
+ html: string;
10827
+ text: string;
10828
+ } | undefined;
10829
+ }
10830
+ //#endregion
10831
+ //#region ../../core/src/features/selection/SelectionController.d.ts
10832
+ declare class SelectionController {
10833
+ #private;
10834
+ private readonly lifecycle;
10835
+ private readonly dom;
10836
+ private readonly parsing;
10837
+ private readonly value;
10838
+ private readonly props;
10839
+ readonly range: Signal<Range$1 | undefined>;
10840
+ readonly position: Signal<number | undefined>;
10841
+ readonly isAllSelected: Computed<boolean>;
10842
+ constructor(lifecycle: Lifecycle, dom: DomModel, parsing: TokenModel, value: ValueModel, props: PropsModel);
10843
+ focusFirst(): void;
10844
+ selectAll(): void;
10845
+ /**
10846
+ * Place the caret at a known token address. Use this when the caller already
10847
+ * has a {@link TokenAddress} and needs to disambiguate which token owns a
10848
+ * shared boundary position (e.g. a text-token ending at N and a mark-token
10849
+ * starting at N both "own" position N). Position-only callers should write
10850
+ * to `range` instead — the auto-apply effect handles the common case.
10851
+ *
10852
+ * Returns `true` when the address could be resolved and focused, `false`
10853
+ * when the DOM is not yet indexed or the address is stale.
10854
+ */
10855
+ placeAtAddress(address: TokenAddress, boundary?: 'start' | 'end'): boolean;
10856
+ }
10857
+ //#endregion
10858
+ //#region ../../core/src/features/edit/EditController.d.ts
10859
+ /**
10860
+ * Single write path for text edits — delegates gating to {@link ValueModel.replace}
10861
+ * and only moves the caret when the edit is accepted. Wrapped in {@link batch}
10862
+ * so subscribers observe a consistent value/selection pair on one tick.
10863
+ */
10864
+ declare class EditController {
10865
+ private readonly value;
10866
+ private readonly selection;
10867
+ constructor(value: ValueModel, selection: SelectionController);
10868
+ replace(range: Range$1, replacement: string): void;
10725
10869
  }
10726
10870
  //#endregion
10727
10871
  //#region ../../core/src/features/parsing/parser/utils/annotate.d.ts
@@ -10763,147 +10907,18 @@ declare function annotate(markup: Markup, params: {
10763
10907
  */
10764
10908
  declare function denote(value: string, callback: (mark: MarkToken) => string, markups: Markup[]): string;
10765
10909
  //#endregion
10766
- //#region ../../core/src/shared/editorContracts.d.ts
10767
- type TokenPath = readonly number[];
10768
- type TokenAddress = {
10769
- readonly path: TokenPath;
10770
- readonly parseGeneration: number;
10771
- };
10772
- type Result<T, Reason extends string> = {
10773
- ok: true;
10774
- value: T;
10775
- } | {
10776
- ok: false;
10777
- reason: Reason;
10778
- };
10779
- type DomRef = (element: HTMLElement | null) => void;
10780
- type RawRange = {
10781
- readonly start: number;
10782
- readonly end: number;
10783
- };
10784
- type RawSelection = {
10785
- readonly range: RawRange;
10786
- readonly direction?: 'forward' | 'backward';
10787
- };
10788
- type NodeLocationResult = Result<{
10789
- readonly address: TokenAddress;
10790
- readonly tokenElement: HTMLElement;
10791
- readonly textElement?: HTMLElement;
10792
- readonly rowElement?: HTMLElement;
10793
- }, 'notIndexed' | 'outsideEditor' | 'control'>;
10794
- type RawSelectionResult = Result<RawSelection, 'notIndexed' | 'outsideEditor' | 'control' | 'mixedBoundary' | 'invalidBoundary'>;
10795
- type BoundaryPositionResult = Result<number, 'notIndexed' | 'outsideEditor' | 'control' | 'invalidBoundary' | 'composing'>;
10796
- type EditResult = {
10797
- ok: true;
10798
- value: string;
10799
- accepted: 'immediate' | 'pendingControlledEcho';
10800
- } | {
10801
- ok: false;
10802
- reason: 'readOnly' | 'invalidRange' | 'stale';
10803
- };
10804
- type CaretRecovery = {
10805
- readonly kind: 'caret';
10806
- readonly rawPosition: number;
10807
- readonly affinity?: 'before' | 'after';
10808
- } | {
10809
- readonly kind: 'selection';
10810
- readonly selection: RawSelection;
10811
- };
10812
- type OptionalMarkFieldPatch = {
10813
- readonly kind: 'set';
10814
- readonly value: string;
10815
- } | {
10816
- readonly kind: 'clear';
10817
- };
10818
- type MarkPatch = {
10819
- readonly value?: string;
10820
- readonly meta?: OptionalMarkFieldPatch;
10821
- readonly slot?: OptionalMarkFieldPatch;
10822
- };
10823
- type MarkSnapshot = {
10824
- readonly value: string;
10825
- readonly meta: string | undefined;
10826
- readonly slot: string | undefined;
10827
- readonly readOnly: boolean;
10828
- };
10829
- type MarkInfo = {
10830
- readonly address: TokenAddress;
10831
- readonly depth: number;
10832
- readonly hasNestedMarks: boolean;
10833
- readonly key: string;
10834
- };
10835
- type TokenShapeSnapshot = {
10836
- readonly kind: 'text';
10837
- } | {
10838
- readonly kind: 'mark';
10839
- readonly descriptor: MarkupDescriptor;
10840
- readonly descriptorIndex: number;
10841
- };
10842
- type DomIndex = {
10843
- readonly generation: number;
10844
- };
10845
- type CaretLocation = {
10846
- readonly address: TokenAddress;
10847
- readonly role: 'row' | 'token' | 'text' | 'markDescendant';
10848
- };
10849
- type DomDiagnostic = {
10850
- readonly kind: 'missingRole' | 'stalePath' | 'outsideEditor' | 'controlBoundary' | 'mixedBoundary' | 'invalidBoundary' | 'renderReentry' | 'recoveryFailed' | 'missingContainer' | 'ambiguousStructure';
10851
- readonly path?: TokenPath;
10852
- readonly reason: string;
10853
- };
10854
- type EditSource = 'input' | 'paste' | 'cut' | 'overlay' | 'mark' | 'block' | 'drag';
10855
- //#endregion
10856
- //#region ../../core/src/features/caret/CaretFeature.d.ts
10857
- declare class CaretFeature implements Feature {
10910
+ //#region ../../core/src/features/block/BlockController.d.ts
10911
+ declare class BlockController {
10858
10912
  #private;
10859
- private readonly _store;
10860
- readonly recovery: Signal<CaretRecovery | undefined>;
10861
- readonly location: Signal<CaretLocation | undefined>;
10862
- readonly selecting: Signal<"drag" | "all" | undefined>;
10863
- constructor(_store: Store);
10864
- enable(): void;
10865
- disable(): void;
10866
- placeAt(rawPosition: number, affinity?: 'before' | 'after'): Result<void, 'notIndexed' | 'invalidBoundary'>;
10867
- focus(address: TokenAddress, boundary?: 'start' | 'end'): Result<void, 'notIndexed' | 'stale'>;
10868
- }
10869
- //#endregion
10870
- //#region ../../core/src/shared/signals/signal.d.ts
10871
- interface Signal<T> {
10872
- (): T;
10873
- (value: T | undefined): void;
10874
- }
10875
- type SignalValues<T> = { [K in keyof T]: T[K] extends Signal<infer V> | Computed<infer V> ? V : T[K] };
10876
- interface Computed<T> {
10877
- (): T;
10878
- }
10879
- interface Event<T = void> {
10880
- (payload: T): void;
10881
- read(): T | undefined;
10882
- }
10883
- //#endregion
10884
- //#region ../../core/src/features/props/PropsFeature.d.ts
10885
- declare class PropsFeature {
10886
- private readonly _store;
10887
- readonly value: Signal<string | undefined>;
10888
- readonly defaultValue: Signal<string | undefined>;
10889
- readonly onChange: Signal<((value: string) => void) | undefined>;
10890
- readonly options: Signal<CoreOption[]>;
10891
- readonly readOnly: Signal<boolean>;
10892
- readonly layout: Signal<"inline" | "block">;
10893
- readonly draggable: Signal<boolean | DraggableConfig>;
10894
- readonly showOverlayOn: Signal<OverlayTrigger>;
10895
- readonly Span: Signal<_$react.ElementType | undefined>;
10896
- readonly Mark: Signal<_$react.ElementType | undefined>;
10897
- readonly Overlay: Signal<_$react.ElementType | undefined>;
10898
- readonly className: Signal<string | undefined>;
10899
- readonly style: Signal<CSSProperties$1 | undefined>;
10900
- readonly slots: Signal<CoreSlots | undefined>;
10901
- readonly slotProps: Signal<CoreSlotProps | undefined>;
10902
- constructor(_store: Store);
10903
- set(values: Partial<SignalValues<typeof this>>): void;
10913
+ private readonly props;
10914
+ private readonly value;
10915
+ private readonly tokens;
10916
+ private readonly selection;
10917
+ readonly action: Event<DragAction>;
10918
+ constructor(props: PropsModel, value: ValueModel, tokens: TokenModel, selection: SelectionController);
10904
10919
  }
10905
10920
  //#endregion
10906
- //#region ../../core/src/store/BlockStore.d.ts
10921
+ //#region ../../core/src/features/block/BlockStore.d.ts
10907
10922
  type DropPosition = 'before' | 'after' | null;
10908
10923
  declare class BlockStore {
10909
10924
  #private;
@@ -10923,91 +10938,31 @@ declare class BlockStore {
10923
10938
  attachContainer(el: HTMLElement | null, blockIndex: number, actions: DragActions): void;
10924
10939
  attachGrip(el: HTMLButtonElement | null, blockIndex: number, actions: DragActions): void;
10925
10940
  attachMenu(el: HTMLElement | null): void;
10926
- closeMenu: () => void;
10941
+ closeMenu: () => boolean;
10927
10942
  addBlock: () => void;
10928
10943
  deleteBlock: () => void;
10929
10944
  duplicateBlock: () => void;
10930
10945
  }
10931
10946
  //#endregion
10932
- //#region ../../core/src/store/BlockRegistry.d.ts
10947
+ //#region ../../core/src/features/block/BlockRegistry.d.ts
10933
10948
  declare class BlockRegistry {
10934
10949
  #private;
10935
10950
  get(token: object): BlockStore;
10936
10951
  }
10937
10952
  //#endregion
10938
- //#region ../../core/src/features/clipboard/ClipboardFeature.d.ts
10939
- declare class ClipboardFeature {
10940
- #private;
10941
- private readonly store;
10942
- constructor(store: Store);
10943
- enable(): void;
10944
- disable(): void;
10945
- }
10946
- //#endregion
10947
- //#region ../../core/src/features/dom/DomFeature.d.ts
10948
- declare class DomFeature {
10953
+ //#region ../../core/src/features/clipboard/ClipboardController.d.ts
10954
+ declare class ClipboardController {
10949
10955
  #private;
10950
- private readonly _store;
10951
- readonly index: Computed<DomIndex | undefined>;
10952
- readonly container: Signal<HTMLElement | null>;
10953
- readonly diagnostics: Event<DomDiagnostic>;
10954
- constructor(_store: Store);
10955
- enable(): void;
10956
- disable(): void;
10957
- compositionStarted(): void;
10958
- compositionEnded(): void;
10959
- controlFor(ownerPath?: TokenPath): DomRef;
10960
- childrenFor(ownerPath: TokenPath): DomRef;
10961
- reconcile(): void;
10962
- locateNode(node: Node): NodeLocationResult;
10963
- placeCaretAtRawPosition(rawPosition: number, affinity?: 'before' | 'after'): Result<void, 'notIndexed' | 'invalidBoundary'>;
10964
- focusAddress(address: TokenAddress, boundary?: 'start' | 'end'): Result<void, 'notIndexed' | 'stale'>;
10965
- rawPositionFromBoundary(node: Node, offset: number, affinity?: 'before' | 'after'): BoundaryPositionResult;
10966
- readRawSelection(): RawSelectionResult;
10967
- }
10968
- //#endregion
10969
- //#region ../../core/src/features/drag/DragFeature.d.ts
10970
- declare class DragFeature {
10971
- #private;
10972
- private readonly store;
10973
- readonly action: Event<DragAction>;
10974
- constructor(store: Store);
10975
- enable(): void;
10976
- disable(): void;
10977
- }
10978
- //#endregion
10979
- //#region ../../core/src/features/keyboard/KeyboardFeature.d.ts
10980
- declare class KeyboardFeature implements Feature {
10981
- #private;
10982
- private readonly _store;
10983
- constructor(_store: Store);
10984
- enable(): void;
10985
- disable(): void;
10986
- }
10987
- //#endregion
10988
- //#region ../../core/src/features/lifecycle/LifecycleFeature.d.ts
10989
- declare class LifecycleFeature implements Feature {
10990
- readonly mounted: Event<void>;
10991
- readonly unmounted: Event<void>;
10992
- readonly rendered: Event<void>;
10993
- enable(): void;
10994
- disable(): void;
10956
+ private readonly lifecycle;
10957
+ private readonly edit;
10958
+ private readonly dom;
10959
+ private readonly tokens;
10960
+ constructor(lifecycle: Lifecycle, edit: EditController, dom: DomModel, tokens: TokenModel);
10995
10961
  }
10996
10962
  //#endregion
10997
- //#region ../../core/src/features/mark/MarkController.d.ts
10998
- declare class MarkController {
10999
- #private;
11000
- private readonly store;
11001
- private readonly address;
11002
- private readonly snapshot;
11003
- constructor(store: Store, address: TokenAddress, snapshot: MarkSnapshot, shape: TokenShapeSnapshot);
11004
- static fromToken(store: Store, token: MarkToken): MarkController;
11005
- get value(): string;
11006
- get meta(): string | undefined;
11007
- get slot(): string | undefined;
11008
- get readOnly(): boolean;
11009
- remove(): EditResult;
11010
- update(patch: MarkPatch): EditResult;
10963
+ //#region ../../core/src/features/keyboard/KeyboardController.d.ts
10964
+ declare class KeyboardController {
10965
+ constructor(lifecycle: Lifecycle, dom: DomModel, value: ValueModel, selection: SelectionController, edit: EditController, tokens: TokenModel, props: PropsModel);
11011
10966
  }
11012
10967
  //#endregion
11013
10968
  //#region ../../core/src/features/slots/types.d.ts
@@ -11019,10 +10974,8 @@ interface OverlaySlot {
11019
10974
  }
11020
10975
  //#endregion
11021
10976
  //#region ../../core/src/features/slots/SlotsFeature.d.ts
11022
- declare class SlotsFeature implements Feature {
11023
- private readonly _store;
11024
- readonly isBlock: Computed<boolean>;
11025
- readonly isDraggable: Computed<boolean>;
10977
+ declare class SlotsFeature {
10978
+ private readonly props;
11026
10979
  readonly containerComponent: Computed<Slot>;
11027
10980
  readonly containerProps: Computed<{
11028
10981
  className: string | undefined;
@@ -11031,27 +10984,61 @@ declare class SlotsFeature implements Feature {
11031
10984
  }>;
11032
10985
  readonly blockComponent: Computed<Slot>;
11033
10986
  readonly blockProps: Computed<Record<string, unknown> | undefined>;
11034
- readonly spanComponent: Computed<Slot>;
11035
- readonly spanProps: Computed<Record<string, unknown> | undefined>;
11036
- constructor(_store: Store);
11037
- enable(): void;
11038
- disable(): void;
10987
+ readonly mark: MarkSlot;
10988
+ constructor(props: PropsModel);
11039
10989
  }
11040
10990
  //#endregion
11041
- //#region ../../core/src/features/mark/MarkFeature.d.ts
11042
- declare class MarkFeature implements Feature {
11043
- private readonly _store;
11044
- readonly enabled: Computed<boolean>;
11045
- readonly slot: MarkSlot;
11046
- constructor(_store: Store);
11047
- enable(): void;
11048
- disable(): void;
10991
+ //#region ../../core/src/shared/classes/KeyGenerator.d.ts
10992
+ declare class KeyGenerator {
10993
+ #private;
10994
+ get(object: object): number | undefined;
11049
10995
  }
11050
10996
  //#endregion
11051
- //#region ../../core/src/features/overlay/OverlayFeature.d.ts
11052
- declare class OverlayFeature implements Feature {
10997
+ //#region ../../core/src/store/Store.d.ts
10998
+ declare class Store {
10999
+ readonly key: KeyGenerator;
11000
+ readonly blocks: BlockRegistry;
11001
+ readonly lifecycle: Lifecycle;
11002
+ readonly props: PropsModel;
11003
+ readonly value: ValueModel;
11004
+ readonly tokens: TokenModel;
11005
+ readonly slots: SlotsFeature;
11006
+ readonly dom: DomModel;
11007
+ readonly selection: SelectionController;
11008
+ readonly edit: EditController;
11009
+ readonly overlay: OverlayController;
11010
+ readonly keyboard: KeyboardController;
11011
+ readonly block: BlockController;
11012
+ readonly clipboard: ClipboardController;
11013
+ readonly handler: MarkputHandler;
11014
+ }
11015
+ //#endregion
11016
+ //#region ../../core/src/features/parsing/MarkController.d.ts
11017
+ declare class MarkController {
11018
+ #private;
11019
+ private readonly store;
11020
+ private readonly address;
11021
+ private readonly snapshot;
11022
+ constructor(store: Store, address: TokenAddress, snapshot: MarkSnapshot);
11023
+ static fromToken(store: Store, token: MarkToken): MarkController;
11024
+ get value(): string;
11025
+ get meta(): string | undefined;
11026
+ get slot(): string | undefined;
11027
+ get readOnly(): boolean;
11028
+ remove(): void;
11029
+ update(patch: MarkPatch): void;
11030
+ }
11031
+ //#endregion
11032
+ //#region ../../core/src/features/overlay/OverlayController.d.ts
11033
+ declare class OverlayController {
11053
11034
  #private;
11054
- private readonly _store;
11035
+ private readonly lifecycle;
11036
+ private readonly props;
11037
+ private readonly value;
11038
+ private readonly dom;
11039
+ private readonly selection;
11040
+ private readonly edit;
11041
+ private readonly tokens;
11055
11042
  readonly match: Signal<OverlayMatch | undefined>;
11056
11043
  readonly element: Signal<HTMLElement | null>;
11057
11044
  readonly slot: OverlaySlot;
@@ -11060,218 +11047,24 @@ declare class OverlayFeature implements Feature {
11060
11047
  match: OverlayMatch;
11061
11048
  }>;
11062
11049
  readonly close: Event<void>;
11063
- constructor(_store: Store);
11064
- enable(): void;
11065
- disable(): void;
11066
- }
11067
- //#endregion
11068
- //#region ../../core/src/features/parsing/tokenIndex.d.ts
11069
- type TokenIndex = {
11070
- readonly generation: number;
11071
- pathFor(token: Token): TokenPath | undefined;
11072
- addressFor(path: TokenPath): TokenAddress | undefined;
11073
- resolve(path: TokenPath): Token | undefined;
11074
- resolveAddress(address: TokenAddress, expected?: TokenShapeSnapshot): Result<Token, 'stale'>;
11075
- key(path: TokenPath): string;
11076
- equals(a: TokenPath, b: TokenPath): boolean;
11077
- };
11078
- //#endregion
11079
- //#region ../../core/src/features/parsing/ParseFeature.d.ts
11080
- declare class ParsingFeature implements Feature {
11081
- #private;
11082
- private readonly _store;
11083
- readonly tokens: Signal<Token[]>;
11084
- readonly index: Computed<TokenIndex>;
11085
- readonly parser: Computed<Parser | undefined>;
11086
- readonly reparse: Event<void>;
11087
- constructor(_store: Store);
11088
- parseValue(value: string): Token[];
11089
- acceptTokens(tokens: Token[]): void;
11090
- enable(): void;
11091
- disable(): void;
11092
- sync(value?: string): void;
11093
- }
11094
- //#endregion
11095
- //#region ../../core/src/features/value/ValueFeature.d.ts
11096
- declare class ValueFeature implements Feature {
11097
- #private;
11098
- private readonly _store;
11099
- readonly current: Signal<string>;
11100
- readonly isControlledMode: Computed<boolean>;
11101
- readonly change: Event<void>;
11102
- constructor(_store: Store);
11103
- enable(): void;
11104
- disable(): void;
11105
- replaceRange(range: RawRange, replacement: string, options?: {
11106
- recover?: CaretRecovery;
11107
- source?: EditSource;
11108
- }): EditResult;
11109
- replaceAll(next: string, options?: {
11110
- recover?: CaretRecovery;
11111
- source?: EditSource;
11112
- }): EditResult;
11050
+ readonly position: Computed<{
11051
+ left: number;
11052
+ top: number;
11053
+ }>;
11054
+ constructor(lifecycle: Lifecycle, props: PropsModel, value: ValueModel, dom: DomModel, selection: SelectionController, edit: EditController, tokens: TokenModel);
11113
11055
  }
11114
11056
  //#endregion
11115
- //#region ../../core/src/shared/classes/MarkputHandler.d.ts
11057
+ //#region ../../core/src/store/MarkputHandler.d.ts
11116
11058
  declare class MarkputHandler {
11117
- private readonly store;
11118
- constructor(store: Store);
11059
+ private readonly dom;
11060
+ private readonly overlayFeature;
11061
+ private readonly selection;
11062
+ constructor(dom: DomModel, overlayFeature: OverlayController, selection: SelectionController);
11119
11063
  get container(): HTMLElement | null;
11120
11064
  get overlay(): HTMLElement | null;
11121
11065
  focus(): void;
11122
11066
  }
11123
11067
  //#endregion
11124
- //#region ../../core/src/shared/classes/KeyGenerator.d.ts
11125
- declare class KeyGenerator {
11126
- #private;
11127
- get(object: object): number | undefined;
11128
- }
11129
- //#endregion
11130
- //#region ../../core/src/store/Store.d.ts
11131
- declare class Store {
11132
- readonly key: KeyGenerator;
11133
- readonly blocks: BlockRegistry;
11134
- readonly props: PropsFeature;
11135
- readonly handler: MarkputHandler;
11136
- readonly lifecycle: LifecycleFeature;
11137
- readonly value: ValueFeature;
11138
- readonly mark: MarkFeature;
11139
- readonly overlay: OverlayFeature;
11140
- readonly slots: SlotsFeature;
11141
- readonly caret: CaretFeature;
11142
- readonly keyboard: KeyboardFeature;
11143
- readonly dom: DomFeature;
11144
- readonly drag: DragFeature;
11145
- readonly clipboard: ClipboardFeature;
11146
- readonly parsing: ParsingFeature;
11147
- constructor();
11148
- }
11149
- //#endregion
11150
- //#region ../../core/src/shared/types.d.ts
11151
- /**
11152
- * Registry interface used as a module-augmentation target. Framework packages
11153
- * add a `default` property whose type is the framework's component type.
11154
- *
11155
- * @example React augmentation
11156
- * declare module '@markput/core' {
11157
- * interface SlotRegistry {
11158
- * default: import('react').ElementType
11159
- * }
11160
- * }
11161
- *
11162
- * Without augmentation, `Slot` falls back to `unknown`.
11163
- */
11164
- interface SlotRegistry {}
11165
- /** Framework-provided component type. Resolves to `unknown` unless `SlotRegistry` is augmented. */
11166
- type Slot = keyof SlotRegistry extends never ? unknown : SlotRegistry[keyof SlotRegistry];
11167
- /**
11168
- * Core option for markups - Framework-agnostic configuration.
11169
- * Extended by framework-specific Option types (e.g., React Option).
11170
- *
11171
- * Architecture:
11172
- * - CoreOption: Contains only markup pattern (framework-independent)
11173
- * - trigger configuration: Handled by framework layer via getTrigger function in TriggerFinder
11174
- * - Separation of concerns: Core focuses on markup parsing, framework handles overlay triggers
11175
- */
11176
- interface CoreOption {
11177
- /**
11178
- * Template string in which the mark is rendered.
11179
- * Must contain placeholders: `__value__`, `__meta__`, and/or `__slot__`
11180
- *
11181
- * Placeholder types:
11182
- * - `__value__` - main content (plain text, no nesting)
11183
- * - `__meta__` - additional metadata (plain text, no nesting)
11184
- * - `__slot__` - content supporting nested structures
11185
- *
11186
- * @example
11187
- * // Simple value
11188
- * "@[__value__]"
11189
- *
11190
- * @example
11191
- * // Value with metadata
11192
- * "@[__value__](__meta__)"
11193
- *
11194
- * @example
11195
- * // Nested content support
11196
- * "@[__slot__]"
11197
- */
11198
- markup?: Markup;
11199
- overlay?: {
11200
- trigger?: string;
11201
- };
11202
- }
11203
- type OverlayMatch<TOption = CoreOption> = {
11204
- /**
11205
- * Found value via a overlayMatch
11206
- */
11207
- value: string;
11208
- /**
11209
- * Triggered value
11210
- */
11211
- source: string;
11212
- /**
11213
- * Piece of text, in which was a overlayMatch
11214
- */
11215
- span: string;
11216
- /**
11217
- * Html element, in which was a overlayMatch
11218
- */
11219
- node: Node;
11220
- range: RawRange;
11221
- /**
11222
- * OverlayMatch's option
11223
- */
11224
- option: TOption;
11225
- };
11226
- type OverlayTrigger = Array<'change' | 'selectionChange'> | 'change' | 'selectionChange' | 'none';
11227
- type CSSProperties$1 = Properties<string | number>;
11228
- type DataAttributes = Record<`data${Capitalize<string>}`, string | number | boolean | undefined>;
11229
- interface CoreSlots {
11230
- container?: Slot;
11231
- block?: Slot;
11232
- span?: Slot;
11233
- }
11234
- interface CoreSlotProps {
11235
- container?: Record<string, unknown> & {
11236
- className?: string;
11237
- style?: CSSProperties$1;
11238
- };
11239
- block?: Record<string, unknown> & {
11240
- className?: string;
11241
- style?: CSSProperties$1;
11242
- };
11243
- span?: Record<string, unknown> & {
11244
- className?: string;
11245
- style?: CSSProperties$1;
11246
- };
11247
- }
11248
- interface DraggableConfig {
11249
- alwaysShowHandle?: boolean;
11250
- }
11251
- type DragAction = {
11252
- type: 'reorder';
11253
- source: number;
11254
- target: number;
11255
- } | {
11256
- type: 'add';
11257
- afterIndex: number;
11258
- } | {
11259
- type: 'delete';
11260
- index: number;
11261
- } | {
11262
- type: 'duplicate';
11263
- index: number;
11264
- };
11265
- interface DragActions {
11266
- action: {
11267
- (action: DragAction): void;
11268
- };
11269
- }
11270
- interface Feature {
11271
- enable(): void;
11272
- disable(): void;
11273
- }
11274
- //#endregion
11275
11068
  //#region src/types.d.ts
11276
11069
  /**
11277
11070
  * Props passed to Mark components.
@@ -11370,12 +11163,12 @@ interface MarkedInputProps<TMarkProps = MarkProps, TOverlayProps extends CoreOpt
11370
11163
  style?: CSSProperties;
11371
11164
  /**
11372
11165
  * Override internal components using slots
11373
- * @example slots={{ container: 'div', span: 'span' }}
11166
+ * @example slots={{ container: 'div' }}
11374
11167
  */
11375
11168
  slots?: Slots;
11376
11169
  /**
11377
11170
  * Props to pass to slot components
11378
- * @example slotProps={{ container: { onKeyDown: handler }, span: { className: 'custom' } }}
11171
+ * @example slotProps={{ container: { onKeyDown: handler } }}
11379
11172
  */
11380
11173
  slotProps?: SlotProps;
11381
11174
  /**