prompt-area 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 +120 -0
- package/dist/action-bar/index.d.ts +60 -0
- package/dist/action-bar/index.js +5 -0
- package/dist/action-bar/index.js.map +1 -0
- package/dist/chat-prompt-layout/index.d.ts +53 -0
- package/dist/chat-prompt-layout/index.js +5 -0
- package/dist/chat-prompt-layout/index.js.map +1 -0
- package/dist/chunk-ANZZEZP2.js +38 -0
- package/dist/chunk-ANZZEZP2.js.map +1 -0
- package/dist/chunk-BPJO4DGM.js +198 -0
- package/dist/chunk-BPJO4DGM.js.map +1 -0
- package/dist/chunk-BWVBDP7C.js +38 -0
- package/dist/chunk-BWVBDP7C.js.map +1 -0
- package/dist/chunk-E7HUXORB.js +2692 -0
- package/dist/chunk-E7HUXORB.js.map +1 -0
- package/dist/chunk-NF2LHZIE.js +12 -0
- package/dist/chunk-NF2LHZIE.js.map +1 -0
- package/dist/chunk-UBBCAMJA.js +116 -0
- package/dist/chunk-UBBCAMJA.js.map +1 -0
- package/dist/chunk-XDKRP7UE.js +125 -0
- package/dist/chunk-XDKRP7UE.js.map +1 -0
- package/dist/compact-prompt-area/index.d.ts +86 -0
- package/dist/compact-prompt-area/index.js +6 -0
- package/dist/compact-prompt-area/index.js.map +1 -0
- package/dist/helpers/index.d.ts +374 -0
- package/dist/helpers/index.js +291 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/prompt-area/index.d.ts +327 -0
- package/dist/prompt-area/index.js +6 -0
- package/dist/prompt-area/index.js.map +1 -0
- package/dist/status-bar/index.d.ts +50 -0
- package/dist/status-bar/index.js +5 -0
- package/dist/status-bar/index.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/tailwind.css +181 -0
- package/dist/types-C4BgDEpe.d.ts +271 -0
- package/package.json +102 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt Area — Tailwind v4 preset.
|
|
3
|
+
*
|
|
4
|
+
* For consumers who run Tailwind themselves and want token-level theming.
|
|
5
|
+
* If you are not using Tailwind, import 'prompt-area/styles.css' instead.
|
|
6
|
+
*
|
|
7
|
+
* @import 'prompt-area/tailwind.css';
|
|
8
|
+
*
|
|
9
|
+
* The component styles use a few tw-animate-css utilities; if you want the
|
|
10
|
+
* entrance/spinner animations, also: @import 'tw-animate-css';
|
|
11
|
+
*/
|
|
12
|
+
@custom-variant dark (&:is(.dark *));
|
|
13
|
+
|
|
14
|
+
/* Generate the utilities the components use from the built output. */
|
|
15
|
+
@source './**/*.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Tailwind theme mappings for Prompt Area.
|
|
19
|
+
*
|
|
20
|
+
* Maps the design-token CSS variables (defined in tokens.css) to Tailwind
|
|
21
|
+
* v4 theme variables so utilities like `bg-secondary` / `text-foreground` /
|
|
22
|
+
* `rounded-lg` resolve correctly. Shipped both inside the prebuilt
|
|
23
|
+
* `styles.css` and as part of the optional `tailwind.css` preset.
|
|
24
|
+
*
|
|
25
|
+
* Names intentionally match the shadcn/ui convention so the component
|
|
26
|
+
* automatically inherits the theme of an existing shadcn project.
|
|
27
|
+
*/
|
|
28
|
+
@theme inline {
|
|
29
|
+
--color-background: var(--background);
|
|
30
|
+
--color-foreground: var(--foreground);
|
|
31
|
+
--color-card: var(--card);
|
|
32
|
+
--color-card-foreground: var(--card-foreground);
|
|
33
|
+
--color-popover: var(--popover);
|
|
34
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
35
|
+
--color-primary: var(--primary);
|
|
36
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
37
|
+
--color-secondary: var(--secondary);
|
|
38
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
39
|
+
--color-muted: var(--muted);
|
|
40
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
41
|
+
--color-accent: var(--accent);
|
|
42
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
43
|
+
--color-destructive: var(--destructive);
|
|
44
|
+
--color-border: var(--border);
|
|
45
|
+
--color-input: var(--input);
|
|
46
|
+
--color-ring: var(--ring);
|
|
47
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
48
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
49
|
+
--radius-lg: var(--radius);
|
|
50
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Default design tokens for Prompt Area (neutral base, light + dark).
|
|
55
|
+
*
|
|
56
|
+
* These are sensible standalone defaults so the component looks right with
|
|
57
|
+
* zero configuration. To theme it, override any of these variables in your
|
|
58
|
+
* own CSS (e.g. on `:root` / `.dark`, or scoped to a wrapper element). In a
|
|
59
|
+
* shadcn project these names already exist, so the component inherits your
|
|
60
|
+
* theme automatically.
|
|
61
|
+
*/
|
|
62
|
+
:root {
|
|
63
|
+
--radius: 0.625rem;
|
|
64
|
+
--background: oklch(1 0 0);
|
|
65
|
+
--foreground: oklch(0.145 0 0);
|
|
66
|
+
--card: oklch(1 0 0);
|
|
67
|
+
--card-foreground: oklch(0.145 0 0);
|
|
68
|
+
--popover: oklch(1 0 0);
|
|
69
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
70
|
+
--primary: oklch(0.205 0 0);
|
|
71
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
72
|
+
--secondary: oklch(0.97 0 0);
|
|
73
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
74
|
+
--muted: oklch(0.97 0 0);
|
|
75
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
76
|
+
--accent: oklch(0.97 0 0);
|
|
77
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
78
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
79
|
+
--border: oklch(0.922 0 0);
|
|
80
|
+
--input: oklch(0.922 0 0);
|
|
81
|
+
--ring: oklch(0.708 0 0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.dark {
|
|
85
|
+
--background: oklch(0.145 0 0);
|
|
86
|
+
--foreground: oklch(0.985 0 0);
|
|
87
|
+
--card: oklch(0.205 0 0);
|
|
88
|
+
--card-foreground: oklch(0.985 0 0);
|
|
89
|
+
--popover: oklch(0.205 0 0);
|
|
90
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
91
|
+
--primary: oklch(0.922 0 0);
|
|
92
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
93
|
+
--secondary: oklch(0.269 0 0);
|
|
94
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
95
|
+
--muted: oklch(0.269 0 0);
|
|
96
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
97
|
+
--accent: oklch(0.269 0 0);
|
|
98
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
99
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
100
|
+
--border: oklch(1 0 0 / 14%);
|
|
101
|
+
--input: oklch(1 0 0 / 20%);
|
|
102
|
+
--ring: oklch(0.556 0 0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Prompt Area component styles.
|
|
107
|
+
*
|
|
108
|
+
* These are the hand-authored styles the components depend on (chips, the
|
|
109
|
+
* tap ripple, markdown markers, and stable selectors for the bars). They
|
|
110
|
+
* live in the `components` layer so consumer utilities win over them.
|
|
111
|
+
*/
|
|
112
|
+
@layer components {
|
|
113
|
+
.prompt-area-chip {
|
|
114
|
+
display: inline-flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
padding: 1px 6px;
|
|
117
|
+
border-radius: 4px;
|
|
118
|
+
font-size: 0.875rem;
|
|
119
|
+
font-weight: 500;
|
|
120
|
+
cursor: pointer;
|
|
121
|
+
user-select: none;
|
|
122
|
+
vertical-align: baseline;
|
|
123
|
+
margin: 0 1px;
|
|
124
|
+
background-color: var(--secondary);
|
|
125
|
+
color: var(--foreground);
|
|
126
|
+
transition: background-color 0.2s ease, transform 0.15s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s ease;
|
|
127
|
+
position: relative;
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.prompt-area-chip:hover {
|
|
132
|
+
background-color: color-mix(in srgb, var(--secondary) 80%, var(--foreground) 20%);
|
|
133
|
+
box-shadow: 0 1px 4px color-mix(in srgb, var(--foreground) 10%, transparent);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.prompt-area-chip:active {
|
|
137
|
+
transform: scale(0.93);
|
|
138
|
+
background-color: color-mix(in srgb, var(--secondary) 70%, var(--foreground) 30%);
|
|
139
|
+
box-shadow: 0 0 0 transparent;
|
|
140
|
+
transition: background-color 0.05s ease, transform 0.08s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.05s ease;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@keyframes prompt-area-chip-ripple {
|
|
144
|
+
0% {
|
|
145
|
+
transform: scale(0);
|
|
146
|
+
opacity: 0.4;
|
|
147
|
+
}
|
|
148
|
+
100% {
|
|
149
|
+
transform: scale(2.5);
|
|
150
|
+
opacity: 0;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.prompt-area-chip-ripple {
|
|
155
|
+
position: absolute;
|
|
156
|
+
border-radius: 50%;
|
|
157
|
+
width: 100%;
|
|
158
|
+
aspect-ratio: 1;
|
|
159
|
+
background: color-mix(in srgb, var(--foreground) 15%, transparent);
|
|
160
|
+
pointer-events: none;
|
|
161
|
+
animation: prompt-area-chip-ripple 0.45s ease-out forwards;
|
|
162
|
+
}
|
|
163
|
+
.prompt-area-md-marker {
|
|
164
|
+
font-size: 0;
|
|
165
|
+
display: inline;
|
|
166
|
+
}
|
|
167
|
+
.prompt-area-chip--inline {
|
|
168
|
+
padding: 0;
|
|
169
|
+
border-radius: 0;
|
|
170
|
+
margin: 0;
|
|
171
|
+
font-weight: 700;
|
|
172
|
+
}
|
|
173
|
+
.action-bar {
|
|
174
|
+
/* Base styles for action-bar; Tailwind utilities handle the layout.
|
|
175
|
+
This class exists as a stable selector for consumer overrides. */
|
|
176
|
+
}
|
|
177
|
+
.status-bar {
|
|
178
|
+
/* Base styles for status-bar; Tailwind utilities handle the layout.
|
|
179
|
+
This class exists as a stable selector for consumer overrides. */
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PromptArea component types
|
|
3
|
+
*
|
|
4
|
+
* A lightweight contentEditable-based text input that supports:
|
|
5
|
+
* - Trigger characters (/, @, #) that activate handlers
|
|
6
|
+
* - Immutable chips for resolved mentions/commands
|
|
7
|
+
* - Configurable trigger behavior (dropdown vs callback)
|
|
8
|
+
* - Simple inline markdown rendering
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* A segment of content within the editable text.
|
|
12
|
+
* The document model is an ordered array of these segments.
|
|
13
|
+
*/
|
|
14
|
+
type TextSegment = {
|
|
15
|
+
type: 'text';
|
|
16
|
+
text: string;
|
|
17
|
+
};
|
|
18
|
+
type ChipSegment = {
|
|
19
|
+
type: 'chip';
|
|
20
|
+
/** The trigger character that created this chip (e.g., '@', '#') */
|
|
21
|
+
trigger: string;
|
|
22
|
+
/** The resolved value/ID (e.g., user ID, file ID) */
|
|
23
|
+
value: string;
|
|
24
|
+
/** The display text shown in the chip */
|
|
25
|
+
displayText: string;
|
|
26
|
+
/** Optional data payload attached to the chip */
|
|
27
|
+
data?: unknown;
|
|
28
|
+
/**
|
|
29
|
+
* True when this chip was auto-created by pressing space (resolveOnSpace).
|
|
30
|
+
* Backspace on an auto-resolved chip reverts it to plain text instead of deleting.
|
|
31
|
+
*/
|
|
32
|
+
autoResolved?: boolean;
|
|
33
|
+
};
|
|
34
|
+
type Segment = TextSegment | ChipSegment;
|
|
35
|
+
/**
|
|
36
|
+
* Determines where a trigger character is valid.
|
|
37
|
+
* - 'start': Only valid at the very start of input or after a newline (e.g., slash commands)
|
|
38
|
+
* - 'any': Valid after any whitespace boundary (e.g., @mentions)
|
|
39
|
+
*/
|
|
40
|
+
type TriggerPosition = 'start' | 'any';
|
|
41
|
+
/**
|
|
42
|
+
* Defines how a trigger behaves when activated.
|
|
43
|
+
* - 'dropdown': Shows a popover with suggestions from `onSearch`
|
|
44
|
+
* - 'callback': Fires `onActivate` immediately without a dropdown
|
|
45
|
+
*/
|
|
46
|
+
type TriggerMode = 'dropdown' | 'callback';
|
|
47
|
+
/**
|
|
48
|
+
* Visual style for rendered chips.
|
|
49
|
+
* - 'pill': Button-like pill with background color, padding, border-radius (default)
|
|
50
|
+
* - 'inline': Bold inline text that flows naturally with surrounding content
|
|
51
|
+
*/
|
|
52
|
+
type ChipStyle = 'pill' | 'inline';
|
|
53
|
+
/**
|
|
54
|
+
* A suggestion item shown in the trigger dropdown.
|
|
55
|
+
*/
|
|
56
|
+
type TriggerSuggestion = {
|
|
57
|
+
/** Unique value/ID for this suggestion */
|
|
58
|
+
value: string;
|
|
59
|
+
/** Display label shown in the dropdown */
|
|
60
|
+
label: string;
|
|
61
|
+
/** Optional description shown below the label */
|
|
62
|
+
description?: string;
|
|
63
|
+
/** Optional icon element rendered before the label */
|
|
64
|
+
icon?: React.ReactNode;
|
|
65
|
+
/** Optional arbitrary data passed through on selection */
|
|
66
|
+
data?: unknown;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Configuration for a trigger character.
|
|
70
|
+
*/
|
|
71
|
+
type TriggerConfig = {
|
|
72
|
+
/** The trigger character (e.g., '/', '@', '#') */
|
|
73
|
+
char: string;
|
|
74
|
+
/** Where this trigger is valid */
|
|
75
|
+
position: TriggerPosition;
|
|
76
|
+
/** How this trigger behaves */
|
|
77
|
+
mode: TriggerMode;
|
|
78
|
+
/**
|
|
79
|
+
* For 'dropdown' mode: called with the current query to fetch suggestions.
|
|
80
|
+
* Should return a list of suggestions to display.
|
|
81
|
+
*
|
|
82
|
+
* Receives an options object with an `AbortSignal` that is aborted when a
|
|
83
|
+
* newer search supersedes this one. Pass it to `fetch()` or other async
|
|
84
|
+
* APIs to cancel in-flight work automatically.
|
|
85
|
+
*/
|
|
86
|
+
onSearch?: (query: string, options: {
|
|
87
|
+
signal: AbortSignal;
|
|
88
|
+
}) => TriggerSuggestion[] | Promise<TriggerSuggestion[]>;
|
|
89
|
+
/**
|
|
90
|
+
* For 'dropdown' mode: called when a suggestion is selected.
|
|
91
|
+
* Return the display text for the chip, or void to use `suggestion.label`.
|
|
92
|
+
*/
|
|
93
|
+
onSelect?: (suggestion: TriggerSuggestion) => string | void;
|
|
94
|
+
/**
|
|
95
|
+
* For 'callback' mode: called when the trigger is activated.
|
|
96
|
+
* Receives the full input text and cursor position.
|
|
97
|
+
*/
|
|
98
|
+
onActivate?: (context: TriggerActivateContext) => void;
|
|
99
|
+
/**
|
|
100
|
+
* When true, pressing space while this trigger is active (with a non-empty query)
|
|
101
|
+
* auto-resolves the typed text into a chip without selecting from the dropdown.
|
|
102
|
+
* The auto-resolved chip can be reverted to plain text with backspace.
|
|
103
|
+
* Useful for free-form tags (e.g., #hashtag).
|
|
104
|
+
*/
|
|
105
|
+
resolveOnSpace?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Visual style for chips created by this trigger.
|
|
108
|
+
* - 'pill' (default): Button-like pill with background, padding, border-radius
|
|
109
|
+
* - 'inline': Bold inline text without pill styling
|
|
110
|
+
*/
|
|
111
|
+
chipStyle?: ChipStyle;
|
|
112
|
+
/** CSS class name(s) applied to chips created by this trigger */
|
|
113
|
+
chipClassName?: string;
|
|
114
|
+
/** Label used for accessibility (e.g., "mention", "command") */
|
|
115
|
+
accessibilityLabel?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Debounce delay in milliseconds before calling `onSearch`.
|
|
118
|
+
* Defaults to 0 (immediate). The initial empty-query search always fires
|
|
119
|
+
* immediately regardless of this setting so the dropdown appears instantly.
|
|
120
|
+
*/
|
|
121
|
+
searchDebounceMs?: number;
|
|
122
|
+
/**
|
|
123
|
+
* Called when `onSearch` rejects or throws (non-abort errors only).
|
|
124
|
+
* Use this to log errors or show toast notifications.
|
|
125
|
+
*/
|
|
126
|
+
onSearchError?: (error: unknown) => void;
|
|
127
|
+
/**
|
|
128
|
+
* Message shown in the dropdown when `onSearch` returns an empty array.
|
|
129
|
+
* If omitted, the popover hides when there are no results (current behavior).
|
|
130
|
+
*/
|
|
131
|
+
emptyMessage?: string;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Context passed to callback-mode trigger handlers.
|
|
135
|
+
*/
|
|
136
|
+
type TriggerActivateContext = {
|
|
137
|
+
/** The full plain text content at the time of activation */
|
|
138
|
+
text: string;
|
|
139
|
+
/** The cursor offset position */
|
|
140
|
+
cursorPosition: number;
|
|
141
|
+
/** Function to insert a chip at the current cursor position */
|
|
142
|
+
insertChip: (chip: Omit<ChipSegment, 'type'>) => void;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Represents an active trigger being typed by the user.
|
|
146
|
+
*/
|
|
147
|
+
type ActiveTrigger = {
|
|
148
|
+
/** The trigger config that was activated */
|
|
149
|
+
config: TriggerConfig;
|
|
150
|
+
/** Position (character offset) where the trigger character was typed */
|
|
151
|
+
startOffset: number;
|
|
152
|
+
/** The text typed after the trigger character so far */
|
|
153
|
+
query: string;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* An image attachment displayed in the prompt area.
|
|
157
|
+
* State is managed externally by the parent component.
|
|
158
|
+
*/
|
|
159
|
+
type PromptAreaImage = {
|
|
160
|
+
/** Unique identifier for this image */
|
|
161
|
+
id: string;
|
|
162
|
+
/** URL to display (CDN URL or temporary blob URL for preview) */
|
|
163
|
+
url: string;
|
|
164
|
+
/** Optional alt text for accessibility */
|
|
165
|
+
alt?: string;
|
|
166
|
+
/** When true, shows a loading indicator over the thumbnail */
|
|
167
|
+
loading?: boolean;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* A file attachment displayed in the prompt area.
|
|
171
|
+
* State is managed externally by the parent component.
|
|
172
|
+
*/
|
|
173
|
+
type PromptAreaFile = {
|
|
174
|
+
/** Unique identifier for this file */
|
|
175
|
+
id: string;
|
|
176
|
+
/** Display filename (e.g., "report.pdf") */
|
|
177
|
+
name: string;
|
|
178
|
+
/** File size in bytes */
|
|
179
|
+
size?: number;
|
|
180
|
+
/** MIME type (used for icon selection, e.g., "application/pdf") */
|
|
181
|
+
type?: string;
|
|
182
|
+
/** When true, shows a loading indicator over the file card */
|
|
183
|
+
loading?: boolean;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* Props for the PromptArea component.
|
|
187
|
+
*/
|
|
188
|
+
type PromptAreaProps = {
|
|
189
|
+
/** The document segments (controlled) */
|
|
190
|
+
value: Segment[];
|
|
191
|
+
/** Called when the content changes */
|
|
192
|
+
onChange: (segments: Segment[]) => void;
|
|
193
|
+
/** Trigger configurations */
|
|
194
|
+
triggers?: TriggerConfig[];
|
|
195
|
+
/** Placeholder text when empty. Pass an array of strings to animate between them. */
|
|
196
|
+
placeholder?: string | string[];
|
|
197
|
+
/** Additional CSS class for the container */
|
|
198
|
+
className?: string;
|
|
199
|
+
/** Whether the input is disabled */
|
|
200
|
+
disabled?: boolean;
|
|
201
|
+
/** Whether to render simple inline markdown (bold, italic, URLs, lists) */
|
|
202
|
+
markdown?: boolean;
|
|
203
|
+
/** Called when Enter is pressed (without Shift) */
|
|
204
|
+
onSubmit?: (segments: Segment[]) => void;
|
|
205
|
+
/** Called when Escape is pressed */
|
|
206
|
+
onEscape?: () => void;
|
|
207
|
+
/** Called when a chip element is clicked. Receives the chip's segment data. */
|
|
208
|
+
onChipClick?: (chip: ChipSegment) => void;
|
|
209
|
+
/** Called when a new chip is added (dropdown selection, auto-resolve, paste, or imperative insert) */
|
|
210
|
+
onChipAdd?: (chip: ChipSegment) => void;
|
|
211
|
+
/** Called when a chip is deleted (backspace or forward delete) */
|
|
212
|
+
onChipDelete?: (chip: ChipSegment) => void;
|
|
213
|
+
/** Called when a URL link is clicked. Receives the URL string. */
|
|
214
|
+
onLinkClick?: (url: string) => void;
|
|
215
|
+
/** Called after content is pasted. Receives the resulting segments and the paste source. */
|
|
216
|
+
onPaste?: (data: {
|
|
217
|
+
segments: Segment[];
|
|
218
|
+
source: 'internal' | 'external';
|
|
219
|
+
}) => void;
|
|
220
|
+
/** Called after an undo operation. Receives the restored segments. */
|
|
221
|
+
onUndo?: (segments: Segment[]) => void;
|
|
222
|
+
/** Called after a redo operation. Receives the restored segments. */
|
|
223
|
+
onRedo?: (segments: Segment[]) => void;
|
|
224
|
+
/** Minimum height in pixels */
|
|
225
|
+
minHeight?: number;
|
|
226
|
+
/** Maximum height in pixels */
|
|
227
|
+
maxHeight?: number;
|
|
228
|
+
/** Auto-focus on mount */
|
|
229
|
+
autoFocus?: boolean;
|
|
230
|
+
/** When true, the area auto-grows to fit content on focus and shrinks on blur */
|
|
231
|
+
autoGrow?: boolean;
|
|
232
|
+
/** Accessible label for the input */
|
|
233
|
+
'aria-label'?: string;
|
|
234
|
+
/** data-test-id for e2e testing */
|
|
235
|
+
'data-test-id'?: string;
|
|
236
|
+
/** Array of image attachments to display */
|
|
237
|
+
images?: PromptAreaImage[];
|
|
238
|
+
/** Where to render the image strip relative to the text area. Defaults to 'above'. */
|
|
239
|
+
imagePosition?: 'above' | 'below';
|
|
240
|
+
/** Called when the user pastes an image from clipboard. Receives the File object. */
|
|
241
|
+
onImagePaste?: (file: File) => void;
|
|
242
|
+
/** Called when the user clicks the remove button on an image */
|
|
243
|
+
onImageRemove?: (image: PromptAreaImage) => void;
|
|
244
|
+
/** Called when the user clicks an image thumbnail */
|
|
245
|
+
onImageClick?: (image: PromptAreaImage) => void;
|
|
246
|
+
/** Array of file attachments to display */
|
|
247
|
+
files?: PromptAreaFile[];
|
|
248
|
+
/** Where to render the file strip relative to the text area. Defaults to 'above'. */
|
|
249
|
+
filePosition?: 'above' | 'below';
|
|
250
|
+
/** Called when the user clicks the remove button on a file */
|
|
251
|
+
onFileRemove?: (file: PromptAreaFile) => void;
|
|
252
|
+
/** Called when the user clicks a file attachment */
|
|
253
|
+
onFileClick?: (file: PromptAreaFile) => void;
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* Ref handle exposed by PromptArea via useImperativeHandle.
|
|
257
|
+
*/
|
|
258
|
+
type PromptAreaHandle = {
|
|
259
|
+
/** Focus the editable area */
|
|
260
|
+
focus: () => void;
|
|
261
|
+
/** Blur the editable area */
|
|
262
|
+
blur: () => void;
|
|
263
|
+
/** Insert a chip at the current cursor position */
|
|
264
|
+
insertChip: (chip: Omit<ChipSegment, 'type'>) => void;
|
|
265
|
+
/** Get the current plain text (without chip markup) */
|
|
266
|
+
getPlainText: () => string;
|
|
267
|
+
/** Clear all content */
|
|
268
|
+
clear: () => void;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
export type { ActiveTrigger as A, ChipSegment as C, PromptAreaFile as P, Segment as S, TextSegment as T, ChipStyle as a, PromptAreaHandle as b, PromptAreaImage as c, PromptAreaProps as d, TriggerActivateContext as e, TriggerConfig as f, TriggerMode as g, TriggerPosition as h, TriggerSuggestion as i };
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prompt-area",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "An opinionated, dependency-light React rich-text prompt input with trigger-based chips (@mentions, /commands, #tags), inline markdown, undo/redo, file & image attachments, and a complete chat-input layout. Ships as an npm package or a shadcn registry.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"prompt",
|
|
8
|
+
"chat-input",
|
|
9
|
+
"textarea",
|
|
10
|
+
"contenteditable",
|
|
11
|
+
"mentions",
|
|
12
|
+
"slash-commands",
|
|
13
|
+
"rich-text",
|
|
14
|
+
"ai",
|
|
15
|
+
"shadcn"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"homepage": "https://prompt-area.com",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/just-marketing/prompt-area.git",
|
|
22
|
+
"directory": "packages/prompt-area"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/just-marketing/prompt-area/issues"
|
|
26
|
+
},
|
|
27
|
+
"type": "module",
|
|
28
|
+
"sideEffects": [
|
|
29
|
+
"**/*.css"
|
|
30
|
+
],
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"import": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./prompt-area": {
|
|
40
|
+
"types": "./dist/prompt-area/index.d.ts",
|
|
41
|
+
"import": "./dist/prompt-area/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./action-bar": {
|
|
44
|
+
"types": "./dist/action-bar/index.d.ts",
|
|
45
|
+
"import": "./dist/action-bar/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./status-bar": {
|
|
48
|
+
"types": "./dist/status-bar/index.d.ts",
|
|
49
|
+
"import": "./dist/status-bar/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./compact-prompt-area": {
|
|
52
|
+
"types": "./dist/compact-prompt-area/index.d.ts",
|
|
53
|
+
"import": "./dist/compact-prompt-area/index.js"
|
|
54
|
+
},
|
|
55
|
+
"./chat-prompt-layout": {
|
|
56
|
+
"types": "./dist/chat-prompt-layout/index.d.ts",
|
|
57
|
+
"import": "./dist/chat-prompt-layout/index.js"
|
|
58
|
+
},
|
|
59
|
+
"./helpers": {
|
|
60
|
+
"types": "./dist/helpers/index.d.ts",
|
|
61
|
+
"import": "./dist/helpers/index.js"
|
|
62
|
+
},
|
|
63
|
+
"./styles.css": "./dist/styles.css",
|
|
64
|
+
"./tailwind.css": "./dist/tailwind.css",
|
|
65
|
+
"./package.json": "./package.json"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"node": ">=18"
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"react": ">=18",
|
|
72
|
+
"react-dom": ">=18"
|
|
73
|
+
},
|
|
74
|
+
"dependencies": {
|
|
75
|
+
"clsx": "^2.1.1",
|
|
76
|
+
"tailwind-merge": "^3.6.0"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
80
|
+
"@tailwindcss/cli": "^4.3.0",
|
|
81
|
+
"@types/react": "19.2.17",
|
|
82
|
+
"@types/react-dom": "^19.2.3",
|
|
83
|
+
"publint": "^0.3.14",
|
|
84
|
+
"react": "^19.2.7",
|
|
85
|
+
"react-dom": "^19.2.7",
|
|
86
|
+
"tailwindcss": "^4.3.0",
|
|
87
|
+
"tsup": "^8.5.0",
|
|
88
|
+
"tw-animate-css": "^1.4.0",
|
|
89
|
+
"typescript": "^5.9.3"
|
|
90
|
+
},
|
|
91
|
+
"publishConfig": {
|
|
92
|
+
"access": "public"
|
|
93
|
+
},
|
|
94
|
+
"scripts": {
|
|
95
|
+
"build": "pnpm run clean && pnpm run build:js && pnpm run build:css",
|
|
96
|
+
"build:js": "tsup && node ./scripts/preserve-directives.mjs",
|
|
97
|
+
"build:css": "tailwindcss --input ./src/styles.css --output ./dist/styles.css --minify && node ./scripts/build-preset.mjs",
|
|
98
|
+
"clean": "rm -rf dist",
|
|
99
|
+
"typecheck": "tsc --noEmit",
|
|
100
|
+
"lint:exports": "publint && attw --pack . --profile esm-only --exclude-entrypoints styles.css tailwind.css"
|
|
101
|
+
}
|
|
102
|
+
}
|