modifywithai 1.7.0 → 1.7.1

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 (2) hide show
  1. package/AGENTS.md +180 -23
  2. package/package.json +1 -1
package/AGENTS.md CHANGED
@@ -37,7 +37,8 @@ import { MWAIHead, MWAIProvider, MWAIComponents } from "modifywithai/react"
37
37
  Then modify the layout to include:
38
38
 
39
39
  1. `<MWAIHead />` inside the `<head>` tag
40
- 2. `<MWAIProvider>` and `<MWAIComponents />` at the end of `<body>`, after `{children}`
40
+ 2. `<MWAIProvider>` wrapping `<body>`
41
+ 3. `<MWAIComponents />` at the end of `<body>`, after `{children}`
41
42
 
42
43
  Example structure:
43
44
 
@@ -48,12 +49,12 @@ export default function RootLayout({ children }: { children: React.ReactNode })
48
49
  <head>
49
50
  <MWAIHead />
50
51
  </head>
51
- <body>
52
- {children}
53
52
  <MWAIProvider id="{{MWAI_ID}}">
54
- <MWAIComponents />
53
+ <body>
54
+ {children}
55
+ <MWAIComponents />
56
+ </body>
55
57
  </MWAIProvider>
56
- </body>
57
58
  </html>
58
59
  )
59
60
  }
@@ -141,23 +142,87 @@ Choose a suitable location based on the app's structure. Common placements inclu
141
142
 
142
143
  ### Example Implementation
143
144
 
144
- Create a client component for the button:
145
+ Create a client component for the button. The modal has two views:
146
+
147
+ 1. **Default view**: A textarea for submitting new modifications, submit/cancel buttons, and a list showing up to 3 recent modifications (sorted by enabled first, then by creation date). If there are more than 3 modifications, a "Show all" button appears.
148
+
149
+ 2. **Show all view**: When "Show all" is clicked, the modal switches to display a search bar at the top and a scrollable list of all modifications. The textarea and submit/cancel buttons are hidden in this view.
150
+
151
+ Each modification item should display a **status indicator dot** based on the `status` field:
152
+ - 🟢 **Green dot**: `status === "success"` - modification was applied successfully
153
+ - 🟡 **Yellow dot**: `status === "pending"` - modification is being processed
154
+ - 🔴 **Red dot**: `status === "error"` - modification failed to apply
145
155
 
146
156
  ```tsx
147
157
  "use client"
148
158
 
149
- import { useState } from "react"
150
- import { useModify } from "modifywithai/react"
159
+ import { useState, useMemo } from "react"
160
+ import { useModify, useList, useEnable, useDisable } from "modifywithai/react"
161
+
162
+ // Status indicator dot component
163
+ function StatusDot({ status }: { status: "success" | "pending" | "error" }) {
164
+ const colors = {
165
+ success: "#22c55e", // green
166
+ pending: "#eab308", // yellow
167
+ error: "#ef4444", // red
168
+ }
169
+ return (
170
+ <span
171
+ style={{
172
+ display: "inline-block",
173
+ width: 8,
174
+ height: 8,
175
+ borderRadius: "50%",
176
+ backgroundColor: colors[status],
177
+ marginRight: 8,
178
+ }}
179
+ title={status}
180
+ />
181
+ )
182
+ }
151
183
 
152
184
  export function ModifyWithAIButton() {
153
185
  const [isOpen, setIsOpen] = useState(false)
154
186
  const [prompt, setPrompt] = useState("")
155
- const { mutate, isPending } = useModify()
187
+ const [showAll, setShowAll] = useState(false)
188
+ const [searchQuery, setSearchQuery] = useState("")
189
+
190
+ const { modify, isPending } = useModify()
191
+ const { data: modifications = [], isLoading: isLoadingList } = useList()
192
+ const { enable } = useEnable()
193
+ const { disable } = useDisable()
194
+
195
+ // Sort modifications: enabled first, then by createdAt (newest first)
196
+ const sortedModifications = useMemo(() => {
197
+ return [...modifications].sort((a, b) => {
198
+ // Enabled items first
199
+ if (a.enabled && !b.enabled) return -1
200
+ if (!a.enabled && b.enabled) return 1
201
+ // Then by createdAt descending (newest first)
202
+ return b.createdAt - a.createdAt
203
+ })
204
+ }, [modifications])
205
+
206
+ // Filter modifications by search query (searches through titles)
207
+ const filteredModifications = useMemo(() => {
208
+ if (!searchQuery.trim()) return sortedModifications
209
+ const query = searchQuery.toLowerCase()
210
+ return sortedModifications.filter((mod) =>
211
+ mod.title?.toLowerCase().includes(query)
212
+ )
213
+ }, [sortedModifications, searchQuery])
214
+
215
+ // Show only first 3 in default view
216
+ const displayedModifications = showAll
217
+ ? filteredModifications
218
+ : sortedModifications.slice(0, 3)
219
+
220
+ const hasMoreThanThree = sortedModifications.length > 3
156
221
 
157
222
  const handleSubmit = () => {
158
223
  if (!prompt.trim()) return
159
224
 
160
- mutate(prompt, {
225
+ modify(prompt, {
161
226
  onSuccess: () => {
162
227
  setPrompt("")
163
228
  setIsOpen(false)
@@ -170,6 +235,26 @@ export function ModifyWithAIButton() {
170
235
  })
171
236
  }
172
237
 
238
+ const handleToggleModification = (mod: typeof modifications[0]) => {
239
+ if (mod.enabled) {
240
+ disable(mod.id)
241
+ } else {
242
+ enable(mod.id)
243
+ }
244
+ }
245
+
246
+ const handleClose = () => {
247
+ setIsOpen(false)
248
+ setShowAll(false)
249
+ setSearchQuery("")
250
+ setPrompt("")
251
+ }
252
+
253
+ const handleBackToDefault = () => {
254
+ setShowAll(false)
255
+ setSearchQuery("")
256
+ }
257
+
173
258
  if (!isOpen) {
174
259
  return (
175
260
  <button onClick={() => setIsOpen(true)}>
@@ -179,24 +264,96 @@ export function ModifyWithAIButton() {
179
264
  }
180
265
 
181
266
  return (
182
- <div>
183
- <textarea
184
- value={prompt}
185
- onChange={(e) => setPrompt(e.target.value)}
186
- placeholder="Describe the changes you want to make..."
187
- disabled={isPending}
188
- />
189
- <button onClick={handleSubmit} disabled={isPending || !prompt.trim()}>
190
- {isPending ? "Submitting..." : "Submit"}
191
- </button>
192
- <button onClick={() => setIsOpen(false)} disabled={isPending}>
193
- Cancel
194
- </button>
267
+ <div className="modal">
268
+ {showAll ? (
269
+ // "Show all" view: search bar + scrollable list
270
+ <>
271
+ <div className="modal-header">
272
+ <button onClick={handleBackToDefault}>← Back</button>
273
+ <h3>All Modifications</h3>
274
+ </div>
275
+
276
+ <input
277
+ type="text"
278
+ value={searchQuery}
279
+ onChange={(e) => setSearchQuery(e.target.value)}
280
+ placeholder="Search modifications..."
281
+ />
282
+
283
+ <div className="modifications-list scrollable">
284
+ {isLoadingList ? (
285
+ <p>Loading...</p>
286
+ ) : filteredModifications.length === 0 ? (
287
+ <p>No modifications found</p>
288
+ ) : (
289
+ filteredModifications.map((mod) => (
290
+ <div key={mod.id} className="modification-item">
291
+ <StatusDot status={mod.status} />
292
+ <span>{mod.title || "Untitled modification"}</span>
293
+ <button onClick={() => handleToggleModification(mod)}>
294
+ {mod.enabled ? "Disable" : "Enable"}
295
+ </button>
296
+ </div>
297
+ ))
298
+ )}
299
+ </div>
300
+ </>
301
+ ) : (
302
+ // Default view: textarea + buttons + limited modifications list
303
+ <>
304
+ <textarea
305
+ value={prompt}
306
+ onChange={(e) => setPrompt(e.target.value)}
307
+ placeholder="Describe the changes you want to make..."
308
+ disabled={isPending}
309
+ />
310
+
311
+ <div className="button-group">
312
+ <button onClick={handleSubmit} disabled={isPending || !prompt.trim()}>
313
+ {isPending ? "Submitting..." : "Submit"}
314
+ </button>
315
+ <button onClick={handleClose} disabled={isPending}>
316
+ Cancel
317
+ </button>
318
+ </div>
319
+
320
+ {/* Modifications list (up to 3) */}
321
+ {sortedModifications.length > 0 && (
322
+ <div className="modifications-section">
323
+ <h4>Recent Modifications</h4>
324
+ <div className="modifications-list">
325
+ {displayedModifications.map((mod) => (
326
+ <div key={mod.id} className="modification-item">
327
+ <StatusDot status={mod.status} />
328
+ <span>{mod.title || "Untitled modification"}</span>
329
+ <button onClick={() => handleToggleModification(mod)}>
330
+ {mod.enabled ? "Disable" : "Enable"}
331
+ </button>
332
+ </div>
333
+ ))}
334
+ </div>
335
+
336
+ {hasMoreThanThree && (
337
+ <button onClick={() => setShowAll(true)}>
338
+ Show all ({sortedModifications.length})
339
+ </button>
340
+ )}
341
+ </div>
342
+ )}
343
+ </>
344
+ )}
195
345
  </div>
196
346
  )
197
347
  }
198
348
  ```
199
349
 
350
+ ### Modal Views Summary
351
+
352
+ | View | Components Displayed |
353
+ |------|---------------------|
354
+ | **Default** | Textarea, Submit button, Cancel button, Up to 3 modifications, "Show all" button (if >3 mods) |
355
+ | **Show all** | Back button, Search bar, Scrollable list of all modifications |
356
+
200
357
  ### Styling Requirements
201
358
 
202
359
  **Important:** The example above is a minimal reference implementation. You MUST:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modifywithai",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",