@ai-react-markdown/core 1.0.1 → 1.0.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/README.md +407 -0
- package/dist/index.cjs +41 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +421 -38
- package/dist/index.d.ts +421 -38
- package/dist/index.js +37 -16
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ import { Components } from 'react-markdown';
|
|
|
12
12
|
* @module defs
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Custom component overrides for the markdown renderer.
|
|
17
|
+
* Alias for `react-markdown`'s `Components` type, re-exported under the
|
|
18
|
+
* library's `AIMarkdown` naming convention so consumers don't need a
|
|
19
|
+
* direct `react-markdown` dependency for type imports.
|
|
20
|
+
*/
|
|
21
|
+
type AIMarkdownCustomComponents = Components;
|
|
15
22
|
/**
|
|
16
23
|
* Extra markdown syntax extensions beyond standard GFM.
|
|
17
24
|
* Enable or disable these via {@link AIMarkdownRenderConfig.extraSyntaxSupported}.
|
|
@@ -47,8 +54,13 @@ interface AIMarkdownRenderConfig {
|
|
|
47
54
|
displayOptimizeAbilities: AIMarkdownRenderDisplayOptimizeAbility[];
|
|
48
55
|
}
|
|
49
56
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
57
|
+
* Sensible default configuration with all extensions and optimizations enabled.
|
|
58
|
+
* Frozen to prevent accidental mutation.
|
|
59
|
+
*/
|
|
60
|
+
declare const defaultAIMarkdownRenderConfig: AIMarkdownRenderConfig;
|
|
61
|
+
/**
|
|
62
|
+
* Arbitrary metadata that consumers can pass through a dedicated React context.
|
|
63
|
+
* Custom renderers can access this via the {@link useAIMarkdownMetadata} hook.
|
|
52
64
|
*/
|
|
53
65
|
interface AIMarkdownMetadata extends Record<string, any> {
|
|
54
66
|
}
|
|
@@ -74,48 +86,373 @@ interface AIMarkdownTypographyProps extends PropsWithChildren {
|
|
|
74
86
|
/** React component type for the typography wrapper. */
|
|
75
87
|
type AIMarkdownTypographyComponent = ComponentType<AIMarkdownTypographyProps>;
|
|
76
88
|
/** Props accepted by an optional extra style wrapper component. */
|
|
77
|
-
interface
|
|
89
|
+
interface AIMarkdownExtraStylesProps extends PropsWithChildren {
|
|
78
90
|
}
|
|
79
91
|
/** React component type for an optional extra style wrapper. */
|
|
80
|
-
type
|
|
92
|
+
type AIMarkdownExtraStylesComponent = ComponentType<AIMarkdownExtraStylesProps>;
|
|
81
93
|
/**
|
|
82
94
|
* Immutable render state exposed to all descendant components via React context.
|
|
83
95
|
* Access this with the {@link useAIMarkdownRenderState} hook.
|
|
84
96
|
*
|
|
97
|
+
* Metadata is provided via a separate context — use {@link useAIMarkdownMetadata} instead.
|
|
98
|
+
*
|
|
85
99
|
* @typeParam TConfig - Render configuration type (defaults to {@link AIMarkdownRenderConfig}).
|
|
86
|
-
* @typeParam TMetadata - Metadata type (defaults to {@link AIMarkdownMetadata}).
|
|
87
100
|
*/
|
|
88
|
-
interface AIMarkdownRenderState<TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig
|
|
101
|
+
interface AIMarkdownRenderState<TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig> {
|
|
89
102
|
/** Whether the content is currently being streamed (e.g. from an LLM). */
|
|
90
103
|
streaming: boolean;
|
|
91
104
|
/** Resolved CSS font-size value. */
|
|
92
105
|
fontSize: string;
|
|
106
|
+
/** Active typography variant. */
|
|
107
|
+
variant: AIMarkdownVariant;
|
|
108
|
+
/** Active color scheme. */
|
|
109
|
+
colorScheme: AIMarkdownColorScheme;
|
|
93
110
|
/** Active render configuration. */
|
|
94
111
|
config: TConfig;
|
|
95
|
-
/** Optional consumer-provided metadata. */
|
|
96
|
-
metadata?: TMetadata;
|
|
97
112
|
}
|
|
98
113
|
|
|
114
|
+
// Sourced from type-fest v5.4.4
|
|
115
|
+
// https://github.com/sindresorhus/type-fest
|
|
116
|
+
// SPDX-License-Identifier: (MIT OR CC0-1.0)
|
|
117
|
+
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
|
118
|
+
|
|
99
119
|
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
120
|
+
Returns a boolean for whether the given type is `never`.
|
|
121
|
+
|
|
122
|
+
@link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
|
|
123
|
+
@link https://stackoverflow.com/a/53984913/10292952
|
|
124
|
+
@link https://www.zhenghao.io/posts/ts-never
|
|
125
|
+
|
|
126
|
+
Useful in type utilities, such as checking if something does not occur.
|
|
127
|
+
|
|
128
|
+
@example
|
|
129
|
+
```
|
|
130
|
+
import type {IsNever, And} from 'type-fest';
|
|
131
|
+
|
|
132
|
+
type A = IsNever<never>;
|
|
133
|
+
//=> true
|
|
134
|
+
|
|
135
|
+
type B = IsNever<any>;
|
|
136
|
+
//=> false
|
|
137
|
+
|
|
138
|
+
type C = IsNever<unknown>;
|
|
139
|
+
//=> false
|
|
140
|
+
|
|
141
|
+
type D = IsNever<never[]>;
|
|
142
|
+
//=> false
|
|
143
|
+
|
|
144
|
+
type E = IsNever<object>;
|
|
145
|
+
//=> false
|
|
146
|
+
|
|
147
|
+
type F = IsNever<string>;
|
|
148
|
+
//=> false
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
@example
|
|
152
|
+
```
|
|
153
|
+
import type {IsNever} from 'type-fest';
|
|
154
|
+
|
|
155
|
+
type IsTrue<T> = T extends true ? true : false;
|
|
156
|
+
|
|
157
|
+
// When a distributive conditional is instantiated with `never`, the entire conditional results in `never`.
|
|
158
|
+
type A = IsTrue<never>;
|
|
159
|
+
//=> never
|
|
160
|
+
|
|
161
|
+
// If you don't want that behaviour, you can explicitly add an `IsNever` check before the distributive conditional.
|
|
162
|
+
type IsTrueFixed<T> =
|
|
163
|
+
IsNever<T> extends true ? false : T extends true ? true : false;
|
|
164
|
+
|
|
165
|
+
type B = IsTrueFixed<never>;
|
|
166
|
+
//=> false
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
@category Type Guard
|
|
170
|
+
@category Utilities
|
|
171
|
+
*/
|
|
172
|
+
type IsNever<T> = [T] extends [never] ? true : false;
|
|
173
|
+
|
|
174
|
+
// Sourced from type-fest v5.4.4
|
|
175
|
+
// https://github.com/sindresorhus/type-fest
|
|
176
|
+
// SPDX-License-Identifier: (MIT OR CC0-1.0)
|
|
177
|
+
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
104
181
|
/**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
182
|
+
Merges user specified options with default options.
|
|
183
|
+
|
|
184
|
+
@example
|
|
185
|
+
```
|
|
186
|
+
type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
|
|
187
|
+
type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: false};
|
|
188
|
+
type SpecifiedOptions = {leavesOnly: true};
|
|
189
|
+
|
|
190
|
+
type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
|
|
191
|
+
//=> {maxRecursionDepth: 10; leavesOnly: true}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
@example
|
|
195
|
+
```
|
|
196
|
+
// Complains if default values are not provided for optional options
|
|
197
|
+
|
|
198
|
+
type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
|
|
199
|
+
type DefaultPathsOptions = {maxRecursionDepth: 10};
|
|
200
|
+
type SpecifiedOptions = {};
|
|
201
|
+
|
|
202
|
+
type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
|
|
203
|
+
// ~~~~~~~~~~~~~~~~~~~
|
|
204
|
+
// Property 'leavesOnly' is missing in type 'DefaultPathsOptions' but required in type '{ maxRecursionDepth: number; leavesOnly: boolean; }'.
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
@example
|
|
208
|
+
```
|
|
209
|
+
// Complains if an option's default type does not conform to the expected type
|
|
210
|
+
|
|
211
|
+
type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
|
|
212
|
+
type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: 'no'};
|
|
213
|
+
type SpecifiedOptions = {};
|
|
214
|
+
|
|
215
|
+
type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
|
|
216
|
+
// ~~~~~~~~~~~~~~~~~~~
|
|
217
|
+
// Types of property 'leavesOnly' are incompatible. Type 'string' is not assignable to type 'boolean'.
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
@example
|
|
221
|
+
```
|
|
222
|
+
// Complains if an option's specified type does not conform to the expected type
|
|
223
|
+
|
|
224
|
+
type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
|
|
225
|
+
type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: false};
|
|
226
|
+
type SpecifiedOptions = {leavesOnly: 'yes'};
|
|
227
|
+
|
|
228
|
+
type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
|
|
229
|
+
// ~~~~~~~~~~~~~~~~
|
|
230
|
+
// Types of property 'leavesOnly' are incompatible. Type 'string' is not assignable to type 'boolean'.
|
|
231
|
+
```
|
|
232
|
+
*/
|
|
233
|
+
type ApplyDefaultOptions<
|
|
234
|
+
Options extends object,
|
|
235
|
+
Defaults extends Simplify<
|
|
236
|
+
Omit<Required<Options>, RequiredKeysOf<Options>> & Partial<Record<RequiredKeysOf<Options>, never>>
|
|
237
|
+
>,
|
|
238
|
+
SpecifiedOptions extends Options,
|
|
239
|
+
> = If<
|
|
240
|
+
IsAny<SpecifiedOptions>,
|
|
241
|
+
Defaults,
|
|
242
|
+
If<
|
|
243
|
+
IsNever<SpecifiedOptions>,
|
|
244
|
+
Defaults,
|
|
245
|
+
Simplify<
|
|
246
|
+
Merge<
|
|
247
|
+
Defaults,
|
|
248
|
+
{
|
|
249
|
+
[Key in keyof SpecifiedOptions as Key extends OptionalKeysOf<Options>
|
|
250
|
+
? undefined extends SpecifiedOptions[Key]
|
|
251
|
+
? never
|
|
252
|
+
: Key
|
|
253
|
+
: Key]: SpecifiedOptions[Key];
|
|
254
|
+
}
|
|
255
|
+
> &
|
|
256
|
+
Required<Options>
|
|
257
|
+
>
|
|
258
|
+
>
|
|
259
|
+
>; // `& Required<Options>` ensures that `ApplyDefaultOptions<SomeOption, ...>` is always assignable to `Required<SomeOption>`
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
Matches any primitive, `void`, `Date`, or `RegExp` value.
|
|
263
|
+
*/
|
|
264
|
+
type BuiltIns = Primitive | void | Date | RegExp;
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
Test if the given function has multiple call signatures.
|
|
268
|
+
|
|
269
|
+
Needed to handle the case of a single call signature with properties.
|
|
270
|
+
|
|
271
|
+
Multiple call signatures cannot currently be supported due to a TypeScript limitation.
|
|
272
|
+
@see https://github.com/microsoft/TypeScript/issues/29732
|
|
273
|
+
*/
|
|
274
|
+
type HasMultipleCallSignatures<T extends (...arguments_: any[]) => unknown> = T extends {
|
|
275
|
+
(...arguments_: infer A): unknown;
|
|
276
|
+
(...arguments_: infer B): unknown;
|
|
277
|
+
}
|
|
278
|
+
? B extends A
|
|
279
|
+
? A extends B
|
|
280
|
+
? false
|
|
281
|
+
: true
|
|
282
|
+
: true
|
|
283
|
+
: false;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
@see {@link PartialDeep}
|
|
287
|
+
*/
|
|
288
|
+
type PartialDeepOptions = {
|
|
289
|
+
/**
|
|
290
|
+
Whether to affect the individual elements of arrays and tuples.
|
|
291
|
+
|
|
292
|
+
@default false
|
|
293
|
+
*/
|
|
294
|
+
readonly recurseIntoArrays?: boolean;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
Allows `undefined` values in non-tuple arrays.
|
|
298
|
+
|
|
299
|
+
- When set to `true`, elements of non-tuple arrays can be `undefined`.
|
|
300
|
+
- When set to `false`, only explicitly defined elements are allowed in non-tuple arrays, ensuring stricter type checking.
|
|
301
|
+
|
|
302
|
+
@default false
|
|
303
|
+
|
|
304
|
+
@example
|
|
305
|
+
You can allow `undefined` values in non-tuple arrays by passing `{recurseIntoArrays: true; allowUndefinedInNonTupleArrays: true}` as the second type argument:
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
import type {PartialDeep} from 'type-fest';
|
|
309
|
+
|
|
310
|
+
type Settings = {
|
|
311
|
+
languages: string[];
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
declare const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true; allowUndefinedInNonTupleArrays: true}>;
|
|
315
|
+
|
|
316
|
+
partialSettings.languages = [undefined]; // OK
|
|
317
|
+
```
|
|
318
|
+
*/
|
|
319
|
+
readonly allowUndefinedInNonTupleArrays?: boolean;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
type DefaultPartialDeepOptions = {
|
|
323
|
+
recurseIntoArrays: false;
|
|
324
|
+
allowUndefinedInNonTupleArrays: false;
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
Create a type from another type with all keys and nested keys set to optional.
|
|
329
|
+
|
|
330
|
+
Use-cases:
|
|
331
|
+
- Merging a default settings/config object with another object, the second object would be a deep partial of the default object.
|
|
332
|
+
- Mocking and testing complex entities, where populating an entire object with its keys would be redundant in terms of the mock or test.
|
|
333
|
+
|
|
334
|
+
@example
|
|
335
|
+
```
|
|
336
|
+
import type {PartialDeep} from 'type-fest';
|
|
337
|
+
|
|
338
|
+
let settings = {
|
|
339
|
+
textEditor: {
|
|
340
|
+
fontSize: 14,
|
|
341
|
+
fontColor: '#000000',
|
|
342
|
+
fontWeight: 400,
|
|
343
|
+
},
|
|
344
|
+
autocomplete: false,
|
|
345
|
+
autosave: true,
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
const applySavedSettings = (savedSettings: PartialDeep<typeof settings>) => (
|
|
349
|
+
{...settings, ...savedSettings, textEditor: {...settings.textEditor, ...savedSettings.textEditor}}
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
settings = applySavedSettings({textEditor: {fontWeight: 500}});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
By default, this does not affect elements in array and tuple types. You can change this by passing `{recurseIntoArrays: true}` as the second type argument:
|
|
356
|
+
|
|
357
|
+
```
|
|
358
|
+
import type {PartialDeep} from 'type-fest';
|
|
359
|
+
|
|
360
|
+
type Shape = {
|
|
361
|
+
dimensions: [number, number];
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
const partialShape: PartialDeep<Shape, {recurseIntoArrays: true}> = {
|
|
365
|
+
dimensions: [], // OK
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
partialShape.dimensions = [15]; // OK
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
@see {@link PartialDeepOptions}
|
|
372
|
+
|
|
373
|
+
@category Object
|
|
374
|
+
@category Array
|
|
375
|
+
@category Set
|
|
376
|
+
@category Map
|
|
377
|
+
*/
|
|
378
|
+
type PartialDeep<T, Options extends PartialDeepOptions = {}> = _PartialDeep<
|
|
379
|
+
T,
|
|
380
|
+
ApplyDefaultOptions<PartialDeepOptions, DefaultPartialDeepOptions, Options>
|
|
381
|
+
>;
|
|
382
|
+
|
|
383
|
+
type _PartialDeep<T, Options extends Required<PartialDeepOptions>> = T extends
|
|
384
|
+
| BuiltIns
|
|
385
|
+
| (new (...arguments_: any[]) => unknown)
|
|
386
|
+
? T
|
|
387
|
+
: T extends Map<infer KeyType, infer ValueType>
|
|
388
|
+
? PartialMapDeep<KeyType, ValueType, Options>
|
|
389
|
+
: T extends Set<infer ItemType>
|
|
390
|
+
? PartialSetDeep<ItemType, Options>
|
|
391
|
+
: T extends ReadonlyMap<infer KeyType, infer ValueType>
|
|
392
|
+
? PartialReadonlyMapDeep<KeyType, ValueType, Options>
|
|
393
|
+
: T extends ReadonlySet<infer ItemType>
|
|
394
|
+
? PartialReadonlySetDeep<ItemType, Options>
|
|
395
|
+
: T extends (...arguments_: any[]) => unknown
|
|
396
|
+
? IsNever<keyof T> extends true
|
|
397
|
+
? T // For functions with no properties
|
|
398
|
+
: HasMultipleCallSignatures<T> extends true
|
|
399
|
+
? T
|
|
400
|
+
: ((...arguments_: Parameters<T>) => ReturnType<T>) & PartialObjectDeep<T, Options>
|
|
401
|
+
: T extends object
|
|
402
|
+
? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
|
|
403
|
+
? Options['recurseIntoArrays'] extends true
|
|
404
|
+
? ItemType[] extends T // Test for arrays (non-tuples) specifically
|
|
405
|
+
? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
|
|
406
|
+
? ReadonlyArray<
|
|
407
|
+
_PartialDeep<
|
|
408
|
+
Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined,
|
|
409
|
+
Options
|
|
410
|
+
>
|
|
411
|
+
>
|
|
412
|
+
: Array<
|
|
413
|
+
_PartialDeep<
|
|
414
|
+
Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined,
|
|
415
|
+
Options
|
|
416
|
+
>
|
|
417
|
+
>
|
|
418
|
+
: PartialObjectDeep<T, Options> // Tuples behave properly
|
|
419
|
+
: T // If they don't opt into array testing, just use the original type
|
|
420
|
+
: PartialObjectDeep<T, Options>
|
|
421
|
+
: unknown;
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`.
|
|
425
|
+
*/
|
|
426
|
+
type PartialMapDeep<KeyType, ValueType, Options extends Required<PartialDeepOptions>> = {} & Map<
|
|
427
|
+
_PartialDeep<KeyType, Options>,
|
|
428
|
+
_PartialDeep<ValueType, Options>
|
|
429
|
+
>;
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
Same as `PartialDeep`, but accepts only `Set`s as inputs. Internal helper for `PartialDeep`.
|
|
433
|
+
*/
|
|
434
|
+
type PartialSetDeep<T, Options extends Required<PartialDeepOptions>> = {} & Set<_PartialDeep<T, Options>>;
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
Same as `PartialDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `PartialDeep`.
|
|
438
|
+
*/
|
|
439
|
+
type PartialReadonlyMapDeep<KeyType, ValueType, Options extends Required<PartialDeepOptions>> = {} & ReadonlyMap<
|
|
440
|
+
_PartialDeep<KeyType, Options>,
|
|
441
|
+
_PartialDeep<ValueType, Options>
|
|
442
|
+
>;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
Same as `PartialDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `PartialDeep`.
|
|
446
|
+
*/
|
|
447
|
+
type PartialReadonlySetDeep<T, Options extends Required<PartialDeepOptions>> = {} & ReadonlySet<
|
|
448
|
+
_PartialDeep<T, Options>
|
|
449
|
+
>;
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`.
|
|
453
|
+
*/
|
|
454
|
+
type PartialObjectDeep<ObjectType extends object, Options extends Required<PartialDeepOptions>> = {
|
|
455
|
+
[KeyType in keyof ObjectType]?: _PartialDeep<ObjectType[KeyType], Options>;
|
|
119
456
|
};
|
|
120
457
|
|
|
121
458
|
/**
|
|
@@ -125,8 +462,7 @@ type DeepPartial<T> = {
|
|
|
125
462
|
* Throws if called outside the provider boundary.
|
|
126
463
|
*
|
|
127
464
|
* @typeParam TConfig - Expected configuration shape (defaults to {@link AIMarkdownRenderConfig}).
|
|
128
|
-
* @
|
|
129
|
-
* @returns The current render state.
|
|
465
|
+
* @returns The current render state (does not include metadata — use {@link useAIMarkdownMetadata} for that).
|
|
130
466
|
*
|
|
131
467
|
* @example
|
|
132
468
|
* ```tsx
|
|
@@ -136,13 +472,35 @@ type DeepPartial<T> = {
|
|
|
136
472
|
* }
|
|
137
473
|
* ```
|
|
138
474
|
*/
|
|
139
|
-
declare function useAIMarkdownRenderState<TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig
|
|
475
|
+
declare function useAIMarkdownRenderState<TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig>(): AIMarkdownRenderState<TConfig>;
|
|
476
|
+
/**
|
|
477
|
+
* Access the current metadata from within the `<AIMarkdown>` tree.
|
|
478
|
+
*
|
|
479
|
+
* Metadata lives in a separate React context so that changes to metadata
|
|
480
|
+
* do not cause re-renders in components that only consume render state
|
|
481
|
+
* (e.g. {@link MarkdownContent}).
|
|
482
|
+
*
|
|
483
|
+
* @typeParam TMetadata - Expected metadata shape (defaults to {@link AIMarkdownMetadata}).
|
|
484
|
+
* @returns The current metadata, or `undefined` if none was provided.
|
|
485
|
+
*/
|
|
486
|
+
declare function useAIMarkdownMetadata<TMetadata extends AIMarkdownMetadata = AIMarkdownMetadata>(): TMetadata | undefined;
|
|
140
487
|
/** Props for {@link AIMarkdownRenderStateProvider}. */
|
|
141
|
-
interface AIMarkdownRenderStateProviderProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig
|
|
488
|
+
interface AIMarkdownRenderStateProviderProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig> extends PropsWithChildren {
|
|
142
489
|
streaming: boolean;
|
|
143
490
|
fontSize: string;
|
|
144
|
-
|
|
145
|
-
|
|
491
|
+
variant: AIMarkdownVariant;
|
|
492
|
+
colorScheme: AIMarkdownColorScheme;
|
|
493
|
+
/**
|
|
494
|
+
* Base default config to merge against. When omitted, falls back to
|
|
495
|
+
* {@link defaultAIMarkdownRenderConfig}. Sub-packages (e.g. mantine) can
|
|
496
|
+
* pass their own extended defaults here.
|
|
497
|
+
*/
|
|
498
|
+
defaultConfig?: TConfig;
|
|
499
|
+
/** Partial config that will be deep-merged with the default config. */
|
|
500
|
+
config?: PartialDeep<TConfig>;
|
|
501
|
+
}
|
|
502
|
+
/** Props for {@link AIMarkdownMetadataProvider}. */
|
|
503
|
+
interface AIMarkdownMetadataProviderProps<TMetadata extends AIMarkdownMetadata = AIMarkdownMetadata> extends PropsWithChildren {
|
|
146
504
|
metadata?: TMetadata;
|
|
147
505
|
}
|
|
148
506
|
|
|
@@ -168,13 +526,38 @@ interface AIMarkdownRenderStateProviderProps<TConfig extends AIMarkdownRenderCon
|
|
|
168
526
|
*/
|
|
169
527
|
type AIMDContentPreprocessor = (content: string) => string;
|
|
170
528
|
|
|
529
|
+
/**
|
|
530
|
+
* Hook for referential stability of deep-equal values.
|
|
531
|
+
*
|
|
532
|
+
* @module hooks/useStableValue
|
|
533
|
+
*/
|
|
534
|
+
/**
|
|
535
|
+
* Returns a referentially stable version of `value`.
|
|
536
|
+
*
|
|
537
|
+
* On each render the new value is deep-compared (via `lodash/isEqual`) against
|
|
538
|
+
* the previous one. If they are structurally equal the *previous* reference is
|
|
539
|
+
* returned, preventing unnecessary re-renders in downstream `useMemo` / `useEffect`
|
|
540
|
+
* consumers that depend on reference equality.
|
|
541
|
+
*
|
|
542
|
+
* @typeParam T - The value type.
|
|
543
|
+
* @param value - The potentially new value to stabilize.
|
|
544
|
+
* @returns The previous reference when deep-equal, otherwise the new value.
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```tsx
|
|
548
|
+
* const stableConfig = useStableValue(config);
|
|
549
|
+
* // stableConfig keeps the same reference as long as config is deep-equal.
|
|
550
|
+
* ```
|
|
551
|
+
*/
|
|
552
|
+
declare function useStableValue<T>(value: T): T;
|
|
553
|
+
|
|
171
554
|
/**
|
|
172
555
|
* Props for the `<AIMarkdown>` component.
|
|
173
556
|
*
|
|
174
557
|
* @typeParam TConfig - Custom render configuration type (extends {@link AIMarkdownRenderConfig}).
|
|
175
558
|
* @typeParam TRenderData - Custom metadata type (extends {@link AIMarkdownMetadata}).
|
|
176
559
|
*/
|
|
177
|
-
interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig, TRenderData extends AIMarkdownMetadata = AIMarkdownMetadata> extends Omit<AIMarkdownRenderStateProviderProps<TConfig
|
|
560
|
+
interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig, TRenderData extends AIMarkdownMetadata = AIMarkdownMetadata> extends Omit<AIMarkdownRenderStateProviderProps<TConfig>, 'fontSize' | 'variant' | 'colorScheme'>, AIMarkdownMetadataProviderProps<TRenderData> {
|
|
178
561
|
/**
|
|
179
562
|
* Base font size for the rendered output.
|
|
180
563
|
* Accepts a CSS length string (e.g. `'14px'`, `'0.875rem'`) or a number
|
|
@@ -193,18 +576,18 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
|
|
|
193
576
|
* Use this to replace the default renderers for specific HTML elements
|
|
194
577
|
* (e.g. code blocks, links, images).
|
|
195
578
|
*/
|
|
196
|
-
customComponents?:
|
|
579
|
+
customComponents?: AIMarkdownCustomComponents;
|
|
197
580
|
/**
|
|
198
581
|
* Typography wrapper component. Receives `fontSize`, `variant`, and `colorScheme`.
|
|
199
582
|
* Defaults to the built-in {@link DefaultTypography}.
|
|
200
583
|
*/
|
|
201
|
-
|
|
584
|
+
Typography?: AIMarkdownTypographyComponent;
|
|
202
585
|
/**
|
|
203
586
|
* Optional extra style wrapper component rendered between the typography
|
|
204
587
|
* wrapper and the markdown content. Useful for injecting additional
|
|
205
588
|
* CSS scope or theme providers.
|
|
206
589
|
*/
|
|
207
|
-
|
|
590
|
+
ExtraStyles?: AIMarkdownExtraStylesComponent;
|
|
208
591
|
/** Typography variant name. Defaults to `'default'`. */
|
|
209
592
|
variant?: AIMarkdownVariant;
|
|
210
593
|
/** Color scheme name. Defaults to `'light'`. */
|
|
@@ -214,7 +597,7 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
|
|
|
214
597
|
* Root component that preprocesses markdown content and renders it through
|
|
215
598
|
* a configurable remark/rehype pipeline wrapped in typography and style layers.
|
|
216
599
|
*/
|
|
217
|
-
declare const AIMarkdownComponent: <TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig, TRenderData extends AIMarkdownMetadata = AIMarkdownMetadata>({ streaming, content, fontSize, contentPreprocessors, customComponents, config, metadata,
|
|
600
|
+
declare const AIMarkdownComponent: <TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig, TRenderData extends AIMarkdownMetadata = AIMarkdownMetadata>({ streaming, content, fontSize, contentPreprocessors, customComponents, defaultConfig, config, metadata, Typography, ExtraStyles, variant, colorScheme, }: AIMarkdownProps<TConfig, TRenderData>) => react_jsx_runtime.JSX.Element;
|
|
218
601
|
declare const _default: typeof AIMarkdownComponent;
|
|
219
602
|
|
|
220
|
-
export { type AIMDContentPreprocessor, type AIMarkdownColorScheme, type
|
|
603
|
+
export { type AIMDContentPreprocessor, type AIMarkdownColorScheme, type AIMarkdownCustomComponents, type AIMarkdownExtraStylesComponent, type AIMarkdownExtraStylesProps, type AIMarkdownMetadata, type AIMarkdownProps, type AIMarkdownRenderConfig, AIMarkdownRenderDisplayOptimizeAbility, AIMarkdownRenderExtraSyntax, type AIMarkdownRenderState, type AIMarkdownTypographyComponent, type AIMarkdownTypographyProps, type AIMarkdownVariant, type PartialDeep, _default as default, defaultAIMarkdownRenderConfig, useAIMarkdownMetadata, useAIMarkdownRenderState, useStableValue };
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@ import { useMemo as useMemo3, memo as memo3 } from "react";
|
|
|
5
5
|
|
|
6
6
|
// src/context.tsx
|
|
7
7
|
import { createContext, useContext, useMemo } from "react";
|
|
8
|
-
import cloneDeep from "lodash/cloneDeep";
|
|
9
|
-
import mergeWith from "lodash/mergeWith";
|
|
8
|
+
import cloneDeep from "lodash-es/cloneDeep";
|
|
9
|
+
import mergeWith from "lodash-es/mergeWith";
|
|
10
10
|
|
|
11
11
|
// src/defs.ts
|
|
12
12
|
var AIMarkdownRenderExtraSyntax = /* @__PURE__ */ ((AIMarkdownRenderExtraSyntax2) => {
|
|
@@ -37,6 +37,7 @@ var defaultAIMarkdownRenderConfig = Object.freeze({
|
|
|
37
37
|
// src/context.tsx
|
|
38
38
|
import { jsx } from "react/jsx-runtime";
|
|
39
39
|
var AIMarkdownRenderStateContext = createContext(null);
|
|
40
|
+
var AIMarkdownMetadataContext = createContext(void 0);
|
|
40
41
|
function useAIMarkdownRenderState() {
|
|
41
42
|
const context = useContext(AIMarkdownRenderStateContext);
|
|
42
43
|
if (!context) {
|
|
@@ -44,30 +45,43 @@ function useAIMarkdownRenderState() {
|
|
|
44
45
|
}
|
|
45
46
|
return context;
|
|
46
47
|
}
|
|
48
|
+
function useAIMarkdownMetadata() {
|
|
49
|
+
return useContext(AIMarkdownMetadataContext);
|
|
50
|
+
}
|
|
47
51
|
var configMergeCustomizer = (_objValue, srcValue, _key, _object, _source, _stack) => {
|
|
48
52
|
if (Array.isArray(srcValue)) {
|
|
49
53
|
return srcValue;
|
|
50
54
|
}
|
|
51
55
|
};
|
|
56
|
+
var AIMarkdownMetadataProvider = ({
|
|
57
|
+
metadata,
|
|
58
|
+
children
|
|
59
|
+
}) => {
|
|
60
|
+
return /* @__PURE__ */ jsx(AIMarkdownMetadataContext.Provider, { value: metadata, children });
|
|
61
|
+
};
|
|
52
62
|
var AIMarkdownRenderStateProvider = ({
|
|
53
63
|
streaming,
|
|
54
64
|
fontSize,
|
|
65
|
+
variant,
|
|
66
|
+
colorScheme,
|
|
67
|
+
defaultConfig,
|
|
55
68
|
config,
|
|
56
|
-
metadata,
|
|
57
69
|
children
|
|
58
70
|
}) => {
|
|
71
|
+
const baseConfig = defaultConfig ?? defaultAIMarkdownRenderConfig;
|
|
59
72
|
const mergedConfig = useMemo(
|
|
60
|
-
() => config ? mergeWith(cloneDeep(
|
|
61
|
-
[config]
|
|
73
|
+
() => config ? mergeWith(cloneDeep(baseConfig), config, configMergeCustomizer) : baseConfig,
|
|
74
|
+
[baseConfig, config]
|
|
62
75
|
);
|
|
63
76
|
const state = useMemo(
|
|
64
77
|
() => Object.freeze({
|
|
65
78
|
streaming,
|
|
66
79
|
fontSize,
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
variant,
|
|
81
|
+
colorScheme,
|
|
82
|
+
config: mergedConfig
|
|
69
83
|
}),
|
|
70
|
-
[streaming, fontSize,
|
|
84
|
+
[streaming, fontSize, variant, colorScheme, mergedConfig]
|
|
71
85
|
);
|
|
72
86
|
return /* @__PURE__ */ jsx(AIMarkdownRenderStateContext.Provider, { value: state, children });
|
|
73
87
|
};
|
|
@@ -339,7 +353,7 @@ var MarkdownContent_default = AIMarkdownContent;
|
|
|
339
353
|
|
|
340
354
|
// src/hooks/useStableValue.ts
|
|
341
355
|
import { useRef, useEffect } from "react";
|
|
342
|
-
import isEqual from "lodash/isEqual";
|
|
356
|
+
import isEqual from "lodash-es/isEqual";
|
|
343
357
|
function useStableValue(value) {
|
|
344
358
|
const ref = useRef(value);
|
|
345
359
|
const prev = ref.current;
|
|
@@ -372,14 +386,16 @@ var AIMarkdownComponent = ({
|
|
|
372
386
|
fontSize,
|
|
373
387
|
contentPreprocessors,
|
|
374
388
|
customComponents,
|
|
389
|
+
defaultConfig,
|
|
375
390
|
config,
|
|
376
391
|
metadata,
|
|
377
|
-
|
|
378
|
-
|
|
392
|
+
Typography = Default_default,
|
|
393
|
+
ExtraStyles,
|
|
379
394
|
variant = "default",
|
|
380
395
|
colorScheme = "light"
|
|
381
396
|
}) => {
|
|
382
397
|
const usedFontSize = fontSize ? typeof fontSize === "number" ? `${fontSize}px` : fontSize : "0.875rem";
|
|
398
|
+
const stableDefaultConfig = useStableValue(defaultConfig);
|
|
383
399
|
const stableConfig = useStableValue(config);
|
|
384
400
|
const stablePreprocessors = useStableValue(contentPreprocessors);
|
|
385
401
|
const stableCustomComponents = useStableValue(customComponents);
|
|
@@ -387,16 +403,18 @@ var AIMarkdownComponent = ({
|
|
|
387
403
|
() => content ? preprocessAIMDContent(content, stablePreprocessors) : content,
|
|
388
404
|
[content, stablePreprocessors]
|
|
389
405
|
);
|
|
390
|
-
return /* @__PURE__ */ jsx4(
|
|
406
|
+
return /* @__PURE__ */ jsx4(AIMarkdownMetadataProvider, { metadata, children: /* @__PURE__ */ jsx4(
|
|
391
407
|
context_default,
|
|
392
408
|
{
|
|
393
409
|
streaming,
|
|
394
410
|
fontSize: usedFontSize,
|
|
411
|
+
variant,
|
|
412
|
+
colorScheme,
|
|
413
|
+
defaultConfig: stableDefaultConfig,
|
|
395
414
|
config: stableConfig,
|
|
396
|
-
|
|
397
|
-
children: /* @__PURE__ */ jsx4(Typography, { fontSize: usedFontSize, variant, colorScheme, children: ExtraStyle ? /* @__PURE__ */ jsx4(ExtraStyle, { children: /* @__PURE__ */ jsx4(MarkdownContent_default, { content: usedContent, customComponents: stableCustomComponents }) }) : /* @__PURE__ */ jsx4(MarkdownContent_default, { content: usedContent, customComponents: stableCustomComponents }) })
|
|
415
|
+
children: /* @__PURE__ */ jsx4(Typography, { fontSize: usedFontSize, variant, colorScheme, children: ExtraStyles ? /* @__PURE__ */ jsx4(ExtraStyles, { children: /* @__PURE__ */ jsx4(MarkdownContent_default, { content: usedContent, customComponents: stableCustomComponents }) }) : /* @__PURE__ */ jsx4(MarkdownContent_default, { content: usedContent, customComponents: stableCustomComponents }) })
|
|
398
416
|
}
|
|
399
|
-
);
|
|
417
|
+
) });
|
|
400
418
|
};
|
|
401
419
|
var AIMarkdown = memo3(AIMarkdownComponent);
|
|
402
420
|
AIMarkdown.displayName = "AIMarkdown";
|
|
@@ -405,6 +423,9 @@ export {
|
|
|
405
423
|
AIMarkdownRenderDisplayOptimizeAbility,
|
|
406
424
|
AIMarkdownRenderExtraSyntax,
|
|
407
425
|
index_default as default,
|
|
408
|
-
|
|
426
|
+
defaultAIMarkdownRenderConfig,
|
|
427
|
+
useAIMarkdownMetadata,
|
|
428
|
+
useAIMarkdownRenderState,
|
|
429
|
+
useStableValue
|
|
409
430
|
};
|
|
410
431
|
//# sourceMappingURL=index.js.map
|