makersclaw 0.7.0 → 0.8.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.
- package/README.md +17 -4
- package/package.json +1 -1
- package/r/activity-log.json +52 -0
- package/r/agent-changes.json +51 -0
- package/r/agent-chat.json +53 -0
- package/r/agent-column.json +85 -0
- package/r/agent-dock.json +57 -0
- package/r/agent-kit.json +49 -0
- package/r/agent-marks.json +49 -0
- package/r/agent-pane.json +93 -0
- package/r/ai-action.json +56 -0
- package/r/annotate.json +4 -4
- package/r/approval-request.json +2 -2
- package/r/approval.json +54 -0
- package/r/ask-bar.json +50 -0
- package/r/audio-player.json +2 -2
- package/r/auth-form.json +2 -2
- package/r/automation-editor.json +66 -0
- package/r/automation-list.json +57 -0
- package/r/automation-model.json +118 -0
- package/r/automations-screen.json +71 -0
- package/r/board.json +2 -2
- package/r/calendar-view.json +3 -3
- package/r/cart.json +2 -2
- package/r/chart.json +5 -5
- package/r/chat-pane.json +84 -0
- package/r/chat.json +3 -3
- package/r/code-editor.json +2 -2
- package/r/comment-box.json +3 -3
- package/r/connect-card.json +51 -0
- package/r/contact-section.json +2 -2
- package/r/core.json +18 -6
- package/r/cost.json +51 -0
- package/r/csv-import.json +3 -3
- package/r/data-picker.json +60 -0
- package/r/data-table.json +2 -2
- package/r/diagram.json +2 -2
- package/r/doc-editor.json +2 -2
- package/r/doc-page.json +3 -3
- package/r/email-render.json +2 -2
- package/r/faq.json +2 -2
- package/r/file-upload.json +2 -2
- package/r/first-run.json +63 -0
- package/r/fix-note.json +57 -0
- package/r/flow-canvas.json +3 -3
- package/r/flow-editor.json +79 -0
- package/r/footer.json +3 -3
- package/r/gantt.json +3 -3
- package/r/job-panel.json +2 -2
- package/r/json-editor.json +3 -3
- package/r/library-shelf.json +56 -0
- package/r/map.json +2 -2
- package/r/margin-notes.json +67 -0
- package/r/menubar.json +2 -2
- package/r/mind-map.json +4 -4
- package/r/navigation-menu.json +2 -2
- package/r/needs-you.json +55 -0
- package/r/order-detail.json +2 -2
- package/r/org-chart.json +4 -4
- package/r/pace-bar.json +69 -0
- package/r/page-builder.json +3 -3
- package/r/payment-methods.json +2 -2
- package/r/pdf-document.json +2 -2
- package/r/pdf-viewer.json +3 -3
- package/r/product-detail.json +2 -2
- package/r/product-grid.json +3 -3
- package/r/record-form.json +2 -2
- package/r/record-grid.json +52 -0
- package/r/record-notes.json +4 -4
- package/r/registry.json +4089 -1510
- package/r/run-history.json +52 -0
- package/r/run-view.json +80 -0
- package/r/schedule-card.json +54 -0
- package/r/schedule-engine.json +79 -0
- package/r/schedule-gantt.json +83 -0
- package/r/schedule-ruler.json +64 -0
- package/r/search-dialog.json +2 -2
- package/r/settings-list.json +2 -2
- package/r/setup-checklist.json +2 -2
- package/r/share-dialog.json +2 -2
- package/r/sidebar.json +3 -3
- package/r/signature-pad.json +2 -2
- package/r/sketch-canvas.json +3 -3
- package/r/source-receipt.json +52 -0
- package/r/spreadsheet.json +3 -3
- package/r/stat-cards.json +3 -3
- package/r/step-picker.json +53 -0
- package/r/step-settings.json +72 -0
- package/r/suggestion.json +58 -0
- package/r/sum-bar.json +64 -0
- package/r/task-list.json +3 -3
- package/r/task-model.json +2 -2
- package/r/testimonials.json +2 -2
- package/r/tier-map.json +67 -0
- package/r/time-grid.json +73 -0
- package/r/time-strip.json +64 -0
- package/r/top-bar.json +66 -0
- package/r/transaction-list.json +2 -2
- package/r/trigger-picker.json +61 -0
- package/r/whiteboard.json +4 -4
- package/r/workflow-view.json +55 -0
- package/registry/blocks/activity-log/README.md +112 -0
- package/registry/blocks/activity-log/activity-log.jsx +351 -0
- package/registry/blocks/activity-log/block.json +33 -0
- package/registry/blocks/activity-log/demo.jsx +48 -0
- package/registry/blocks/activity-log/index.js +4 -0
- package/registry/blocks/agent-changes/README.md +94 -0
- package/registry/blocks/agent-changes/agent-changes.jsx +118 -0
- package/registry/blocks/agent-changes/block.json +28 -0
- package/registry/blocks/agent-changes/demo.jsx +39 -0
- package/registry/blocks/agent-changes/index.js +3 -0
- package/registry/blocks/agent-chat/README.md +145 -0
- package/registry/blocks/agent-chat/agent-chat.jsx +415 -0
- package/registry/blocks/agent-chat/block.json +30 -0
- package/registry/blocks/agent-chat/demo.jsx +165 -0
- package/registry/blocks/agent-chat/index.js +3 -0
- package/registry/blocks/agent-column/README.md +197 -0
- package/registry/blocks/agent-column/agent-column.jsx +492 -0
- package/registry/blocks/agent-column/block.json +67 -0
- package/registry/blocks/agent-column/column-picker.jsx +163 -0
- package/registry/blocks/agent-column/demo.jsx +50 -0
- package/registry/blocks/agent-column/index.js +7 -0
- package/registry/blocks/agent-column/model.js +164 -0
- package/registry/blocks/agent-column/receipt.jsx +483 -0
- package/registry/blocks/agent-column/spreadsheet-type.jsx +24 -0
- package/registry/blocks/agent-dock/README.md +210 -0
- package/registry/blocks/agent-dock/agent-dock.jsx +356 -0
- package/registry/blocks/agent-dock/block.json +47 -0
- package/registry/blocks/agent-dock/demo.jsx +153 -0
- package/registry/blocks/agent-dock/dock-model.js +118 -0
- package/registry/blocks/agent-dock/index.js +5 -0
- package/registry/blocks/agent-kit/README.md +73 -0
- package/registry/blocks/agent-kit/agent-kit.jsx +86 -0
- package/registry/blocks/agent-kit/block.json +10 -0
- package/registry/blocks/agent-kit/demo.jsx +35 -0
- package/registry/blocks/agent-kit/index.js +3 -0
- package/registry/blocks/agent-marks/README.md +80 -0
- package/registry/blocks/agent-marks/agent-marks.jsx +133 -0
- package/registry/blocks/agent-marks/block.json +27 -0
- package/registry/blocks/agent-marks/demo.jsx +49 -0
- package/registry/blocks/agent-marks/index.js +3 -0
- package/registry/blocks/agent-pane/README.md +225 -0
- package/registry/blocks/agent-pane/agent-pane.jsx +244 -0
- package/registry/blocks/agent-pane/block.json +41 -0
- package/registry/blocks/agent-pane/composer.jsx +6 -0
- package/registry/blocks/agent-pane/demo.jsx +233 -0
- package/registry/blocks/agent-pane/dock-context.js +10 -0
- package/registry/blocks/agent-pane/index.js +4 -0
- package/registry/blocks/agent-pane/prose.jsx +84 -0
- package/registry/blocks/agent-pane/questions.jsx +134 -0
- package/registry/blocks/agent-pane/transcript.jsx +268 -0
- package/registry/blocks/agent-pane/work.jsx +368 -0
- package/registry/blocks/ai-action/README.md +94 -0
- package/registry/blocks/ai-action/ai-action.jsx +188 -0
- package/registry/blocks/ai-action/block.json +34 -0
- package/registry/blocks/ai-action/demo.jsx +93 -0
- package/registry/blocks/ai-action/index.js +3 -0
- package/registry/blocks/annotate/README.md +14 -11
- package/registry/blocks/approval/README.md +145 -0
- package/registry/blocks/approval/approval.jsx +163 -0
- package/registry/blocks/approval/block.json +31 -0
- package/registry/blocks/approval/demo.jsx +121 -0
- package/registry/blocks/approval/index.js +3 -0
- package/registry/blocks/ask-bar/README.md +105 -0
- package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
- package/registry/blocks/ask-bar/block.json +26 -0
- package/registry/blocks/ask-bar/demo.jsx +78 -0
- package/registry/blocks/ask-bar/index.js +3 -0
- package/registry/blocks/automation-editor/README.md +291 -0
- package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
- package/registry/blocks/automation-editor/block.json +39 -0
- package/registry/blocks/automation-editor/demo.jsx +284 -0
- package/registry/blocks/automation-editor/index.js +4 -0
- package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
- package/registry/blocks/automation-list/README.md +129 -0
- package/registry/blocks/automation-list/automation-list.jsx +476 -0
- package/registry/blocks/automation-list/block.json +35 -0
- package/registry/blocks/automation-list/demo.jsx +67 -0
- package/registry/blocks/automation-list/index.js +3 -0
- package/registry/blocks/automation-model/README.md +109 -0
- package/registry/blocks/automation-model/block.json +135 -0
- package/registry/blocks/automation-model/catalog.js +256 -0
- package/registry/blocks/automation-model/check.js +161 -0
- package/registry/blocks/automation-model/demo.jsx +42 -0
- package/registry/blocks/automation-model/edit.js +262 -0
- package/registry/blocks/automation-model/fixes.js +287 -0
- package/registry/blocks/automation-model/glyph.jsx +13 -0
- package/registry/blocks/automation-model/graph.js +410 -0
- package/registry/blocks/automation-model/index.js +33 -0
- package/registry/blocks/automation-model/overlay.js +175 -0
- package/registry/blocks/automation-model/parts.jsx +94 -0
- package/registry/blocks/automation-model/schedule.js +53 -0
- package/registry/blocks/automation-model/templates.js +128 -0
- package/registry/blocks/automation-model/values.js +29 -0
- package/registry/blocks/automation-model/words.js +439 -0
- package/registry/blocks/automations-screen/README.md +207 -0
- package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
- package/registry/blocks/automations-screen/block.json +47 -0
- package/registry/blocks/automations-screen/demo.jsx +364 -0
- package/registry/blocks/automations-screen/index.js +4 -0
- package/registry/blocks/automations-screen/screen-model.js +129 -0
- package/registry/blocks/chart/cartesian.jsx +1 -1
- package/registry/blocks/chart/core.jsx +33 -23
- package/registry/blocks/chart/pie.jsx +1 -1
- package/registry/blocks/chat/README.md +4 -1
- package/registry/blocks/chat/demo.jsx +2 -2
- package/registry/blocks/chat-pane/README.md +143 -0
- package/registry/blocks/chat-pane/block.json +48 -0
- package/registry/blocks/chat-pane/chat-attach.js +166 -0
- package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
- package/registry/blocks/chat-pane/chat-context.js +17 -0
- package/registry/blocks/chat-pane/chat-model.js +43 -0
- package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
- package/registry/blocks/chat-pane/chats-list.jsx +52 -0
- package/registry/blocks/chat-pane/demo.jsx +103 -0
- package/registry/blocks/chat-pane/index.js +9 -0
- package/registry/blocks/connect-card/README.md +99 -0
- package/registry/blocks/connect-card/block.json +10 -0
- package/registry/blocks/connect-card/connect-card.jsx +103 -0
- package/registry/blocks/connect-card/demo.jsx +49 -0
- package/registry/blocks/connect-card/index.js +3 -0
- package/registry/blocks/cost/README.md +115 -0
- package/registry/blocks/cost/block.json +10 -0
- package/registry/blocks/cost/cost.jsx +176 -0
- package/registry/blocks/cost/demo.jsx +66 -0
- package/registry/blocks/cost/index.js +3 -0
- package/registry/blocks/data-picker/README.md +81 -0
- package/registry/blocks/data-picker/block.json +38 -0
- package/registry/blocks/data-picker/data-picker.jsx +210 -0
- package/registry/blocks/data-picker/demo.jsx +34 -0
- package/registry/blocks/data-picker/fields.js +89 -0
- package/registry/blocks/data-picker/index.js +4 -0
- package/registry/blocks/data-table/demo.jsx +1 -1
- package/registry/blocks/first-run/README.md +118 -0
- package/registry/blocks/first-run/block.json +11 -0
- package/registry/blocks/first-run/demo.jsx +88 -0
- package/registry/blocks/first-run/first-run-model.js +51 -0
- package/registry/blocks/first-run/first-run.jsx +156 -0
- package/registry/blocks/first-run/index.js +5 -0
- package/registry/blocks/first-run/probe-rules.js +26 -0
- package/registry/blocks/fix-note/README.md +79 -0
- package/registry/blocks/fix-note/block.json +35 -0
- package/registry/blocks/fix-note/demo.jsx +30 -0
- package/registry/blocks/fix-note/fix-note.jsx +235 -0
- package/registry/blocks/fix-note/index.js +3 -0
- package/registry/blocks/flow-canvas/README.md +15 -8
- package/registry/blocks/flow-editor/README.md +108 -0
- package/registry/blocks/flow-editor/block.json +44 -0
- package/registry/blocks/flow-editor/demo.jsx +115 -0
- package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
- package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
- package/registry/blocks/flow-editor/index.js +6 -0
- package/registry/blocks/flow-editor/minimap.jsx +78 -0
- package/registry/blocks/flow-editor/outline.jsx +134 -0
- package/registry/blocks/footer/README.md +3 -2
- package/registry/blocks/library-shelf/README.md +117 -0
- package/registry/blocks/library-shelf/block.json +28 -0
- package/registry/blocks/library-shelf/demo.jsx +68 -0
- package/registry/blocks/library-shelf/index.js +3 -0
- package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
- package/registry/blocks/library-shelf/probe-rules.js +15 -0
- package/registry/blocks/margin-notes/README.md +222 -0
- package/registry/blocks/margin-notes/block.json +10 -0
- package/registry/blocks/margin-notes/demo.jsx +144 -0
- package/registry/blocks/margin-notes/index.js +20 -0
- package/registry/blocks/margin-notes/margin-model.js +224 -0
- package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
- package/registry/blocks/mind-map/README.md +4 -2
- package/registry/blocks/needs-you/README.md +177 -0
- package/registry/blocks/needs-you/block.json +34 -0
- package/registry/blocks/needs-you/demo.jsx +143 -0
- package/registry/blocks/needs-you/index.js +3 -0
- package/registry/blocks/needs-you/needs-you.jsx +441 -0
- package/registry/blocks/org-chart/README.md +4 -2
- package/registry/blocks/pace-bar/README.md +230 -0
- package/registry/blocks/pace-bar/block.json +10 -0
- package/registry/blocks/pace-bar/demo.jsx +255 -0
- package/registry/blocks/pace-bar/index.js +22 -0
- package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
- package/registry/blocks/pace-bar/pace-model.js +288 -0
- package/registry/blocks/page-builder/README.md +1 -1
- package/registry/blocks/page-builder/demo.jsx +3 -3
- package/registry/blocks/pdf-viewer/README.md +4 -1
- package/registry/blocks/record-grid/README.md +100 -0
- package/registry/blocks/record-grid/block.json +28 -0
- package/registry/blocks/record-grid/demo.jsx +43 -0
- package/registry/blocks/record-grid/index.js +3 -0
- package/registry/blocks/record-grid/record-grid.jsx +251 -0
- package/registry/blocks/run-history/README.md +138 -0
- package/registry/blocks/run-history/block.json +10 -0
- package/registry/blocks/run-history/demo.jsx +74 -0
- package/registry/blocks/run-history/index.js +3 -0
- package/registry/blocks/run-history/run-history.jsx +218 -0
- package/registry/blocks/run-view/README.md +174 -0
- package/registry/blocks/run-view/block.json +50 -0
- package/registry/blocks/run-view/demo.jsx +286 -0
- package/registry/blocks/run-view/index.js +5 -0
- package/registry/blocks/run-view/run-controls.jsx +266 -0
- package/registry/blocks/run-view/run-view.jsx +236 -0
- package/registry/blocks/run-view/runs-list.jsx +99 -0
- package/registry/blocks/schedule-card/README.md +121 -0
- package/registry/blocks/schedule-card/block.json +10 -0
- package/registry/blocks/schedule-card/demo.jsx +82 -0
- package/registry/blocks/schedule-card/index.js +3 -0
- package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
- package/registry/blocks/schedule-engine/README.md +137 -0
- package/registry/blocks/schedule-engine/block.json +10 -0
- package/registry/blocks/schedule-engine/demo.jsx +82 -0
- package/registry/blocks/schedule-engine/engine.js +769 -0
- package/registry/blocks/schedule-engine/index.js +9 -0
- package/registry/blocks/schedule-engine/ops.js +71 -0
- package/registry/blocks/schedule-engine/place.js +294 -0
- package/registry/blocks/schedule-engine/tree.js +79 -0
- package/registry/blocks/schedule-engine/waits.js +80 -0
- package/registry/blocks/schedule-gantt/README.md +159 -0
- package/registry/blocks/schedule-gantt/block.json +10 -0
- package/registry/blocks/schedule-gantt/demo.jsx +223 -0
- package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
- package/registry/blocks/schedule-gantt/geometry.js +176 -0
- package/registry/blocks/schedule-gantt/index.js +26 -0
- package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
- package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
- package/registry/blocks/schedule-gantt/track.jsx +190 -0
- package/registry/blocks/schedule-ruler/README.md +148 -0
- package/registry/blocks/schedule-ruler/block.json +10 -0
- package/registry/blocks/schedule-ruler/demo.jsx +181 -0
- package/registry/blocks/schedule-ruler/index.js +21 -0
- package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
- package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
- package/registry/blocks/sidebar/README.md +23 -13
- package/registry/blocks/sketch-canvas/README.md +15 -9
- package/registry/blocks/source-receipt/README.md +97 -0
- package/registry/blocks/source-receipt/block.json +30 -0
- package/registry/blocks/source-receipt/demo.jsx +71 -0
- package/registry/blocks/source-receipt/index.js +3 -0
- package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
- package/registry/blocks/step-picker/README.md +78 -0
- package/registry/blocks/step-picker/block.json +31 -0
- package/registry/blocks/step-picker/demo.jsx +23 -0
- package/registry/blocks/step-picker/index.js +3 -0
- package/registry/blocks/step-picker/step-picker.jsx +144 -0
- package/registry/blocks/step-settings/README.md +100 -0
- package/registry/blocks/step-settings/block.json +44 -0
- package/registry/blocks/step-settings/demo.jsx +93 -0
- package/registry/blocks/step-settings/fields.jsx +58 -0
- package/registry/blocks/step-settings/flow-settings.jsx +115 -0
- package/registry/blocks/step-settings/index.js +5 -0
- package/registry/blocks/step-settings/step-settings.jsx +290 -0
- package/registry/blocks/suggestion/README.md +171 -0
- package/registry/blocks/suggestion/block.json +40 -0
- package/registry/blocks/suggestion/demo.jsx +91 -0
- package/registry/blocks/suggestion/index.js +3 -0
- package/registry/blocks/suggestion/suggestion.jsx +436 -0
- package/registry/blocks/sum-bar/README.md +122 -0
- package/registry/blocks/sum-bar/block.json +10 -0
- package/registry/blocks/sum-bar/demo.jsx +110 -0
- package/registry/blocks/sum-bar/index.js +5 -0
- package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
- package/registry/blocks/sum-bar/sum-model.js +126 -0
- package/registry/blocks/tier-map/README.md +217 -0
- package/registry/blocks/tier-map/block.json +10 -0
- package/registry/blocks/tier-map/demo.jsx +222 -0
- package/registry/blocks/tier-map/index.js +24 -0
- package/registry/blocks/tier-map/tier-map.jsx +574 -0
- package/registry/blocks/tier-map/tier-model.js +318 -0
- package/registry/blocks/time-grid/README.md +305 -0
- package/registry/blocks/time-grid/block.json +10 -0
- package/registry/blocks/time-grid/demo.jsx +279 -0
- package/registry/blocks/time-grid/grid-model.js +322 -0
- package/registry/blocks/time-grid/index.js +25 -0
- package/registry/blocks/time-grid/time-grid.jsx +1325 -0
- package/registry/blocks/time-strip/README.md +141 -0
- package/registry/blocks/time-strip/block.json +10 -0
- package/registry/blocks/time-strip/demo.jsx +129 -0
- package/registry/blocks/time-strip/index.js +19 -0
- package/registry/blocks/time-strip/strip-model.js +178 -0
- package/registry/blocks/time-strip/time-strip.jsx +260 -0
- package/registry/blocks/top-bar/README.md +149 -0
- package/registry/blocks/top-bar/block.json +35 -0
- package/registry/blocks/top-bar/demo.jsx +78 -0
- package/registry/blocks/top-bar/index.js +5 -0
- package/registry/blocks/top-bar/probe-rules.js +74 -0
- package/registry/blocks/top-bar/top-bar-model.js +152 -0
- package/registry/blocks/top-bar/top-bar.jsx +244 -0
- package/registry/blocks/trigger-picker/README.md +98 -0
- package/registry/blocks/trigger-picker/block.json +38 -0
- package/registry/blocks/trigger-picker/demo.jsx +59 -0
- package/registry/blocks/trigger-picker/index.js +3 -0
- package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
- package/registry/blocks/whiteboard/README.md +20 -14
- package/registry/blocks/workflow-view/README.md +123 -0
- package/registry/blocks/workflow-view/block.json +10 -0
- package/registry/blocks/workflow-view/demo.jsx +90 -0
- package/registry/blocks/workflow-view/index.js +3 -0
- package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
- package/src/cli.mjs +2 -2
- package/src/install.mjs +100 -22
- package/src/registry.mjs +37 -3
- package/templates/next/browser/lib/data.js +6 -1
- package/templates/next/files/README.md +909 -26
- package/templates/next/files/app/shell.jsx +54 -37
- package/templates/next/files/check/automation-format.ts +2103 -0
- package/templates/next/files/check/automation-package.ts +142 -0
- package/templates/next/files/check/run.mjs +1043 -12
- package/templates/next/files/components/ui/field.jsx +17 -4
- package/templates/next/files/components/ui/icon.jsx +13 -0
- package/templates/next/files/components/ui/index.js +3 -1
- package/templates/next/files/components/ui/layout.jsx +382 -0
- package/templates/next/files/components/ui/notice.jsx +70 -0
- package/templates/next/files/components/ui/page.jsx +124 -0
- package/templates/next/files/components/ui/stat.jsx +22 -7
- package/templates/next/files/components/ui/toast.jsx +6 -3
- package/templates/next/files/lib/automations.js +660 -0
- package/templates/next/files/lib/claw.js +244 -5
- package/templates/next/files/lib/door.js +92 -0
- package/templates/next/files/lib/hooks.js +1694 -6
- package/templates/next/files/lib/platform.js +611 -14
- package/templates/next/template.json +22 -3
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "needs-you",
|
|
3
|
+
"title": "NeedsYou",
|
|
4
|
+
"description": "What waits on the member, in the app: NeedsYou is the queue of the agent's questions and yeses — a question is answered in place (QuestionBox: its options, and the member's own words where it welcomes them), a yes is the `approval` block's press frame (renderYes), and the rest open the desk (\"Waiting for your yes on the desk\" when the press frame cannot load, \"Connect on the desk\"); WaitingYes is the frozen-text card for that fallback — what goes out, frozen, then \"Waiting for your yes on the desk\", Open the desk and Take the ask back; AgentWorking is the strip while the agent works, with what it is on, Stop, and \"Stop keeps everything written so far\". Fed by useNeedsYou() (lib/hooks.js). Never an Approve in the app's own code: the yes is pressed in the Makersclaw-held frame; account sign-ins and money stay on the desk.",
|
|
5
|
+
"useWhen": "A home screen or a record that should say what the agent waits on and let the member settle it there (answer a question, give a yes before sending or spending), a screen where something is about to go out (a post, an email, a batch) and waits for the member's yes, or any place an ask is running and the member should be able to stop it. For the yes card itself use approval; for the conversation use agent-chat; for one job's progress use job-panel.",
|
|
6
|
+
"tags": [
|
|
7
|
+
"needs you",
|
|
8
|
+
"approval",
|
|
9
|
+
"yes",
|
|
10
|
+
"waiting",
|
|
11
|
+
"inbox",
|
|
12
|
+
"queue",
|
|
13
|
+
"agent",
|
|
14
|
+
"stop",
|
|
15
|
+
"working",
|
|
16
|
+
"take back",
|
|
17
|
+
"send",
|
|
18
|
+
"desk",
|
|
19
|
+
"question",
|
|
20
|
+
"answer",
|
|
21
|
+
"press"
|
|
22
|
+
],
|
|
23
|
+
"exports": [
|
|
24
|
+
"NeedsYou",
|
|
25
|
+
"QuestionBox",
|
|
26
|
+
"WaitingYes",
|
|
27
|
+
"AgentWorking"
|
|
28
|
+
],
|
|
29
|
+
"files": [
|
|
30
|
+
"index.js",
|
|
31
|
+
"needs-you.jsx"
|
|
32
|
+
],
|
|
33
|
+
"requires": []
|
|
34
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// NeedsYou, WaitingYes and AgentWorking in every state, with fake data
|
|
4
|
+
// shaped as useNeedsYou() returns it — the gallery's and the smoke test's
|
|
5
|
+
// surface. Not installed into apps.
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { NeedsYou, WaitingYes, AgentWorking } from "../components/blocks/needs-you";
|
|
8
|
+
|
|
9
|
+
const ITEMS = [
|
|
10
|
+
{
|
|
11
|
+
id: "n1",
|
|
12
|
+
request: { id: "r1" },
|
|
13
|
+
kind: "yes",
|
|
14
|
+
title: "Follow-ups to the investor list",
|
|
15
|
+
text: "Send 12 follow-ups from ada@acme.com to the investors on the list?",
|
|
16
|
+
at: "2026-10-09T09:12:00Z",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "n2",
|
|
20
|
+
request: { id: "r2" },
|
|
21
|
+
kind: "question",
|
|
22
|
+
title: "Pinewood's renewal",
|
|
23
|
+
text: "Pinewood has two contacts named Sam. Which one owns the renewal: Sam Ortiz (operations) or Sam Lee (finance)?",
|
|
24
|
+
at: "09:40",
|
|
25
|
+
},
|
|
26
|
+
{ id: "n3", request: { id: "r3" }, kind: "connect", title: "Morning read", text: "Connect a mailbox so the agent can read replies.", at: "Yesterday" },
|
|
27
|
+
{ id: "n4", request: { id: "r4" }, kind: "spend", title: "Enrich 480 companies", text: "This uses about 19,200 credits, at most 24,000.", at: "Mon" },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// The same queue with what the app can settle itself (0.8.1, D18/D19): a
|
|
31
|
+
// question answered in place, a yes through the approval card.
|
|
32
|
+
const IN_APP = [
|
|
33
|
+
{
|
|
34
|
+
id: "a1",
|
|
35
|
+
request: { id: "r5" },
|
|
36
|
+
kind: "question",
|
|
37
|
+
via: "answer",
|
|
38
|
+
options: [
|
|
39
|
+
{ id: "ortiz", label: "Sam Ortiz (operations)" },
|
|
40
|
+
{ id: "lee", label: "Sam Lee (finance)" },
|
|
41
|
+
],
|
|
42
|
+
free: true,
|
|
43
|
+
title: "Pinewood's renewal",
|
|
44
|
+
text: "Pinewood has two contacts named Sam. Which one owns the renewal?",
|
|
45
|
+
at: "09:40",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "a2",
|
|
49
|
+
request: { id: "r6" },
|
|
50
|
+
kind: "yes",
|
|
51
|
+
via: "press",
|
|
52
|
+
title: "Follow-ups to the investor list",
|
|
53
|
+
text: "Send 12 follow-ups from ada@acme.com to the investors on the list?",
|
|
54
|
+
at: "09:12",
|
|
55
|
+
},
|
|
56
|
+
{ id: "a3", request: { id: "r7" }, kind: "connect", via: null, title: "Morning read", text: "Connect a mailbox so the agent can read replies.", at: "Yesterday" },
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
const POST = `How to cover a sudden sick day
|
|
60
|
+
|
|
61
|
+
When someone calls in sick at 6 a.m., the shift still has to open. Here is the three-message routine our customers use…`;
|
|
62
|
+
|
|
63
|
+
const pause = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
64
|
+
|
|
65
|
+
export default function NeedsYouDemo() {
|
|
66
|
+
const [stopping, setStopping] = useState(false);
|
|
67
|
+
const [stopped, setStopped] = useState(false);
|
|
68
|
+
return (
|
|
69
|
+
<div className="grid gap-6 p-6">
|
|
70
|
+
<div className="grid gap-4 [grid-template-columns:repeat(auto-fit,minmax(min(100%,22rem),1fr))]">
|
|
71
|
+
<NeedsYou items={ITEMS} onOpen={() => pause(500)} />
|
|
72
|
+
<NeedsYou
|
|
73
|
+
title="Needs you · settled here"
|
|
74
|
+
items={IN_APP}
|
|
75
|
+
onOpen={() => pause(500)}
|
|
76
|
+
onAnswer={() => pause(600).then(() => ({ ok: true }))}
|
|
77
|
+
renderYes={() => <p className="rounded-[var(--radius)] border border-border p-2.5 text-muted-foreground">The approval card sits here.</p>}
|
|
78
|
+
/>
|
|
79
|
+
<div className="grid content-start gap-4">
|
|
80
|
+
<NeedsYou items={[]} />
|
|
81
|
+
<NeedsYou items={[]} loading title="Needs you · loading" />
|
|
82
|
+
<NeedsYou items={[]} unavailable />
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div className="grid gap-4 [grid-template-columns:repeat(auto-fit,minmax(min(100%,20rem),1fr))]">
|
|
87
|
+
<WaitingYes
|
|
88
|
+
title="How to cover a sudden sick day"
|
|
89
|
+
frozen={POST}
|
|
90
|
+
body="Say yes there, and the agent makes this one post live on Webflow, then adds its link here."
|
|
91
|
+
onOpen={() => true}
|
|
92
|
+
onTakeBack={() => pause(700).then(() => ({ ok: true }))}
|
|
93
|
+
/>
|
|
94
|
+
<WaitingYes title="Kickoff note to Harbor Seed" frozen="Hi Ana — thanks for the intro…" kicker="Ready to send" state="ready" />
|
|
95
|
+
<WaitingYes title="Weekly digest" frozen="Five things that moved this week…" state="approved" />
|
|
96
|
+
<WaitingYes
|
|
97
|
+
title="Price change to the Pro plan"
|
|
98
|
+
frozen="From 1 November, Pro is $35 a month."
|
|
99
|
+
state="failed"
|
|
100
|
+
error="Webflow refused the change: the page is locked by another editor."
|
|
101
|
+
onOpen={() => true}
|
|
102
|
+
/>
|
|
103
|
+
<WaitingYes
|
|
104
|
+
title="A take back that fails"
|
|
105
|
+
frozen="Hi team — the release moves to Thursday."
|
|
106
|
+
onOpen={() => true}
|
|
107
|
+
onTakeBack={() => pause(500).then(() => ({ ok: false, error: "The agent already started sending. Stop it on the desk." }))}
|
|
108
|
+
/>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div className="grid gap-3">
|
|
112
|
+
{stopped ? (
|
|
113
|
+
<p className="text-sm text-muted-foreground">Stopped. Everything written so far is kept.</p>
|
|
114
|
+
) : (
|
|
115
|
+
<AgentWorking
|
|
116
|
+
words="Writing the follow-ups"
|
|
117
|
+
steps={[
|
|
118
|
+
{ label: "Reading the investor list", status: "done" },
|
|
119
|
+
{ label: "Reading last month's notes", status: "done" },
|
|
120
|
+
{ label: "Drafting note 4 of 12", status: "running" },
|
|
121
|
+
]}
|
|
122
|
+
stopping={stopping}
|
|
123
|
+
onStop={() => {
|
|
124
|
+
setStopping(true);
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
setStopping(false);
|
|
127
|
+
setStopped(true);
|
|
128
|
+
}, 700);
|
|
129
|
+
}}
|
|
130
|
+
/>
|
|
131
|
+
)}
|
|
132
|
+
<AgentWorking words="Sorting the stickies into groups" />
|
|
133
|
+
<div className="w-80 max-w-full">
|
|
134
|
+
<AgentWorking
|
|
135
|
+
words="Reading every deal note since March and writing a summary for each account owner"
|
|
136
|
+
steps={[{ label: "Reading notes for Pinewood Restaurant Group, Harborview and nine more", status: "running" }]}
|
|
137
|
+
onStop={() => undefined}
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Button, Icon, Input, Skeleton, Spinner, cx } from "../../ui";
|
|
5
|
+
|
|
6
|
+
// What waits on the member, in the app (the app kit, D15). Four pieces:
|
|
7
|
+
//
|
|
8
|
+
// NeedsYou the queue: the agent's questions and its yeses. A
|
|
9
|
+
// question is answered in place (QuestionBox, 0.8.1, D19);
|
|
10
|
+
// a yes is the `approval` block's press frame, given to
|
|
11
|
+
// `renderYes` (D18); everything else opens the desk.
|
|
12
|
+
// QuestionBox the agent's question answered where it was asked: its
|
|
13
|
+
// options as one press each, and the member's own words
|
|
14
|
+
// where the question welcomes them.
|
|
15
|
+
// WaitingYes the frozen-text card: what goes out, frozen, then
|
|
16
|
+
// "Waiting for your yes on the desk", Open the desk, and
|
|
17
|
+
// Take the ask back (Blog Post Studio's design).
|
|
18
|
+
// AgentWorking the strip while the agent works: what it is on, Stop,
|
|
19
|
+
// and "Stop keeps everything written so far".
|
|
20
|
+
//
|
|
21
|
+
// Fed by useNeedsYou() (lib/hooks.js). An answer is words, so the app
|
|
22
|
+
// takes it (D19). The YES is not: these blocks never draw an Approve — the
|
|
23
|
+
// press is the Makersclaw-held frame of the `approval` block, which app
|
|
24
|
+
// code cannot press (D18). The account sign-in and money stay on the
|
|
25
|
+
// desk. WaitingYes is the card for when the press frame cannot load: it
|
|
26
|
+
// says the yes waits on the desk and opens it. Props in, callbacks out.
|
|
27
|
+
|
|
28
|
+
const ISO = /^\d{4}-\d{2}-\d{2}T/;
|
|
29
|
+
|
|
30
|
+
/** "11:20" today, "12 Sep" another day; words as given. */
|
|
31
|
+
function when(at) {
|
|
32
|
+
if (at == null || at === "") return null;
|
|
33
|
+
const d = at instanceof Date ? at : typeof at === "string" && ISO.test(at) ? new Date(at) : null;
|
|
34
|
+
if (!d) return { words: String(at) };
|
|
35
|
+
if (Number.isNaN(d.getTime())) return null;
|
|
36
|
+
const today = d.toDateString() === new Date().toDateString();
|
|
37
|
+
return {
|
|
38
|
+
words: today ? d.toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" }) : d.toLocaleDateString("en-GB", { day: "numeric", month: "short" }),
|
|
39
|
+
iso: d.toISOString(),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Each kind of need: its word, its icon, what its one press says. */
|
|
44
|
+
const KINDS = {
|
|
45
|
+
question: { word: "A question", icon: "circle-help", head: "Waiting for your answer on the desk", press: "Answer on the desk" },
|
|
46
|
+
yes: { word: "Your yes", icon: "shield-check", head: "Waiting for your yes on the desk", press: "Open the desk" },
|
|
47
|
+
approval: { word: "Your yes", icon: "shield-check", head: "Waiting for your yes on the desk", press: "Open the desk" },
|
|
48
|
+
spend: { word: "Spending", icon: "credit-card", head: "Waiting for your yes to spend, on the desk", press: "Open the desk" },
|
|
49
|
+
limit: { word: "Credits", icon: "credit-card", head: "Paused for credits — see the desk", press: "Open the desk" },
|
|
50
|
+
connect: { word: "An account", icon: "link", head: "Waiting for you to connect an account on the desk", press: "Connect on the desk" },
|
|
51
|
+
};
|
|
52
|
+
const OTHER = { word: "Needs you", icon: "bell", head: "Needs you on the desk", press: "Open the desk" };
|
|
53
|
+
const kindOf = (k) => KINDS[k] ?? OTHER;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The agent's question, answered where it was asked (D19). Its options are
|
|
57
|
+
* one press each (a lone question with options answers on the spot, as the
|
|
58
|
+
* desk's form does), and where the question welcomes words there is a box
|
|
59
|
+
* for them.
|
|
60
|
+
*
|
|
61
|
+
* options [{ id, label }] the question offers (none: words only)
|
|
62
|
+
* free false when the question takes one of its options only
|
|
63
|
+
* onAnswer({ optionId } | { text }) async → { ok } | { ok: false, error }
|
|
64
|
+
* placeholder, sendLabel the box's words
|
|
65
|
+
*
|
|
66
|
+
* Fed by useNeedsYou().answer(item, …) or useAgentThread().answer(…). The
|
|
67
|
+
* door checks it all again (the member who asked, one of the options, the
|
|
68
|
+
* words not empty): a refusal is shown as it is.
|
|
69
|
+
*/
|
|
70
|
+
export function QuestionBox({ options = [], free = true, onAnswer, placeholder, sendLabel = "Send answer", className }) {
|
|
71
|
+
const list = Array.isArray(options) ? options.filter((o) => o && o.id) : [];
|
|
72
|
+
const [text, setText] = useState("");
|
|
73
|
+
const [busy, setBusy] = useState(null); // an option id, or "text"
|
|
74
|
+
const [error, setError] = useState(null);
|
|
75
|
+
const [sent, setSent] = useState(false);
|
|
76
|
+
if (!onAnswer) return null;
|
|
77
|
+
|
|
78
|
+
async function give(payload, which) {
|
|
79
|
+
if (busy || sent) return;
|
|
80
|
+
setBusy(which);
|
|
81
|
+
setError(null);
|
|
82
|
+
let r;
|
|
83
|
+
try {
|
|
84
|
+
r = await onAnswer(payload);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
r = { ok: false, error: e?.message ?? String(e) };
|
|
87
|
+
}
|
|
88
|
+
setBusy(null);
|
|
89
|
+
if (r && r.ok === false) setError(r.error || "That did not go through. Try again.");
|
|
90
|
+
else setSent(true);
|
|
91
|
+
}
|
|
92
|
+
const words = text.trim();
|
|
93
|
+
const hasBox = free !== false || list.length === 0;
|
|
94
|
+
|
|
95
|
+
if (sent)
|
|
96
|
+
return (
|
|
97
|
+
<p role="status" className={cx("flex items-center gap-2 text-sm text-success", className)}>
|
|
98
|
+
<Icon name="check" size={14} className="shrink-0" /> Sent. The agent is on it.
|
|
99
|
+
</p>
|
|
100
|
+
);
|
|
101
|
+
return (
|
|
102
|
+
<div className={cx("grid grid-cols-1 min-w-0 gap-2", className)}>
|
|
103
|
+
{list.length ? (
|
|
104
|
+
<div className="flex min-w-0 flex-wrap gap-1.5">
|
|
105
|
+
{list.map((o) => (
|
|
106
|
+
<Button key={o.id} size="sm" variant="secondary" loading={busy === o.id} disabled={Boolean(busy) && busy !== o.id} onClick={() => give({ optionId: o.id }, o.id)}>
|
|
107
|
+
{o.label}
|
|
108
|
+
</Button>
|
|
109
|
+
))}
|
|
110
|
+
</div>
|
|
111
|
+
) : null}
|
|
112
|
+
{hasBox ? (
|
|
113
|
+
<form
|
|
114
|
+
className="flex min-w-0 items-center gap-2"
|
|
115
|
+
onSubmit={(e) => {
|
|
116
|
+
e.preventDefault();
|
|
117
|
+
if (words) give({ text: words }, "text");
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
<Input
|
|
121
|
+
aria-label={placeholder ?? (list.length ? "Or answer in your own words" : "Your answer")}
|
|
122
|
+
placeholder={placeholder ?? (list.length ? "Or answer in your own words…" : "Your answer…")}
|
|
123
|
+
value={text}
|
|
124
|
+
disabled={Boolean(busy)}
|
|
125
|
+
onChange={(e) => setText(e.target.value)}
|
|
126
|
+
className="min-w-0 flex-1"
|
|
127
|
+
/>
|
|
128
|
+
<Button size="sm" variant="primary" type="submit" loading={busy === "text"} disabled={!words || Boolean(busy)}>
|
|
129
|
+
{sendLabel}
|
|
130
|
+
</Button>
|
|
131
|
+
</form>
|
|
132
|
+
) : null}
|
|
133
|
+
{error ? (
|
|
134
|
+
<p role="alert" className="text-xs text-destructive">
|
|
135
|
+
{error}
|
|
136
|
+
</p>
|
|
137
|
+
) : null}
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** One thing that waits. */
|
|
143
|
+
function Need({ item, onOpen, onAnswer, renderYes }) {
|
|
144
|
+
const k = kindOf(item.kind);
|
|
145
|
+
const answerHere = item.via === "answer" && Boolean(onAnswer);
|
|
146
|
+
const pressHere = item.via === "press" && typeof renderYes === "function";
|
|
147
|
+
const t = when(item.at);
|
|
148
|
+
const [opening, setOpening] = useState(false);
|
|
149
|
+
async function open() {
|
|
150
|
+
if (!onOpen || opening) return;
|
|
151
|
+
setOpening(true);
|
|
152
|
+
try {
|
|
153
|
+
await onOpen(item);
|
|
154
|
+
} finally {
|
|
155
|
+
setOpening(false);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return (
|
|
159
|
+
<li
|
|
160
|
+
className={cx(
|
|
161
|
+
"grid grid-cols-1 min-w-0 gap-2 border-b border-border px-3.5 py-3 last:border-b-0",
|
|
162
|
+
!answerHere && !pressHere && "@lg:grid-cols-[minmax(0,1fr)_auto] @lg:items-start",
|
|
163
|
+
)}
|
|
164
|
+
>
|
|
165
|
+
<div className="flex min-w-0 items-start gap-2.5">
|
|
166
|
+
<Icon name={k.icon} size={16} className="mt-0.5 shrink-0 text-warning" />
|
|
167
|
+
<div className="grid grid-cols-1 min-w-0 gap-0.5">
|
|
168
|
+
<p className="flex min-w-0 flex-wrap items-baseline gap-x-2 text-xs text-muted-foreground">
|
|
169
|
+
<span className="font-medium text-foreground">{k.word}</span>
|
|
170
|
+
{item.title ? <span className="min-w-0 break-words">{item.title}</span> : null}
|
|
171
|
+
{t ? <time dateTime={t.iso}>{t.words}</time> : null}
|
|
172
|
+
</p>
|
|
173
|
+
<p className="font-medium">{answerHere ? "A question for you" : pressHere ? "Waiting for your yes" : k.head}</p>
|
|
174
|
+
{item.text ? <p className={cx("break-words text-muted-foreground", !answerHere && !pressHere && "line-clamp-3")}>{item.text}</p> : null}
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
{answerHere ? (
|
|
178
|
+
<QuestionBox
|
|
179
|
+
options={item.options ?? []}
|
|
180
|
+
free={item.free}
|
|
181
|
+
onAnswer={(payload) => onAnswer(item, payload)}
|
|
182
|
+
className="pl-[26px]"
|
|
183
|
+
/>
|
|
184
|
+
) : pressHere ? (
|
|
185
|
+
<div className="min-w-0 pl-[26px]">{renderYes(item)}</div>
|
|
186
|
+
) : onOpen ? (
|
|
187
|
+
<Button size="sm" variant="secondary" loading={opening} onClick={open} className="justify-self-start @lg:justify-self-end">
|
|
188
|
+
{k.press} <Icon name="external" size={12} />
|
|
189
|
+
</Button>
|
|
190
|
+
) : null}
|
|
191
|
+
</li>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* items what useNeedsYou() returns as `items`:
|
|
197
|
+
* [{ id, request, kind, text, title, at, via, options,
|
|
198
|
+
* free, needsAt }]; kind is question · yes · spend ·
|
|
199
|
+
* connect (another word reads "Needs you"); `via` says how
|
|
200
|
+
* the app can settle it ("answer", "press" or null: the desk)
|
|
201
|
+
* onOpen(item) opens it on the desk (useNeedsYou's `open`); the press
|
|
202
|
+
* of everything the app cannot settle itself
|
|
203
|
+
* onAnswer(item, { optionId | text }) answers a question in place
|
|
204
|
+
* (useNeedsYou's `answer`, D19): an item with via "answer"
|
|
205
|
+
* shows its QuestionBox; without it, it opens the desk
|
|
206
|
+
* renderYes(item) draws the yes of an item with via "press" (D18):
|
|
207
|
+
* `<YesCard item={item} />`, a component of yours that
|
|
208
|
+
* calls useApproval(item.id) and returns the `approval`
|
|
209
|
+
* block; without it the item opens the desk
|
|
210
|
+
* empty the line when nothing waits (default "Nothing waits on
|
|
211
|
+
* you here."); `false` draws nothing at all then
|
|
212
|
+
* title the head (default "Needs you"); `null` for none
|
|
213
|
+
* loading skeleton rows before the first read
|
|
214
|
+
* unavailable a quiet "not connected yet" instead of the list
|
|
215
|
+
*/
|
|
216
|
+
export function NeedsYou({ items = [], onOpen, onAnswer, renderYes, empty = "Nothing waits on you here.", title = "Needs you", loading = false, unavailable = false, className }) {
|
|
217
|
+
const list = (items ?? []).filter(Boolean);
|
|
218
|
+
if (!list.length && empty === false && !loading) return null;
|
|
219
|
+
return (
|
|
220
|
+
<section aria-label={typeof title === "string" ? title : "Needs you"} className={cx("@container min-w-0 overflow-hidden rounded-lg border border-border bg-card text-sm text-card-foreground", className)}>
|
|
221
|
+
{title ? (
|
|
222
|
+
<div className="flex min-w-0 items-center gap-2 border-b border-border px-3.5 py-2.5 font-semibold">
|
|
223
|
+
<span className="min-w-0 flex-1 truncate">{title}</span>
|
|
224
|
+
{list.length ? <span className="shrink-0 rounded-full bg-warning/15 px-2 text-xs font-medium text-warning">{list.length}</span> : null}
|
|
225
|
+
</div>
|
|
226
|
+
) : null}
|
|
227
|
+
{unavailable ? (
|
|
228
|
+
<p className="px-3.5 py-3 text-muted-foreground">What waits on you is not connected yet.</p>
|
|
229
|
+
) : loading && !list.length ? (
|
|
230
|
+
<div aria-busy="true" aria-label="Loading" className="grid grid-cols-1 gap-3 px-3.5 py-3">
|
|
231
|
+
<Skeleton className="w-3/4" />
|
|
232
|
+
<Skeleton className="w-1/2" />
|
|
233
|
+
</div>
|
|
234
|
+
) : !list.length ? (
|
|
235
|
+
<p className="flex items-center gap-2 px-3.5 py-3 text-muted-foreground">
|
|
236
|
+
<Icon name="check" size={14} className="shrink-0 text-success" />
|
|
237
|
+
{empty}
|
|
238
|
+
</p>
|
|
239
|
+
) : (
|
|
240
|
+
<ul className="m-0 grid grid-cols-1 list-none p-0">
|
|
241
|
+
{list.map((item, i) => (
|
|
242
|
+
<Need key={item.id ?? i} item={item} onOpen={onOpen} onAnswer={onAnswer} renderYes={renderYes} />
|
|
243
|
+
))}
|
|
244
|
+
</ul>
|
|
245
|
+
)}
|
|
246
|
+
</section>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** What WaitingYes says in each state. */
|
|
251
|
+
const YES = {
|
|
252
|
+
ready: null,
|
|
253
|
+
waiting: { icon: "clock", head: "Waiting for your yes on the desk", tone: "text-primary" },
|
|
254
|
+
approved: { icon: "check", head: "You said yes · the agent is on it", tone: "text-success" },
|
|
255
|
+
declined: { icon: "x", head: "You said no on the desk. Nothing went out.", tone: "text-muted-foreground" },
|
|
256
|
+
taken: { icon: "undo", head: "Taken back. Nothing went out.", tone: "text-muted-foreground" },
|
|
257
|
+
failed: { icon: "warning", head: "It didn't go through", tone: "text-destructive" },
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* The frozen-text card: what goes out, frozen while the ask waits, and
|
|
262
|
+
* where it stands. Never an Approve: the yes is the `approval` block's
|
|
263
|
+
* press frame (D18), and this card is what shows when that frame cannot
|
|
264
|
+
* load — "Waiting for your yes on the desk", with the desk one press away.
|
|
265
|
+
*
|
|
266
|
+
* title what it is ("How to cover a sudden sick day")
|
|
267
|
+
* frozen what goes out, as it will go (text or a node)
|
|
268
|
+
* kicker the line over it (default "Ready to send")
|
|
269
|
+
* state ready · waiting (default) · approved · declined ·
|
|
270
|
+
* taken · failed
|
|
271
|
+
* body one sentence under the state, in the app's words
|
|
272
|
+
* (default: "The ask is on your desk. Say yes there, and
|
|
273
|
+
* the agent does it.")
|
|
274
|
+
* error the words for `failed`
|
|
275
|
+
* onOpen() opens the desk on this ask (useNeedsYou's `open`)
|
|
276
|
+
* onTakeBack() async → { ok } | { ok: false, error }: stops the ask
|
|
277
|
+
* while the agent has not acted (useNeedsYou's `takeBack`);
|
|
278
|
+
* without it there is no Take back
|
|
279
|
+
* takeBackLabel default "Take the ask back"
|
|
280
|
+
*/
|
|
281
|
+
export function WaitingYes({
|
|
282
|
+
title,
|
|
283
|
+
frozen,
|
|
284
|
+
kicker = "Ready to send",
|
|
285
|
+
state = "waiting",
|
|
286
|
+
body = "The ask is on your desk. Say yes there, and the agent does it.",
|
|
287
|
+
error,
|
|
288
|
+
onOpen,
|
|
289
|
+
onTakeBack,
|
|
290
|
+
takeBackLabel = "Take the ask back",
|
|
291
|
+
className,
|
|
292
|
+
}) {
|
|
293
|
+
const [taking, setTaking] = useState(false);
|
|
294
|
+
const [takeError, setTakeError] = useState(null);
|
|
295
|
+
const [taken, setTaken] = useState(false);
|
|
296
|
+
const now = taken ? "taken" : state;
|
|
297
|
+
const s = YES[now] ?? YES.waiting;
|
|
298
|
+
|
|
299
|
+
async function takeBack() {
|
|
300
|
+
if (!onTakeBack || taking) return;
|
|
301
|
+
setTaking(true);
|
|
302
|
+
setTakeError(null);
|
|
303
|
+
let r;
|
|
304
|
+
try {
|
|
305
|
+
r = await onTakeBack();
|
|
306
|
+
} catch (e) {
|
|
307
|
+
r = { ok: false, error: e?.message ?? String(e) };
|
|
308
|
+
}
|
|
309
|
+
setTaking(false);
|
|
310
|
+
if (r && r.ok === false) setTakeError(r.error || "Couldn't take it back. Open the desk to stop it there.");
|
|
311
|
+
else setTaken(true);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return (
|
|
315
|
+
<section
|
|
316
|
+
aria-label={typeof title === "string" ? title : "What goes out"}
|
|
317
|
+
className={cx("@container grid grid-cols-1 min-w-0 content-start gap-3 rounded-lg border border-border bg-card p-3.5 text-sm text-card-foreground", className)}
|
|
318
|
+
>
|
|
319
|
+
<div className="grid grid-cols-1 min-w-0 gap-1">
|
|
320
|
+
{kicker ? (
|
|
321
|
+
<p className="flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
322
|
+
{now !== "ready" && now !== "taken" ? <Icon name="lock" size={12} label="Frozen while it waits" /> : null}
|
|
323
|
+
{kicker}
|
|
324
|
+
</p>
|
|
325
|
+
) : null}
|
|
326
|
+
{title ? <p className="break-words text-[15px] font-semibold leading-snug">{title}</p> : null}
|
|
327
|
+
</div>
|
|
328
|
+
{frozen != null && frozen !== "" ? (
|
|
329
|
+
<div
|
|
330
|
+
className={cx(
|
|
331
|
+
"min-w-0 whitespace-pre-wrap break-words rounded-[var(--radius)] border border-border px-3 py-2.5",
|
|
332
|
+
now === "ready" || now === "taken" ? "bg-background" : "bg-muted text-muted-foreground",
|
|
333
|
+
)}
|
|
334
|
+
>
|
|
335
|
+
{frozen}
|
|
336
|
+
</div>
|
|
337
|
+
) : null}
|
|
338
|
+
|
|
339
|
+
{s ? (
|
|
340
|
+
<div role="status" className="grid grid-cols-1 min-w-0 gap-2 border-t border-border pt-3">
|
|
341
|
+
<p className={cx("flex min-w-0 items-center gap-2 font-medium", now === "waiting" ? null : s.tone)}>
|
|
342
|
+
<Icon name={s.icon} size={16} className={cx("shrink-0", s.tone)} />
|
|
343
|
+
<span className="min-w-0 break-words">{s.head}</span>
|
|
344
|
+
</p>
|
|
345
|
+
{now === "waiting" && body ? <p className="text-muted-foreground">{body}</p> : null}
|
|
346
|
+
{now === "failed" && error ? <p className="text-destructive">{error}</p> : null}
|
|
347
|
+
{now === "waiting" ? (
|
|
348
|
+
<div className="flex min-w-0 flex-wrap items-center gap-2">
|
|
349
|
+
{onOpen ? (
|
|
350
|
+
<Button size="sm" variant="primary" onClick={onOpen}>
|
|
351
|
+
Open the desk <Icon name="external" size={12} />
|
|
352
|
+
</Button>
|
|
353
|
+
) : null}
|
|
354
|
+
{onTakeBack ? (
|
|
355
|
+
<>
|
|
356
|
+
<Button size="sm" variant="quiet" loading={taking} onClick={takeBack}>
|
|
357
|
+
{takeBackLabel}
|
|
358
|
+
</Button>
|
|
359
|
+
<span className="text-xs text-muted-foreground">while the agent hasn't acted</span>
|
|
360
|
+
</>
|
|
361
|
+
) : null}
|
|
362
|
+
</div>
|
|
363
|
+
) : now === "failed" && onOpen ? (
|
|
364
|
+
<Button size="sm" variant="secondary" className="justify-self-start" onClick={onOpen}>
|
|
365
|
+
Open the desk <Icon name="external" size={12} />
|
|
366
|
+
</Button>
|
|
367
|
+
) : null}
|
|
368
|
+
{takeError ? (
|
|
369
|
+
<p role="alert" className="text-xs text-destructive">
|
|
370
|
+
{takeError}
|
|
371
|
+
</p>
|
|
372
|
+
) : null}
|
|
373
|
+
</div>
|
|
374
|
+
) : null}
|
|
375
|
+
</section>
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* The strip while the agent works on an ask: what it is on now, Stop,
|
|
381
|
+
* and what Stop keeps.
|
|
382
|
+
*
|
|
383
|
+
* words what it is doing ("Writing the draft"); default "Working on it"
|
|
384
|
+
* steps [{ label, status: running · done · failed }]: the running
|
|
385
|
+
* step's label shows, with the count
|
|
386
|
+
* onStop() stops it (useNeedsYou's `stop`, useAgentThread's `stop`);
|
|
387
|
+
* may be async → { ok } | { ok: false, error }; without it
|
|
388
|
+
* there is no Stop (the member may not stop it)
|
|
389
|
+
* stopping true while a stop you track is out
|
|
390
|
+
* stopHint default "Stop keeps everything written so far"; null for none
|
|
391
|
+
*/
|
|
392
|
+
export function AgentWorking({ words = "Working on it", steps, onStop, stopping = false, stopHint = "Stop keeps everything written so far", className }) {
|
|
393
|
+
const list = Array.isArray(steps) ? steps : [];
|
|
394
|
+
const running = list.filter((s) => s?.status === "running").at(-1);
|
|
395
|
+
const done = list.filter((s) => s?.status === "done").length;
|
|
396
|
+
// useNeedsYou's stop(request) answers { ok } | { ok: false, error }: the
|
|
397
|
+
// strip spins while it is out and says why when it fails.
|
|
398
|
+
const [busy, setBusy] = useState(false);
|
|
399
|
+
const [error, setError] = useState(null);
|
|
400
|
+
async function stop() {
|
|
401
|
+
if (!onStop || busy || stopping) return;
|
|
402
|
+
setBusy(true);
|
|
403
|
+
setError(null);
|
|
404
|
+
let r;
|
|
405
|
+
try {
|
|
406
|
+
r = await onStop();
|
|
407
|
+
} catch (e) {
|
|
408
|
+
r = { ok: false, error: e?.message ?? String(e) };
|
|
409
|
+
}
|
|
410
|
+
setBusy(false);
|
|
411
|
+
if (r && r.ok === false) setError(r.error || "Couldn't stop it. Open the desk to stop it there.");
|
|
412
|
+
}
|
|
413
|
+
return (
|
|
414
|
+
<div role="status" className={cx("@container flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1.5 rounded-lg border border-border bg-card px-3.5 py-2.5 text-sm text-card-foreground", className)}>
|
|
415
|
+
<Spinner size="sm" label="Working" className="shrink-0 text-primary" />
|
|
416
|
+
<div className="grid grid-cols-1 min-w-0 flex-1 basis-48 gap-0.5">
|
|
417
|
+
<span className="min-w-0 break-words font-medium">{words}</span>
|
|
418
|
+
{running || list.length ? (
|
|
419
|
+
<span className="min-w-0 truncate text-xs text-muted-foreground">
|
|
420
|
+
{running ? running.label : null}
|
|
421
|
+
{running && list.length > 1 ? " · " : null}
|
|
422
|
+
{list.length > 1 ? `${done} of ${list.length} steps done` : null}
|
|
423
|
+
</span>
|
|
424
|
+
) : null}
|
|
425
|
+
</div>
|
|
426
|
+
{onStop ? (
|
|
427
|
+
<span className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5">
|
|
428
|
+
{stopHint ? <span className="text-xs text-muted-foreground">{stopHint}</span> : null}
|
|
429
|
+
<Button size="sm" variant="secondary" loading={stopping || busy} onClick={stop}>
|
|
430
|
+
<Icon name="stop" size={12} /> Stop
|
|
431
|
+
</Button>
|
|
432
|
+
</span>
|
|
433
|
+
) : null}
|
|
434
|
+
{error ? (
|
|
435
|
+
<p role="alert" className="basis-full text-xs text-destructive">
|
|
436
|
+
{error}
|
|
437
|
+
</p>
|
|
438
|
+
) : null}
|
|
439
|
+
</div>
|
|
440
|
+
);
|
|
441
|
+
}
|
|
@@ -73,7 +73,9 @@ One row per person, as a table holds them:
|
|
|
73
73
|
reports: kit parts (their open deals, a "Message" button).
|
|
74
74
|
- `onSelectionChange(person | null)` — the selected card changed.
|
|
75
75
|
- `height` — px or any CSS length, default `640`. A height class in
|
|
76
|
-
`className` (`h-
|
|
76
|
+
`className` (`h-full`, `min-h-0 flex-1`) replaces it: `min-h-0 flex-1`
|
|
77
|
+
fills what the surface has left (the Example). Never `h-dvh` or a `vh`
|
|
78
|
+
height, which `npm run check` refuses.
|
|
77
79
|
- `label` — the chart's accessible name (default "Org chart").
|
|
78
80
|
- `className` — layout around it (margin, width, height). Never colour.
|
|
79
81
|
|
|
@@ -124,7 +126,7 @@ export default function TeamChart() {
|
|
|
124
126
|
if (res.ok) await whenLanded(); // the people are read again: the chart draws the new manager
|
|
125
127
|
return res;
|
|
126
128
|
}}
|
|
127
|
-
className="h-
|
|
129
|
+
className="min-h-0 flex-1"
|
|
128
130
|
/>
|
|
129
131
|
);
|
|
130
132
|
}
|