@dreamtree-org/twreact-ui 1.3.1 → 1.3.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.
Files changed (60) hide show
  1. package/DESIGN.md +2 -2
  2. package/README.md +80 -1
  3. package/ai-skills/dreamtree-ui.md +40 -3
  4. package/charts/package.json +5 -0
  5. package/dist/_shared/cn-DPPQUJu1.js +138 -0
  6. package/dist/ai-schema.json +638 -0
  7. package/dist/charts/index.d.ts +9 -0
  8. package/dist/charts/index.d.ts.map +1 -0
  9. package/dist/charts/index.js +769 -0
  10. package/dist/components/charts/AreaChart.d.ts +4 -0
  11. package/dist/components/charts/AreaChart.d.ts.map +1 -0
  12. package/dist/components/charts/BarChart.d.ts +4 -0
  13. package/dist/components/charts/BarChart.d.ts.map +1 -0
  14. package/dist/components/charts/CartesianChart.d.ts +5 -0
  15. package/dist/components/charts/CartesianChart.d.ts.map +1 -0
  16. package/dist/components/charts/ChartFrame.d.ts +18 -0
  17. package/dist/components/charts/ChartFrame.d.ts.map +1 -0
  18. package/dist/components/charts/DonutChart.d.ts +4 -0
  19. package/dist/components/charts/DonutChart.d.ts.map +1 -0
  20. package/dist/components/charts/LineChart.d.ts +4 -0
  21. package/dist/components/charts/LineChart.d.ts.map +1 -0
  22. package/dist/components/charts/Sparkline.d.ts +5 -0
  23. package/dist/components/charts/Sparkline.d.ts.map +1 -0
  24. package/dist/components/charts/chartTheme.d.ts +26 -0
  25. package/dist/components/charts/chartTheme.d.ts.map +1 -0
  26. package/dist/components/rich-text/RichTextEditor.d.ts +4 -0
  27. package/dist/components/rich-text/RichTextEditor.d.ts.map +1 -0
  28. package/dist/components/rich-text/RichTextToolbar.d.ts +219 -0
  29. package/dist/components/rich-text/RichTextToolbar.d.ts.map +1 -0
  30. package/dist/esm/charts/index.js +5 -0
  31. package/dist/esm/components/charts/AreaChart.js +16 -0
  32. package/dist/esm/components/charts/BarChart.js +16 -0
  33. package/dist/esm/components/charts/CartesianChart.js +250 -0
  34. package/dist/esm/components/charts/ChartFrame.js +170 -0
  35. package/dist/esm/components/charts/DonutChart.js +119 -0
  36. package/dist/esm/components/charts/LineChart.js +16 -0
  37. package/dist/esm/components/charts/Sparkline.js +110 -0
  38. package/dist/esm/components/charts/chartTheme.js +109 -0
  39. package/dist/esm/components/rich-text/RichTextEditor.js +244 -0
  40. package/dist/esm/components/rich-text/RichTextToolbar.js +397 -0
  41. package/dist/esm/rich-text/index.js +1 -0
  42. package/dist/index.css +1 -1
  43. package/dist/index.esm.css +1 -1
  44. package/dist/index.esm.js +17 -4
  45. package/dist/index.js +17 -4
  46. package/dist/rich-text/index.d.ts +5 -0
  47. package/dist/rich-text/index.d.ts.map +1 -0
  48. package/dist/rich-text/index.js +654 -0
  49. package/dist/tokens/brands/studio.css +14 -0
  50. package/dist/tokens/brands/studio.json +20 -0
  51. package/dist/types/charts.d.ts +97 -0
  52. package/dist/types/charts.d.ts.map +1 -0
  53. package/dist/types/rich-text.d.ts +50 -0
  54. package/dist/types/rich-text.d.ts.map +1 -0
  55. package/doc/README.md +13 -0
  56. package/mcp/catalog.snapshot.json +1009 -3
  57. package/mcp/server-core.mjs +30 -1
  58. package/package.json +38 -2
  59. package/rich-text/package.json +5 -0
  60. package/tokens/brands/studio.json +20 -0
@@ -0,0 +1,97 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ import type { BaseComponentProps } from './index';
3
+ /** A palette from the design tokens (`--dt-<palette>-<shade>`). */
4
+ export type ChartPalette = 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'gray';
5
+ export type ChartShade = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950;
6
+ /**
7
+ * A series colour. Prefer a token — `'primary'` (shade 500) or `'primary-300'` —
8
+ * which resolves to the matching `--dt-*` CSS variable and follows the theme and
9
+ * dark mode. Any other string is used as a CSS colour (e.g. a colour stored with
10
+ * the data); it does not follow the theme.
11
+ */
12
+ export type ChartColor = ChartPalette | `${ChartPalette}-${ChartShade}` | (string & {});
13
+ export type ChartValueFormatter = (value: number) => string;
14
+ export type ChartDatum = Record<string, unknown>;
15
+ /** Props shared by every chart (the accessible shell + chrome toggles). */
16
+ export interface ChartBaseProps extends BaseComponentProps, Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'title' | 'color'> {
17
+ /** Rows to plot. An empty array renders `emptyState`. */
18
+ data: ChartDatum[];
19
+ /** Accessible name of the chart (`aria-label` on the `role="img"` region and the hidden table's caption). */
20
+ title?: string;
21
+ /** Longer text alternative, linked with `aria-describedby` (e.g. the takeaway: "Revenue doubled since May"). */
22
+ description?: string;
23
+ /** Formats values in the tooltip, value axis and hidden data table. */
24
+ valueFormatter?: ChartValueFormatter;
25
+ /** Chart height in px, or any CSS length. */
26
+ height?: number | string;
27
+ /** Shown instead of the chart when `data` is empty. */
28
+ emptyState?: ReactNode;
29
+ /** Render the numbers as a visually-hidden table for screen-reader users. */
30
+ accessibleTable?: boolean;
31
+ /** Animate on mount and data change. Always off when the user prefers reduced motion. */
32
+ animate?: boolean;
33
+ showTooltip?: boolean;
34
+ }
35
+ export type ChartCurveType = 'linear' | 'monotone' | 'step' | 'natural';
36
+ /** LineChart / BarChart / AreaChart. */
37
+ export interface CartesianChartProps extends ChartBaseProps {
38
+ /** Key of the x-axis (category) value in each row, e.g. `"month"`. */
39
+ index: string;
40
+ /** Keys of the numeric series to plot, one line/bar/area per key. */
41
+ categories: string[];
42
+ /** Series colours, matched to `categories` by position (cycled). */
43
+ colors?: ChartColor[];
44
+ /** Formats x-axis (category) tick labels and the hidden table's row headers. */
45
+ xAxisFormatter?: (value: unknown) => string;
46
+ showLegend?: boolean;
47
+ showXAxis?: boolean;
48
+ showYAxis?: boolean;
49
+ showGrid?: boolean;
50
+ /** Width reserved for value-axis labels, in px. */
51
+ yAxisWidth?: number;
52
+ }
53
+ export interface LineChartProps extends CartesianChartProps {
54
+ curveType?: ChartCurveType;
55
+ showDots?: boolean;
56
+ /** Draw across `null` gaps instead of breaking the line. */
57
+ connectNulls?: boolean;
58
+ }
59
+ export interface AreaChartProps extends CartesianChartProps {
60
+ curveType?: ChartCurveType;
61
+ /** Stack the series on top of each other. */
62
+ stacked?: boolean;
63
+ showDots?: boolean;
64
+ connectNulls?: boolean;
65
+ }
66
+ export interface BarChartProps extends CartesianChartProps {
67
+ /** Stack the series in one bar per category. */
68
+ stacked?: boolean;
69
+ /** Draw bars horizontally (categories on the y-axis). */
70
+ horizontal?: boolean;
71
+ }
72
+ export interface DonutChartProps extends ChartBaseProps {
73
+ /** Key of the slice name in each row. */
74
+ index?: string;
75
+ /** Key of the slice value in each row. */
76
+ category?: string;
77
+ /** Slice colours, matched to rows by position (cycled). */
78
+ colors?: ChartColor[];
79
+ /** `'pie'` fills the centre. */
80
+ variant?: 'donut' | 'pie';
81
+ /** Inner radius of the ring (px or percentage string). Ignored for `variant="pie"`. */
82
+ innerRadius?: number | string;
83
+ outerRadius?: number | string;
84
+ /** Content drawn in the middle of the donut, e.g. the total. Decorative (`aria-hidden`); put the figure in `description` too. */
85
+ centerLabel?: ReactNode;
86
+ showLegend?: boolean;
87
+ }
88
+ export interface SparklineProps extends ChartBaseProps {
89
+ /** Key of the plotted value in each row. */
90
+ category?: string;
91
+ /** Optional key of a label per row (tooltip label and table row header). */
92
+ index?: string;
93
+ /** Line colour token. */
94
+ color?: ChartColor;
95
+ type?: 'line' | 'area';
96
+ }
97
+ //# sourceMappingURL=charts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"charts.d.ts","sourceRoot":"","sources":["../../src/types/charts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AACvG,MAAM,MAAM,UAAU,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAExF;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,GAAG,YAAY,IAAI,UAAU,EAAE,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAExF,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAE5D,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,2EAA2E;AAC3E,MAAM,WAAW,cACf,SAAQ,kBAAkB,EACxB,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC;IACvE,yDAAyD;IACzD,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,6GAA6G;IAC7G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gHAAgH;IAChH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yFAAyF;IACzF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAExE,wCAAwC;AACxC,MAAM,WAAW,mBAAoB,SAAQ,cAAc;IACzD,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,oEAAoE;IACpE,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,gFAAgF;IAChF,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAc,SAAQ,mBAAmB;IACxD,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC1B,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,iIAAiI;IACjI,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB"}
@@ -0,0 +1,50 @@
1
+ import type { FocusEvent, HTMLAttributes, ReactNode } from 'react';
2
+ import type { AnyExtension, Editor, JSONContent } from '@tiptap/react';
3
+ import type { BaseComponentProps } from './index';
4
+ export type RichTextToolbarItem = 'bold' | 'italic' | 'strike' | 'code' | 'heading1' | 'heading2' | 'heading3' | 'bulletList' | 'orderedList' | 'blockquote' | 'codeBlock' | 'link' | 'undo' | 'redo';
5
+ export type RichTextContent = string | JSONContent;
6
+ export interface RichTextEditorProps extends BaseComponentProps, Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'onChange' | 'onFocus' | 'onBlur' | 'defaultValue'> {
7
+ /** Controlled content: an HTML string (or Tiptap JSON). Sanitize it on the server before you store or render it. */
8
+ value?: RichTextContent;
9
+ /** Uncontrolled initial content (HTML string or Tiptap JSON). */
10
+ defaultValue?: RichTextContent;
11
+ /** Called on every edit with HTML (default) or Tiptap JSON when `outputFormat="json"`. */
12
+ onChange?: (value: RichTextContent, editor: Editor) => void;
13
+ outputFormat?: 'html' | 'json';
14
+ onFocus?: (event: FocusEvent) => void;
15
+ onBlur?: (event: FocusEvent) => void;
16
+ label?: ReactNode;
17
+ error?: ReactNode;
18
+ helperText?: ReactNode;
19
+ placeholder?: string;
20
+ required?: boolean;
21
+ disabled?: boolean;
22
+ /** Read-only: content is shown formatted, not editable, and the toolbar is hidden. */
23
+ readOnly?: boolean;
24
+ /** Toolbar buttons in order, or `false` for none. */
25
+ toolbar?: RichTextToolbarItem[] | false;
26
+ /** Accessible name of the toolbar. */
27
+ toolbarLabel?: string;
28
+ /** Minimum height of the editable area (px or CSS length). */
29
+ minHeight?: number | string;
30
+ /** Maximum height before the editable area scrolls (px or CSS length). */
31
+ maxHeight?: number | string;
32
+ autoFocus?: boolean;
33
+ /** Extra classes for the editable (ProseMirror) element. */
34
+ editorClassName?: string;
35
+ /** Extra Tiptap extensions, appended after StarterKit (bold … link, history). */
36
+ extensions?: AnyExtension[];
37
+ }
38
+ /** What a `ref` on RichTextEditor receives. */
39
+ export interface RichTextEditorHandle {
40
+ /** The Tiptap editor (null until it mounts on the client). */
41
+ editor: Editor | null;
42
+ /** The root wrapper element. */
43
+ element: HTMLDivElement | null;
44
+ focus: () => void;
45
+ clear: () => void;
46
+ getHTML: () => string;
47
+ getJSON: () => JSONContent | null;
48
+ setContent: (content: RichTextContent) => void;
49
+ }
50
+ //# sourceMappingURL=rich-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rich-text.d.ts","sourceRoot":"","sources":["../../src/types/rich-text.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,MAAM,mBAAmB,GAC3B,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,UAAU,GACV,UAAU,GACV,UAAU,GACV,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,WAAW,GACX,MAAM,GACN,MAAM,GACN,MAAM,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,WAAW,CAAC;AAEnD,MAAM,WAAW,mBACf,SAAQ,kBAAkB,EACxB,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,cAAc,CAAC;IACxG,oHAAoH;IACpH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,iEAAiE;IACjE,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qDAAqD;IACrD,OAAO,CAAC,EAAE,mBAAmB,EAAE,GAAG,KAAK,CAAC;IACxC,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;CAC7B;AAED,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gCAAgC;IAChC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;CAChD"}
package/doc/README.md CHANGED
@@ -123,6 +123,19 @@ function App() {
123
123
  | [LoadingState](LoadingState.md) | Block | Skeleton shaped like the content | [LoadingState.md](LoadingState.md) |
124
124
  | [ConfirmDialog](ConfirmDialog.md) | Block | Confirmation dialog (replaces confirm()) | [ConfirmDialog.md](ConfirmDialog.md) |
125
125
 
126
+ ### Optional entry points (need an optional peer dependency)
127
+
128
+ These are **not** exported from the root package. Import them from their subpath, after installing the peer. Apps that never import them install and bundle nothing extra.
129
+
130
+ | Component | Import from | Peer to install | Description | Doc |
131
+ |-----------|-------------|-----------------|-------------|-----|
132
+ | [LineChart](LineChart.md) | `@dreamtree-org/twreact-ui/charts` | `recharts` | Themed line chart, data-first API | [LineChart.md](LineChart.md) |
133
+ | [BarChart](BarChart.md) | `@dreamtree-org/twreact-ui/charts` | `recharts` | Grouped / stacked / horizontal bars | [BarChart.md](BarChart.md) |
134
+ | [AreaChart](AreaChart.md) | `@dreamtree-org/twreact-ui/charts` | `recharts` | Area chart, optionally stacked | [AreaChart.md](AreaChart.md) |
135
+ | [DonutChart](DonutChart.md) | `@dreamtree-org/twreact-ui/charts` | `recharts` | Donut or pie, legend + centre label | [DonutChart.md](DonutChart.md) |
136
+ | [Sparkline](Sparkline.md) | `@dreamtree-org/twreact-ui/charts` | `recharts` | Word-sized trend line for cards and cells | [Sparkline.md](Sparkline.md) |
137
+ | [RichTextEditor](RichTextEditor.md) | `@dreamtree-org/twreact-ui/rich-text` | `@tiptap/react @tiptap/pm @tiptap/starter-kit` | Tiptap WYSIWYG field with accessible toolbar | [RichTextEditor.md](RichTextEditor.md) |
138
+
126
139
  ---
127
140
 
128
141
  ## Hooks & utilities