@markput/react 0.1.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/LICENSE +21 -0
- package/README.md +35 -0
- package/index.css +1 -0
- package/index.d.ts +261 -0
- package/index.js +1755 -0
- package/package.json +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Ruslan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# [Marked Input](https://marked-input.vercel.app) · [](https://www.npmjs.com/package/@markput/react) [](https://bundlephobia.com/package/@markput/react) [](https://marked-input.vercel.app)
|
|
2
|
+
|
|
3
|
+
<img width="521" alt="image" src="https://user-images.githubusercontent.com/37639183/182974441-49e4b247-449a-47ba-a090-2cb3aab7ce44.png">
|
|
4
|
+
|
|
5
|
+
A React component that lets you combine editable text with any component using annotated text.
|
|
6
|
+
|
|
7
|
+
**[Documentation](https://markput.vercel.app)** **[Storybook](https://marked-input.vercel.app)**
|
|
8
|
+
|
|
9
|
+
## Feature
|
|
10
|
+
|
|
11
|
+
- Powerful annotations tool: add, edit, remove, visualize
|
|
12
|
+
- Nested marks support
|
|
13
|
+
- Support for custom syntax patterns (e.g., HTML, markdown)
|
|
14
|
+
- TypeScript
|
|
15
|
+
- Support for any components
|
|
16
|
+
- Flexible and customizable
|
|
17
|
+
- Two ways to configure
|
|
18
|
+
- Helpers for processing text
|
|
19
|
+
- Hooks for advanced components
|
|
20
|
+
- Button handling (Left, Right, Delete, Backspace, Esc)
|
|
21
|
+
- Overlay with the suggestions component by default
|
|
22
|
+
- Zero dependencies
|
|
23
|
+
- Cross selection
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
You can install the package via npm:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
npm install @markput/react
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Contributing
|
|
34
|
+
|
|
35
|
+
If you want to contribute, you are welcome! Create an issue or start a discussion.
|
package/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._Container_1lmfr_1{min-height:1.4em}._Container_1lmfr_1 span{outline:none;white-space:pre-wrap}._Suggestions_1lmfr_10{border:1px solid #ccc;max-height:186px;overflow-y:auto;padding-left:0;position:fixed;background:#fff;width:fit-content;min-width:100px;margin-top:0;margin-bottom:0;transition:1.1s ease-out;filter:blur(0);transform:scale(1);opacity:1;visibility:visible;color:#000;border-radius:4%;box-shadow:0 3px 6px -2px #0009}._Suggestions_1lmfr_10 li{padding:.5rem}._Suggestions_1lmfr_10 li:hover,._suggestionActive_1lmfr_38{background-color:#cce9ff;color:#2589f5;cursor:pointer}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { annotate } from '@markput/core';
|
|
2
|
+
import type { ComponentType } from 'react';
|
|
3
|
+
import type { CoreMarkputProps } from '@markput/core';
|
|
4
|
+
import type { CoreOption } from '@markput/core';
|
|
5
|
+
import type { CSSProperties } from 'react';
|
|
6
|
+
import { denote } from '@markput/core';
|
|
7
|
+
import type { DependencyList } from 'react';
|
|
8
|
+
import type { ElementType } from 'react';
|
|
9
|
+
import type { EventKey } from '@markput/core';
|
|
10
|
+
import type { ForwardedRef } from 'react';
|
|
11
|
+
import type { HTMLAttributes } from 'react';
|
|
12
|
+
import type { Listener } from '@markput/core';
|
|
13
|
+
import { MarkToken } from '@markput/core';
|
|
14
|
+
import { Markup } from '@markput/core';
|
|
15
|
+
import type { OverlayMatch } from '@markput/core';
|
|
16
|
+
import type { OverlayTrigger } from '@markput/core';
|
|
17
|
+
import type { ReactNode } from 'react';
|
|
18
|
+
import type { RefObject } from 'react';
|
|
19
|
+
import type { Store } from '@markput/core';
|
|
20
|
+
import { TextToken } from '@markput/core';
|
|
21
|
+
import { Token } from '@markput/core';
|
|
22
|
+
|
|
23
|
+
export { annotate }
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Data attributes with automatic camelCase to kebab-case conversion
|
|
27
|
+
*/
|
|
28
|
+
declare type DataAttributes = Record<`data${Capitalize<string>}`, string | number | boolean | undefined>;
|
|
29
|
+
|
|
30
|
+
export { denote }
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @function
|
|
34
|
+
*/
|
|
35
|
+
export declare const MarkedInput: MarkedInputComponent;
|
|
36
|
+
|
|
37
|
+
export declare interface MarkedInputComponent {
|
|
38
|
+
<TMarkProps = MarkProps, TOverlayProps = OverlayProps>(props: MarkedInputProps<TMarkProps, TOverlayProps>): JSX.Element | null;
|
|
39
|
+
displayName?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export declare interface MarkedInputHandler {
|
|
43
|
+
/** Container element */
|
|
44
|
+
readonly container: HTMLDivElement | null;
|
|
45
|
+
/** Overlay element if exists */
|
|
46
|
+
readonly overlay: HTMLElement | null;
|
|
47
|
+
focus(): void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Props for MarkedInput component.
|
|
52
|
+
*
|
|
53
|
+
* @template TMarkProps - Type of props for the global Mark component
|
|
54
|
+
* @template TOverlayProps - Type of props for the global Overlay component
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* <MarkedInput<ChipProps>
|
|
59
|
+
* Mark={Chip}
|
|
60
|
+
* options={[{
|
|
61
|
+
* markup: '@[__value__]',
|
|
62
|
+
* mark: { label: 'Click me' }
|
|
63
|
+
* }]}
|
|
64
|
+
* />
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare interface MarkedInputProps<TMarkProps = MarkProps, TOverlayProps = OverlayProps> extends CoreMarkputProps {
|
|
68
|
+
/** Ref to handler */
|
|
69
|
+
ref?: ForwardedRef<MarkedInputHandler>;
|
|
70
|
+
/** Global component used for rendering markups (fallback for option.mark.slot) */
|
|
71
|
+
Mark?: ComponentType<TMarkProps>;
|
|
72
|
+
/** Global component used for rendering overlays (fallback for option.overlay.slot) */
|
|
73
|
+
Overlay?: ComponentType<TOverlayProps>;
|
|
74
|
+
/**
|
|
75
|
+
* Configuration options for markups and overlays.
|
|
76
|
+
* Each option can specify its own slot component via mark.slot or overlay.slot.
|
|
77
|
+
* Falls back to global Mark/Overlay components when not specified.
|
|
78
|
+
*/
|
|
79
|
+
options?: Option_2<TMarkProps, TOverlayProps>[];
|
|
80
|
+
/** Additional classes */
|
|
81
|
+
className?: string;
|
|
82
|
+
/** Additional style */
|
|
83
|
+
style?: CSSProperties;
|
|
84
|
+
/**
|
|
85
|
+
* Override internal components using slots
|
|
86
|
+
* @example
|
|
87
|
+
* slots={{ container: 'div', span: 'span' }}
|
|
88
|
+
*/
|
|
89
|
+
slots?: Slots;
|
|
90
|
+
/**
|
|
91
|
+
* Props to pass to slot components
|
|
92
|
+
* @example
|
|
93
|
+
* slotProps={{ container: { onKeyDown: handler }, span: { className: 'custom' } }}
|
|
94
|
+
*/
|
|
95
|
+
slotProps?: SlotProps;
|
|
96
|
+
/**
|
|
97
|
+
* Events that trigger overlay display
|
|
98
|
+
* @default 'change'
|
|
99
|
+
*/
|
|
100
|
+
showOverlayOn?: OverlayTrigger;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export declare class MarkHandler<T extends HTMLElement = HTMLElement> {
|
|
104
|
+
#private;
|
|
105
|
+
readonly ref: RefObject<T>;
|
|
106
|
+
readOnly?: boolean;
|
|
107
|
+
constructor(param: {
|
|
108
|
+
ref: RefObject<T>;
|
|
109
|
+
store: Store;
|
|
110
|
+
token: MarkToken;
|
|
111
|
+
});
|
|
112
|
+
/** Displayed text of the mark */
|
|
113
|
+
get content(): string;
|
|
114
|
+
set content(value: string);
|
|
115
|
+
/** Data value associated with the mark */
|
|
116
|
+
get value(): string | undefined;
|
|
117
|
+
set value(value: string | undefined);
|
|
118
|
+
/** Optional metadata for the mark */
|
|
119
|
+
get meta(): string | undefined;
|
|
120
|
+
set meta(value: string | undefined);
|
|
121
|
+
/** Nesting depth (0 for root-level marks) */
|
|
122
|
+
get depth(): number;
|
|
123
|
+
/** Whether this mark has nested children */
|
|
124
|
+
get hasChildren(): boolean;
|
|
125
|
+
/** Parent mark token (undefined for root-level marks) */
|
|
126
|
+
get parent(): MarkToken | undefined;
|
|
127
|
+
/** Child tokens of this mark */
|
|
128
|
+
get tokens(): Token[];
|
|
129
|
+
/** Update multiple properties in a single operation */
|
|
130
|
+
change: (props: {
|
|
131
|
+
content: string;
|
|
132
|
+
value?: string;
|
|
133
|
+
meta?: string;
|
|
134
|
+
}) => void;
|
|
135
|
+
/** Delete this mark from the editor */
|
|
136
|
+
remove: () => void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
declare interface MarkOptions {
|
|
140
|
+
/**
|
|
141
|
+
* @default false
|
|
142
|
+
*/
|
|
143
|
+
controlled?: boolean;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Props passed to Mark components.
|
|
148
|
+
*/
|
|
149
|
+
export declare interface MarkProps {
|
|
150
|
+
/** Custom component to render this mark */
|
|
151
|
+
slot?: ComponentType<MarkProps>;
|
|
152
|
+
/** Main content value of the mark */
|
|
153
|
+
value?: string;
|
|
154
|
+
/** Additional metadata for the mark */
|
|
155
|
+
meta?: string;
|
|
156
|
+
/** Nested content as string (raw, unparsed) */
|
|
157
|
+
nested?: string;
|
|
158
|
+
/** Rendered children content (ReactNode) for nested marks */
|
|
159
|
+
children?: ReactNode;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export { MarkToken }
|
|
163
|
+
|
|
164
|
+
export { Markup }
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* React-specific markup option for defining mark behavior and styling.
|
|
168
|
+
*
|
|
169
|
+
* @template TMarkProps - Type of props for the mark component
|
|
170
|
+
* @template TOverlayProps - Type of props for the overlay component
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* const option: Option<ChipProps> = {
|
|
174
|
+
* markup: '@[__value__]',
|
|
175
|
+
* mark: { slot: Chip, label: 'Click' }
|
|
176
|
+
* }
|
|
177
|
+
*/
|
|
178
|
+
declare interface Option_2<TMarkProps = MarkProps, TOverlayProps = OverlayProps> extends CoreOption {
|
|
179
|
+
/**
|
|
180
|
+
* Props for the mark component.
|
|
181
|
+
* Can be a static object or a function that transforms MarkProps.
|
|
182
|
+
*/
|
|
183
|
+
mark?: TMarkProps | ((props: MarkProps) => TMarkProps);
|
|
184
|
+
/**
|
|
185
|
+
* Props for the overlay component.
|
|
186
|
+
*/
|
|
187
|
+
overlay?: TOverlayProps;
|
|
188
|
+
}
|
|
189
|
+
export { Option_2 as Option }
|
|
190
|
+
|
|
191
|
+
export declare interface OverlayHandler {
|
|
192
|
+
/**
|
|
193
|
+
* Style with caret absolute position. Used for placing an overlay.
|
|
194
|
+
*/
|
|
195
|
+
style: {
|
|
196
|
+
left: number;
|
|
197
|
+
top: number;
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* Used for close overlay.
|
|
201
|
+
*/
|
|
202
|
+
close: () => void;
|
|
203
|
+
/**
|
|
204
|
+
* Used for insert an annotation instead a triggered value.
|
|
205
|
+
*/
|
|
206
|
+
select: (value: {
|
|
207
|
+
value: string;
|
|
208
|
+
meta?: string;
|
|
209
|
+
}) => void;
|
|
210
|
+
/**
|
|
211
|
+
* Overlay match details
|
|
212
|
+
*/
|
|
213
|
+
match: OverlayMatch<Option_2>;
|
|
214
|
+
ref: RefObject<HTMLElement>;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Props for Overlay components.
|
|
219
|
+
*/
|
|
220
|
+
export declare interface OverlayProps {
|
|
221
|
+
/** Custom component to render this overlay */
|
|
222
|
+
slot?: ComponentType<OverlayProps>;
|
|
223
|
+
/** Trigger character(s) that activate the overlay */
|
|
224
|
+
trigger?: string;
|
|
225
|
+
/** Data array for suggestions/autocomplete */
|
|
226
|
+
data?: string[];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Props for each slot component
|
|
231
|
+
*/
|
|
232
|
+
declare interface SlotProps {
|
|
233
|
+
/** Props to pass to the container slot */
|
|
234
|
+
container?: HTMLAttributes<HTMLDivElement> & DataAttributes;
|
|
235
|
+
/** Props to pass to the span slot */
|
|
236
|
+
span?: HTMLAttributes<HTMLSpanElement> & DataAttributes;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Available slots for customizing MarkedInput internal components
|
|
241
|
+
*/
|
|
242
|
+
declare interface Slots {
|
|
243
|
+
/** Root container component */
|
|
244
|
+
container?: ElementType<HTMLAttributes<HTMLDivElement>>;
|
|
245
|
+
/** Text span component for rendering text tokens */
|
|
246
|
+
span?: ElementType<HTMLAttributes<HTMLSpanElement>>;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export { TextToken }
|
|
250
|
+
|
|
251
|
+
export { Token }
|
|
252
|
+
|
|
253
|
+
export declare function useListener<T>(key: EventKey<T>, listener: Listener<T>, deps?: DependencyList): void;
|
|
254
|
+
|
|
255
|
+
export declare function useListener<K extends keyof HTMLElementEventMap>(key: K, listener: Listener<HTMLElementEventMap[K]>, deps?: DependencyList): void;
|
|
256
|
+
|
|
257
|
+
export declare const useMark: <T extends HTMLElement = HTMLElement>(options?: MarkOptions) => MarkHandler<T>;
|
|
258
|
+
|
|
259
|
+
export declare function useOverlay(): OverlayHandler;
|
|
260
|
+
|
|
261
|
+
export { }
|