makersclaw 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- 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 +3 -3
- 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 +2 -2
- package/r/chat-pane.json +84 -0
- package/r/chat.json +2 -2
- 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 +13 -7
- 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 +2 -2
- package/r/flow-editor.json +79 -0
- package/r/footer.json +2 -2
- 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 +3 -3
- 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 +3 -3
- package/r/pace-bar.json +69 -0
- package/r/page-builder.json +2 -2
- package/r/payment-methods.json +2 -2
- package/r/pdf-document.json +2 -2
- package/r/pdf-viewer.json +2 -2
- 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 +4086 -1512
- 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 +2 -2
- package/r/signature-pad.json +2 -2
- package/r/sketch-canvas.json +2 -2
- 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 +3 -3
- 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 +234 -0
- package/registry/blocks/agent-pane/agent-pane.jsx +246 -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/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/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-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/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/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/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/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/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/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/install.mjs +77 -16
- package/src/registry.mjs +3 -0
- package/templates/next/browser/lib/data.js +6 -1
- package/templates/next/files/README.md +627 -24
- 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 +968 -9
- 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 +2 -1
- package/templates/next/files/components/ui/layout.jsx +77 -2
- 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 +241 -5
- package/templates/next/files/lib/door.js +92 -0
- package/templates/next/files/lib/hooks.js +1677 -8
- package/templates/next/files/lib/platform.js +529 -21
- package/templates/next/template.json +13 -3
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// The app's declared accounts as rows, the way the window's Settings ›
|
|
4
|
+
// Connections draws them: what each is for, live or not connected, which
|
|
5
|
+
// accounts meet it, and Connect (or Change). Props in, callbacks out: the
|
|
6
|
+
// press goes out as onConnect(key), which useConnections turns into the
|
|
7
|
+
// desk's connections panel (every provider of the kind; no agent turn),
|
|
8
|
+
// or a link in a new tab outside the desk. Signing in stays the member's,
|
|
9
|
+
// at the provider. Tokens only; live or not is a mark AND a word. Its own
|
|
10
|
+
// width decides its layout (@container): under about 384 px the state and
|
|
11
|
+
// the button go under the words.
|
|
12
|
+
|
|
13
|
+
import { Button, Icon, cx } from "../../ui";
|
|
14
|
+
|
|
15
|
+
/** Live or not, as a pill: a mark and a word. */
|
|
16
|
+
function StatePill({ connected, waiting }) {
|
|
17
|
+
const look = connected
|
|
18
|
+
? { icon: "circle-check", word: "Live", tone: "text-success border-success" }
|
|
19
|
+
: waiting
|
|
20
|
+
? { icon: "loader", word: "Waiting for sign-in", tone: "text-info border-info" }
|
|
21
|
+
: { icon: "circle-dashed", word: "Not connected", tone: "text-muted-foreground border-border" };
|
|
22
|
+
return (
|
|
23
|
+
<span className={cx("inline-flex shrink-0 items-center gap-1 rounded-full border px-2 py-0.5 text-[11.5px]", look.tone)}>
|
|
24
|
+
<Icon name={look.icon} size={12} className={waiting && !connected ? "animate-spin motion-reduce:animate-none" : undefined} />
|
|
25
|
+
{look.word}
|
|
26
|
+
</span>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* One declared account.
|
|
32
|
+
*
|
|
33
|
+
* connection { key, label, required, connected, accounts, category_label }
|
|
34
|
+
* (a row of useConnections' `connections`)
|
|
35
|
+
* onConnect(key) Connect / Change; leave it out and no button is drawn
|
|
36
|
+
* connecting this account is being connected: the pill waits
|
|
37
|
+
* connectLabel, changeLabel the button's words (default "Connect", "Change")
|
|
38
|
+
*/
|
|
39
|
+
export function ConnectRow({ connection, onConnect, connecting = false, connectLabel = "Connect", changeLabel = "Change", className }) {
|
|
40
|
+
const c = connection ?? {};
|
|
41
|
+
const accounts = Array.isArray(c.accounts) ? c.accounts.filter(Boolean) : [];
|
|
42
|
+
const meta = [c.category_label, c.required === true ? "Needed" : c.required === false ? "Optional" : null].filter(Boolean).join(" · ");
|
|
43
|
+
return (
|
|
44
|
+
<li className={cx("grid min-w-0 gap-2 px-3.5 py-3 @sm:grid-cols-[minmax(0,1fr)_auto] @sm:items-center @sm:gap-3", className)}>
|
|
45
|
+
<div className="grid min-w-0 gap-0.5">
|
|
46
|
+
<span className="line-clamp-2 text-[13px] text-card-foreground">{c.label}</span>
|
|
47
|
+
{meta ? <span className="truncate text-xs text-muted-foreground">{meta}</span> : null}
|
|
48
|
+
{c.connected && accounts.length ? (
|
|
49
|
+
<span className="truncate text-xs text-muted-foreground" title={accounts.join(", ")}>
|
|
50
|
+
{accounts.length === 1 ? accounts[0] : `${accounts[0]} and ${accounts.length - 1} more`}
|
|
51
|
+
</span>
|
|
52
|
+
) : null}
|
|
53
|
+
</div>
|
|
54
|
+
<div className="flex min-w-0 flex-wrap items-center gap-2 @sm:flex-nowrap @sm:justify-end">
|
|
55
|
+
<StatePill connected={Boolean(c.connected)} waiting={connecting} />
|
|
56
|
+
{onConnect ? (
|
|
57
|
+
<Button size="sm" variant={c.connected ? "quiet" : "secondary"} onClick={() => onConnect(c.key)} disabled={connecting && !c.connected}>
|
|
58
|
+
{c.connected ? changeLabel : connectLabel}
|
|
59
|
+
</Button>
|
|
60
|
+
) : null}
|
|
61
|
+
</div>
|
|
62
|
+
</li>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The app's accounts on a card.
|
|
68
|
+
*
|
|
69
|
+
* connections useConnections' `connections`
|
|
70
|
+
* onConnect(key) useConnections' `connect`
|
|
71
|
+
* connecting the key being connected (useConnections' `connecting`)
|
|
72
|
+
* title the card's head (default "Accounts it uses"); null for none
|
|
73
|
+
* description one line under it: what the app does with them
|
|
74
|
+
* empty what the card says with no accounts (null draws nothing)
|
|
75
|
+
*/
|
|
76
|
+
export function ConnectCard({ connections = [], onConnect, connecting = null, title = "Accounts it uses", description, empty = "This app connects to no accounts.", className }) {
|
|
77
|
+
const list = Array.isArray(connections) ? connections : [];
|
|
78
|
+
if (!list.length && empty === null) return null;
|
|
79
|
+
return (
|
|
80
|
+
<section aria-label={title ?? "Accounts"} className={cx("@container grid min-w-0 overflow-hidden rounded-[var(--radius)] border border-border bg-card text-card-foreground", className)}>
|
|
81
|
+
{title || description ? (
|
|
82
|
+
<header className="grid gap-0.5 border-b border-border px-3.5 py-3">
|
|
83
|
+
{title ? (
|
|
84
|
+
<span className="flex min-w-0 items-center gap-2">
|
|
85
|
+
<Icon name="link" size={14} className="shrink-0 text-muted-foreground" />
|
|
86
|
+
<b className="truncate text-sm font-semibold">{title}</b>
|
|
87
|
+
</span>
|
|
88
|
+
) : null}
|
|
89
|
+
{description ? <span className="text-xs text-muted-foreground">{description}</span> : null}
|
|
90
|
+
</header>
|
|
91
|
+
) : null}
|
|
92
|
+
{list.length ? (
|
|
93
|
+
<ul className="m-0 grid list-none divide-y divide-border p-0">
|
|
94
|
+
{list.map((c) => (
|
|
95
|
+
<ConnectRow key={c.key} connection={c} onConnect={onConnect} connecting={connecting === c.key} />
|
|
96
|
+
))}
|
|
97
|
+
</ul>
|
|
98
|
+
) : (
|
|
99
|
+
<p className="m-0 px-3.5 py-3 text-[13px] text-muted-foreground">{empty}</p>
|
|
100
|
+
)}
|
|
101
|
+
</section>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// ConnectCard with pretend accounts — the gallery's and the smoke test's
|
|
4
|
+
// surface. Not installed into apps. Connect waits for a pretend sign-in,
|
|
5
|
+
// then the row goes live. Below: the card at 320 px, a read-only card,
|
|
6
|
+
// and one with no accounts.
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { ConnectCard, ConnectRow } from "../components/blocks/connect-card";
|
|
9
|
+
|
|
10
|
+
const START = [
|
|
11
|
+
{ key: "mail", label: "Email, to build your contacts and timelines and send the follow-ups you approve", category: "mail", category_label: "Mail", required: true, connected: false, accounts: [] },
|
|
12
|
+
{ key: "calendar", label: "Calendar, to add your meetings to each timeline", category: "calendar", category_label: "Calendar", required: false, connected: true, accounts: ["nadia@pinewood.co", "team@pinewood.co"] },
|
|
13
|
+
{ key: "old_crm", label: "Your old CRM, to import from", category: "crm", category_label: "CRM", required: false, connected: false, accounts: [] },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export default function ConnectCardDemo() {
|
|
17
|
+
const [connections, setConnections] = useState(START);
|
|
18
|
+
const [connecting, setConnecting] = useState(null);
|
|
19
|
+
const connect = (key) => {
|
|
20
|
+
setConnecting(key);
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
setConnections((cs) => cs.map((c) => (c.key === key ? { ...c, connected: true, accounts: c.accounts.length ? c.accounts : ["nadia@pinewood.co"] } : c)));
|
|
23
|
+
setConnecting(null);
|
|
24
|
+
}, 1500);
|
|
25
|
+
};
|
|
26
|
+
return (
|
|
27
|
+
<div className="grid gap-6 p-4">
|
|
28
|
+
<ConnectCard
|
|
29
|
+
className="w-full max-w-[800px]"
|
|
30
|
+
title="What the CRM reads"
|
|
31
|
+
description="Your mail and calendar, to build each person's timeline. Nothing is sent without your yes."
|
|
32
|
+
connections={connections}
|
|
33
|
+
connecting={connecting}
|
|
34
|
+
onConnect={connect}
|
|
35
|
+
/>
|
|
36
|
+
<div className="flex flex-wrap items-start gap-4">
|
|
37
|
+
<ConnectCard className="w-full max-w-[320px]" connections={connections} connecting={connecting} onConnect={connect} />
|
|
38
|
+
<ConnectCard className="w-full max-w-[368px]" title="Read only" connections={connections.slice(0, 2)} />
|
|
39
|
+
<ConnectCard className="w-full max-w-[320px]" connections={[]} />
|
|
40
|
+
</div>
|
|
41
|
+
<div className="@container w-full max-w-[368px] rounded-[var(--radius)] border border-dashed border-border">
|
|
42
|
+
<p className="m-0 px-3.5 pt-3 text-[13px] text-muted-foreground">No people yet. They come from your mail once it is connected.</p>
|
|
43
|
+
<ul className="m-0 list-none p-0">
|
|
44
|
+
<ConnectRow connection={connections[0]} onConnect={connect} connecting={connecting === "mail"} />
|
|
45
|
+
</ul>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Cost
|
|
2
|
+
|
|
3
|
+
What a press will spend, said before the press. Part of the agent kit
|
|
4
|
+
(0.8.1): **every control that spends shows its price on the control.**
|
|
5
|
+
|
|
6
|
+
- `CostTag` — the price on a control: "about 700 cr", "up to 2,000 cr",
|
|
7
|
+
"1 call · 2 cr".
|
|
8
|
+
- `CostConfirm` — the confirm before a big spend: "This uses about 700
|
|
9
|
+
credits, at most 1,000. 12,400 left.", **Go ahead**, and a cheaper
|
|
10
|
+
first step as a second choice ("Try the first 10 rows").
|
|
11
|
+
- `Allowance` — the week's credits as a meter: "2,840 credits left this
|
|
12
|
+
week".
|
|
13
|
+
- `creditsWords(n)` — credits as the kit says them: to a tenth under 10
|
|
14
|
+
("1.2"), whole above, thousands marked ("2,000").
|
|
15
|
+
|
|
16
|
+
```jsx
|
|
17
|
+
import { CostTag, CostConfirm, Allowance } from "../components/blocks/cost"; // a Makersclaw app
|
|
18
|
+
import { CostTag, CostConfirm, Allowance } from "@/components/makersclaw/blocks/cost"; // a shadcn project
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Client components. They read no wallet and spend nothing: the screen
|
|
22
|
+
passes the figures and the press goes out as a callback. 1 USD is 1,000
|
|
23
|
+
credits.
|
|
24
|
+
|
|
25
|
+
## Props
|
|
26
|
+
|
|
27
|
+
### CostTag
|
|
28
|
+
|
|
29
|
+
- `credits` — the estimate. `max` — the ceiling: alone it is "up to
|
|
30
|
+
2,000 cr"; with `credits` it is said on hover.
|
|
31
|
+
- `calls` — model calls: "1 call · 2 cr".
|
|
32
|
+
- `words` — your own words instead.
|
|
33
|
+
- `loading` — the price is being asked for: a quiet "pricing…".
|
|
34
|
+
- `icon` — `false` for no mark. `className`.
|
|
35
|
+
|
|
36
|
+
Nothing is drawn when there is no price to say.
|
|
37
|
+
|
|
38
|
+
### CostConfirm
|
|
39
|
+
|
|
40
|
+
- `estimate`, `max` — credits it is likely to use, and at most.
|
|
41
|
+
- `left` — credits left (a number), or your own words.
|
|
42
|
+
- `onConfirm`, `confirmLabel` ("Go ahead"), `busy` (the press is out).
|
|
43
|
+
- `onCancel`, `cancelLabel` ("Not now").
|
|
44
|
+
- `cheaper` — `{ label, price?, onChoose }`: the smaller first step.
|
|
45
|
+
- `onTopUp` — opens the desk to add credits. When `left` is under
|
|
46
|
+
`estimate`, the confirm says there are not enough and offers this
|
|
47
|
+
instead of Go ahead.
|
|
48
|
+
- `title` — default "Before it starts". `className`.
|
|
49
|
+
|
|
50
|
+
Under about 384 px of its own width its buttons stack, full width.
|
|
51
|
+
|
|
52
|
+
### Allowance
|
|
53
|
+
|
|
54
|
+
- `used`, `of` — credits used this week and the week's cap.
|
|
55
|
+
- `words` — the line (default "4,180 of 10,000 credits this week").
|
|
56
|
+
- `title` — default "This week"; `null` for none. `className`.
|
|
57
|
+
|
|
58
|
+
## Where the figures come from (lib/hooks.js)
|
|
59
|
+
|
|
60
|
+
- A model call: `useLlmAction({ input, … }).estimate` — `{ credits,
|
|
61
|
+
credits_max }`, asked of `POST _claw/llm` with `estimate: true`
|
|
62
|
+
(priced, never sent to a model, never charged), once per input.
|
|
63
|
+
- A job: `useJobs().budget` — `{ week_cap_credits, week_used_credits }`
|
|
64
|
+
for Allowance; the job's own price is the app's to say ("about 700
|
|
65
|
+
cr"), from what its runs cost (`useRuns`' `credits`).
|
|
66
|
+
- What is left: `useJobs().credits`, as `_claw/me` gives them.
|
|
67
|
+
|
|
68
|
+
## Who may do what
|
|
69
|
+
|
|
70
|
+
The confirm is the member's own act, in their own app, with credits the
|
|
71
|
+
workspace already holds. Adding credits, a plan, a card: the desk's,
|
|
72
|
+
always. `onTopUp` opens the desk; nothing here takes money.
|
|
73
|
+
|
|
74
|
+
## Never
|
|
75
|
+
|
|
76
|
+
- Never a control that spends without its price on it.
|
|
77
|
+
- Never a payment form, a card field or a plan picker: money is the
|
|
78
|
+
desk's.
|
|
79
|
+
- Never a price made up: say what the estimate, the runs or the
|
|
80
|
+
declared price say, or say nothing.
|
|
81
|
+
|
|
82
|
+
## Example
|
|
83
|
+
|
|
84
|
+
```jsx
|
|
85
|
+
"use client";
|
|
86
|
+
import { useState } from "react";
|
|
87
|
+
import { useJobs } from "../lib/hooks";
|
|
88
|
+
import { Button } from "../components/ui";
|
|
89
|
+
import { Allowance, CostConfirm, CostTag } from "../components/blocks/cost";
|
|
90
|
+
|
|
91
|
+
export default function EnrichAll({ rows, enrich }) {
|
|
92
|
+
const { budget } = useJobs();
|
|
93
|
+
const [asking, setAsking] = useState(false);
|
|
94
|
+
const each = 1.4;
|
|
95
|
+
return (
|
|
96
|
+
<div className="grid gap-3">
|
|
97
|
+
{asking ? (
|
|
98
|
+
<CostConfirm
|
|
99
|
+
estimate={rows.length * each}
|
|
100
|
+
max={rows.length * each * 1.5}
|
|
101
|
+
left={budget ? budget.week_cap_credits - budget.week_used_credits : null}
|
|
102
|
+
onConfirm={() => enrich(rows)}
|
|
103
|
+
onCancel={() => setAsking(false)}
|
|
104
|
+
cheaper={{ label: "Try the first 10 rows", price: `about ${Math.round(10 * each)} cr`, onChoose: () => enrich(rows.slice(0, 10)) }}
|
|
105
|
+
/>
|
|
106
|
+
) : (
|
|
107
|
+
<Button icon="sparkles" onClick={() => setAsking(true)}>
|
|
108
|
+
Enrich {rows.length} rows <CostTag credits={rows.length * each} icon={false} />
|
|
109
|
+
</Button>
|
|
110
|
+
)}
|
|
111
|
+
{budget ? <Allowance used={budget.week_used_credits} of={budget.week_cap_credits} /> : null}
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cost",
|
|
3
|
+
"title": "Cost",
|
|
4
|
+
"description": "What a press will spend, said before the press. CostTag is the price on a control that spends (\"about 700 cr\", \"up to 2,000 cr\", \"1 call · 2 cr\"). CostConfirm is the confirm before a big spend: what it uses and at most, what is left, Go ahead, and an optional cheaper first step (\"Try the first 10 rows\"); with too few credits it says so and points at the desk, where credits are added. Allowance is the week's credits as a meter. Fed by useLlmAction's estimate, useJobs' budget and credits (lib/hooks.js); it reads no wallet and spends nothing itself.",
|
|
5
|
+
"useWhen": "Every control that spends credits says its price on it: Run now, Read now, Enrich 500 rows, Summarize, Generate. Put CostConfirm before a spend big enough to pause over (a whole table, a long run), and Allowance where an app shows its agent's week (beside a schedule-card, in a run's overview).",
|
|
6
|
+
"tags": ["cost", "price", "credits", "estimate", "spend", "confirm", "budget", "allowance", "meter", "billing", "kit"],
|
|
7
|
+
"exports": ["CostTag", "CostConfirm", "Allowance", "creditsWords"],
|
|
8
|
+
"files": ["index.js", "cost.jsx"],
|
|
9
|
+
"requires": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// What a press will spend, said before the press: the price on a control
|
|
4
|
+
// (CostTag), the confirm before a big spend with a cheaper second choice
|
|
5
|
+
// (CostConfirm), and the week's allowance (Allowance). Props in,
|
|
6
|
+
// callbacks out; the block reads no wallet and spends nothing itself.
|
|
7
|
+
// Tokens only. Money stays on the desk: topping up opens it, never a
|
|
8
|
+
// form here. Its own width decides its layout (@container).
|
|
9
|
+
|
|
10
|
+
import { Button, Icon, cx } from "../../ui";
|
|
11
|
+
|
|
12
|
+
/** Credits as the kit says them: to a tenth under 10 ("1.2"), whole above,
|
|
13
|
+
* thousands marked the same on the server and in the browser ("2,000"). */
|
|
14
|
+
export function creditsWords(n) {
|
|
15
|
+
if (typeof n !== "number" || !Number.isFinite(n)) return null;
|
|
16
|
+
const v = n < 10 ? Math.round(n * 10) / 10 : Math.round(n);
|
|
17
|
+
return v.toLocaleString("en-US", { maximumFractionDigits: 1 });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** The price words: "about 700 cr", "up to 2,000 cr", "1 call · 2 cr". */
|
|
21
|
+
function tagWords({ credits, max, calls, words }) {
|
|
22
|
+
if (words) return words;
|
|
23
|
+
const c = creditsWords(credits);
|
|
24
|
+
const m = creditsWords(max);
|
|
25
|
+
if (typeof calls === "number" && calls > 0) {
|
|
26
|
+
const n = `${calls} ${calls === 1 ? "call" : "calls"}`;
|
|
27
|
+
return c ? `${n} · ${c} cr` : m ? `${n} · up to ${m} cr` : n;
|
|
28
|
+
}
|
|
29
|
+
if (c) return `about ${c} cr`;
|
|
30
|
+
if (m) return `up to ${m} cr`;
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The price on a control that spends.
|
|
36
|
+
*
|
|
37
|
+
* credits the estimate ("about 700 cr")
|
|
38
|
+
* max the ceiling: alone, "up to 2,000 cr"; with credits, said on hover
|
|
39
|
+
* calls model calls: "1 call · 2 cr"
|
|
40
|
+
* words your own words instead ("free", "about a minute of reading")
|
|
41
|
+
* loading the price is being asked for: a quiet "pricing…"
|
|
42
|
+
* icon false for no mark (inside a Button that has its own icon)
|
|
43
|
+
*
|
|
44
|
+
* Nothing at all when there is no price to say.
|
|
45
|
+
*/
|
|
46
|
+
export function CostTag({ credits, max, calls, words, loading = false, icon = true, className }) {
|
|
47
|
+
const said = tagWords({ credits, max, calls, words });
|
|
48
|
+
if (!said && !loading) return null;
|
|
49
|
+
const ceiling = creditsWords(max);
|
|
50
|
+
return (
|
|
51
|
+
<span
|
|
52
|
+
className={cx("inline-flex min-w-0 items-center gap-1 whitespace-nowrap text-xs font-normal tabular-nums text-muted-foreground", className)}
|
|
53
|
+
title={credits != null && ceiling ? `at most ${ceiling} credits` : undefined}
|
|
54
|
+
>
|
|
55
|
+
{icon ? <Icon name="zap" size={12} className="shrink-0" /> : null}
|
|
56
|
+
<span className="truncate">{said ?? "pricing…"}</span>
|
|
57
|
+
</span>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The confirm before a big spend, in the member's own app: what it uses,
|
|
63
|
+
* at most, what is left, Go ahead or a cheaper first step.
|
|
64
|
+
*
|
|
65
|
+
* estimate credits it is likely to use (700)
|
|
66
|
+
* max at most (1,000), or null
|
|
67
|
+
* left credits left (12,400), or words ("12,400 left this week"), or null
|
|
68
|
+
* onConfirm, confirmLabel ("Go ahead"), busy (the press is out)
|
|
69
|
+
* onCancel, cancelLabel ("Not now")
|
|
70
|
+
* cheaper { label: "Try the first 10 rows", price?: "about 70 cr", onChoose }
|
|
71
|
+
* onTopUp opens the desk to add credits, when there is not enough
|
|
72
|
+
* title the head (default "Before it starts")
|
|
73
|
+
*/
|
|
74
|
+
export function CostConfirm({
|
|
75
|
+
estimate,
|
|
76
|
+
max,
|
|
77
|
+
left,
|
|
78
|
+
onConfirm,
|
|
79
|
+
confirmLabel = "Go ahead",
|
|
80
|
+
busy = false,
|
|
81
|
+
onCancel,
|
|
82
|
+
cancelLabel = "Not now",
|
|
83
|
+
cheaper,
|
|
84
|
+
onTopUp,
|
|
85
|
+
title = "Before it starts",
|
|
86
|
+
className,
|
|
87
|
+
}) {
|
|
88
|
+
const e = creditsWords(estimate);
|
|
89
|
+
const m = creditsWords(max);
|
|
90
|
+
const leftNumber = typeof left === "number" && Number.isFinite(left) ? left : null;
|
|
91
|
+
const leftWords = leftNumber != null ? `${creditsWords(leftNumber)} left.` : typeof left === "string" && left ? left : null;
|
|
92
|
+
const short = leftNumber != null && typeof estimate === "number" && leftNumber < estimate;
|
|
93
|
+
const use = e ? `This uses about ${e} credits${m && max !== estimate ? `, at most ${m}` : ""}.` : m ? `This uses at most ${m} credits.` : null;
|
|
94
|
+
return (
|
|
95
|
+
<section role="group" aria-label={title} className={cx("@container grid min-w-0 gap-3 rounded-[var(--radius)] border border-border bg-card p-3 text-[13px] text-card-foreground", className)}>
|
|
96
|
+
<div className="flex min-w-0 items-start gap-2">
|
|
97
|
+
<Icon name="zap" size={16} className="mt-0.5 shrink-0 text-muted-foreground" />
|
|
98
|
+
<div className="grid min-w-0 gap-0.5">
|
|
99
|
+
<b className="font-semibold">{title}</b>
|
|
100
|
+
<p className="m-0">
|
|
101
|
+
{use} {leftWords ? <span className={short ? "text-destructive" : "text-muted-foreground"}>{leftWords}</span> : null}
|
|
102
|
+
</p>
|
|
103
|
+
{short ? (
|
|
104
|
+
<p className="m-0 flex items-center gap-1 text-xs text-destructive">
|
|
105
|
+
<Icon name="warning" size={12} />
|
|
106
|
+
Not enough credits for this. Adding them is on the desk.
|
|
107
|
+
</p>
|
|
108
|
+
) : null}
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
<div className="flex flex-col items-stretch gap-2 @sm:flex-row @sm:flex-wrap @sm:items-center">
|
|
112
|
+
{short && onTopUp ? (
|
|
113
|
+
<Button size="sm" variant="primary" icon="external" onClick={onTopUp}>
|
|
114
|
+
Add credits on the desk
|
|
115
|
+
</Button>
|
|
116
|
+
) : (
|
|
117
|
+
<Button size="sm" variant="primary" icon="play" loading={busy} disabled={short} onClick={onConfirm}>
|
|
118
|
+
{confirmLabel}
|
|
119
|
+
</Button>
|
|
120
|
+
)}
|
|
121
|
+
{cheaper ? (
|
|
122
|
+
<Button size="sm" variant="secondary" onClick={cheaper.onChoose} disabled={busy}>
|
|
123
|
+
<span className="truncate">{cheaper.label}</span>
|
|
124
|
+
{cheaper.price ? <span className="font-normal text-muted-foreground">{cheaper.price}</span> : null}
|
|
125
|
+
</Button>
|
|
126
|
+
) : null}
|
|
127
|
+
{onCancel ? (
|
|
128
|
+
<Button size="sm" variant="quiet" onClick={onCancel} disabled={busy}>
|
|
129
|
+
{cancelLabel}
|
|
130
|
+
</Button>
|
|
131
|
+
) : null}
|
|
132
|
+
</div>
|
|
133
|
+
</section>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The week's allowance as a meter.
|
|
139
|
+
*
|
|
140
|
+
* used, of credits used and the cap (4,180 of 10,000)
|
|
141
|
+
* words the line ("2,840 credits left this week"); default "<used> of <of> credits this week"
|
|
142
|
+
* title the label over it (default "This week"); null for none
|
|
143
|
+
*/
|
|
144
|
+
export function Allowance({ used, of, words, title = "This week", className }) {
|
|
145
|
+
const pct = typeof used === "number" && of > 0 ? Math.max(0, Math.min(1, used / of)) : null;
|
|
146
|
+
const full = pct != null && pct >= 1;
|
|
147
|
+
const said = words ?? (pct != null ? `${creditsWords(used)} of ${creditsWords(of)} credits this week` : null);
|
|
148
|
+
return (
|
|
149
|
+
<div className={cx("grid min-w-0 gap-1 text-xs", className)}>
|
|
150
|
+
{title || said ? (
|
|
151
|
+
<div className="flex min-w-0 flex-wrap items-baseline justify-between gap-x-3">
|
|
152
|
+
{title ? <span className="font-medium text-foreground">{title}</span> : null}
|
|
153
|
+
{said ? (
|
|
154
|
+
<span className={cx("inline-flex min-w-0 items-center gap-1 tabular-nums", full ? "text-destructive" : "text-muted-foreground")}>
|
|
155
|
+
{full ? <Icon name="warning" size={12} className="shrink-0" /> : null}
|
|
156
|
+
<span className="truncate">{said}</span>
|
|
157
|
+
</span>
|
|
158
|
+
) : null}
|
|
159
|
+
</div>
|
|
160
|
+
) : null}
|
|
161
|
+
{pct != null ? (
|
|
162
|
+
<span
|
|
163
|
+
role="meter"
|
|
164
|
+
aria-label={title ?? "Credits this week"}
|
|
165
|
+
aria-valuemin={0}
|
|
166
|
+
aria-valuemax={of}
|
|
167
|
+
aria-valuenow={Math.min(used, of)}
|
|
168
|
+
aria-valuetext={said ?? undefined}
|
|
169
|
+
className="block h-1.5 overflow-hidden rounded-sm bg-border"
|
|
170
|
+
>
|
|
171
|
+
<span className={cx("block h-full", full ? "bg-destructive" : "bg-muted-foreground")} style={{ width: `${pct * 100}%` }} />
|
|
172
|
+
</span>
|
|
173
|
+
) : null}
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// CostTag, CostConfirm and Allowance with pretend figures — the
|
|
4
|
+
// gallery's and the smoke test's surface. Not installed into apps. Prices
|
|
5
|
+
// on buttons, a confirm with a cheaper first step, a confirm with too few
|
|
6
|
+
// credits, and the week's allowance empty, half spent and spent; at 320
|
|
7
|
+
// and 368 px so the layout by its own width shows.
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { Button } from "../components/ui";
|
|
10
|
+
import { Allowance, CostConfirm, CostTag } from "../components/blocks/cost";
|
|
11
|
+
|
|
12
|
+
export default function CostDemo() {
|
|
13
|
+
const [asking, setAsking] = useState(true);
|
|
14
|
+
const [busy, setBusy] = useState(false);
|
|
15
|
+
const go = () => {
|
|
16
|
+
setBusy(true);
|
|
17
|
+
setTimeout(() => {
|
|
18
|
+
setBusy(false);
|
|
19
|
+
setAsking(false);
|
|
20
|
+
}, 900);
|
|
21
|
+
};
|
|
22
|
+
return (
|
|
23
|
+
<div className="grid gap-6 p-4">
|
|
24
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
25
|
+
<Button size="sm" icon="play">
|
|
26
|
+
Read now <CostTag credits={700} max={1000} icon={false} />
|
|
27
|
+
</Button>
|
|
28
|
+
<Button size="sm" icon="sparkles">
|
|
29
|
+
Shorter <CostTag calls={1} credits={1.2} icon={false} />
|
|
30
|
+
</Button>
|
|
31
|
+
<Button size="sm" icon="sparkles">
|
|
32
|
+
Enrich 500 rows <CostTag max={2000} icon={false} />
|
|
33
|
+
</Button>
|
|
34
|
+
<Button size="sm" icon="sparkles">
|
|
35
|
+
Explain this score <CostTag loading icon={false} />
|
|
36
|
+
</Button>
|
|
37
|
+
<CostTag credits={0.4} />
|
|
38
|
+
<CostTag words="free" />
|
|
39
|
+
</div>
|
|
40
|
+
<div className="flex flex-wrap items-start gap-4">
|
|
41
|
+
{asking ? (
|
|
42
|
+
<CostConfirm
|
|
43
|
+
className="w-full max-w-[368px]"
|
|
44
|
+
estimate={700}
|
|
45
|
+
max={1000}
|
|
46
|
+
left={12400}
|
|
47
|
+
busy={busy}
|
|
48
|
+
onConfirm={go}
|
|
49
|
+
onCancel={() => setAsking(false)}
|
|
50
|
+
cheaper={{ label: "Try the first 10 rows", price: "about 14 cr", onChoose: go }}
|
|
51
|
+
/>
|
|
52
|
+
) : (
|
|
53
|
+
<Button size="sm" onClick={() => setAsking(true)}>
|
|
54
|
+
Enrich 500 rows <CostTag credits={700} icon={false} />
|
|
55
|
+
</Button>
|
|
56
|
+
)}
|
|
57
|
+
<CostConfirm className="w-full max-w-[320px]" title="Not enough credits" estimate={700} max={1000} left={400} onTopUp={() => {}} onCancel={() => {}} />
|
|
58
|
+
</div>
|
|
59
|
+
<div className="grid w-full max-w-[368px] gap-4">
|
|
60
|
+
<Allowance used={0} of={10000} words="10,000 credits left this week" />
|
|
61
|
+
<Allowance used={7160} of={10000} words="2,840 credits left this week" />
|
|
62
|
+
<Allowance used={10000} of={10000} words="All 10,000 spent · back Monday" />
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# DataPicker
|
|
2
|
+
|
|
3
|
+
Mapping data from earlier steps into a field of an automation. A step reads
|
|
4
|
+
what an earlier step made with `{{ steps.read_mail.output.messages }}`; the
|
|
5
|
+
data picker is how a person writes that without knowing the syntax.
|
|
6
|
+
|
|
7
|
+
- `DataPicker` — the menu. **This run** (when it started, the clock, the
|
|
8
|
+
run's id); **This item** (inside a for-each: the item and its place in
|
|
9
|
+
the list); **Your questions** (what a manual run asks first); **Earlier
|
|
10
|
+
steps** (every step that runs before this one, nearest first). Where a
|
|
11
|
+
real run left a sample of a step's output, the step opens to the fields
|
|
12
|
+
inside it, each with a taste of its value ("ana@x.com", "12 items").
|
|
13
|
+
- `DataButton` — the **{ }** button and the menu in a popover.
|
|
14
|
+
- `DataInput` — a labelled text field (one line, or several with
|
|
15
|
+
`multiline`) with the button beside it. A press inserts the reference
|
|
16
|
+
where the cursor was.
|
|
17
|
+
- `DataPairs` — a list of name and value rows (a step's `input`, a Set's
|
|
18
|
+
`values`), each value with its own button. A value that reads as a
|
|
19
|
+
number, true, false, null, a list or an object is kept as that; anything
|
|
20
|
+
else is text, and `{{ … }}` is a reference the platform reads later.
|
|
21
|
+
|
|
22
|
+
```jsx
|
|
23
|
+
import { DataInput, DataPairs } from "../components/blocks/data-picker"; // a Makersclaw app
|
|
24
|
+
import { DataInput, DataPairs } from "@/components/makersclaw/blocks/data-picker"; // a shadcn project
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`makersclaw add data-picker` lays `automation-model` with it
|
|
28
|
+
(`availableBefore` says what a step may read). Client components. The
|
|
29
|
+
platform checks every reference when the automation is saved; a reference
|
|
30
|
+
to a field no earlier step makes is refused with the step and the field
|
|
31
|
+
named.
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
### DataInput
|
|
36
|
+
|
|
37
|
+
- `label`, `value`, `onChange(text)`, `help`, `placeholder`, `mono`,
|
|
38
|
+
`multiline`, `rows`, `disabled`.
|
|
39
|
+
- `available` — automation-model's `availableBefore(def, stepId,
|
|
40
|
+
stepTitle)`: `{ steps: [{ id, kind, label }], inLoop }`, and optionally
|
|
41
|
+
`inputs: [{ name, label }]`. Leave it out and the field is plain text.
|
|
42
|
+
- `samples` — `{ [stepId]: a real output }`, from a run, so the menu can
|
|
43
|
+
show fields and values; or null.
|
|
44
|
+
|
|
45
|
+
### DataPairs
|
|
46
|
+
|
|
47
|
+
- `label`, `value` (`{ name: value }`), `onChange(next)`, `help`,
|
|
48
|
+
`keyLabel` ("Name"), `addLabel` ("Add a field"), `disabled`, `available`,
|
|
49
|
+
`samples`.
|
|
50
|
+
|
|
51
|
+
### DataPicker / DataButton
|
|
52
|
+
|
|
53
|
+
- `available`, `samples`, `onPick(text)`; `DataButton` also `disabled`.
|
|
54
|
+
|
|
55
|
+
### Helpers
|
|
56
|
+
|
|
57
|
+
`menuGroups(available, samples)`, `fieldsOf(sample, base)` and
|
|
58
|
+
`preview(value)`: the menu's data as plain objects.
|
|
59
|
+
|
|
60
|
+
## Never
|
|
61
|
+
|
|
62
|
+
- Never put a secret in a value: an account is chosen by kind, and the
|
|
63
|
+
platform resolves the token when the step runs.
|
|
64
|
+
- Never rename a step to change a reference: a step's id is what a run's
|
|
65
|
+
rows and an app update match steps by.
|
|
66
|
+
|
|
67
|
+
## Example
|
|
68
|
+
|
|
69
|
+
```jsx
|
|
70
|
+
"use client";
|
|
71
|
+
import { useState } from "react";
|
|
72
|
+
import { DataInput } from "../components/blocks/data-picker";
|
|
73
|
+
|
|
74
|
+
const available = { steps: [{ id: "mail", kind: "tool", label: "Read the mail" }], inLoop: false };
|
|
75
|
+
const samples = { mail: { messages: [{ from: "ana@x.com", subject: "Quote" }], count: 1 } };
|
|
76
|
+
|
|
77
|
+
export default function Note() {
|
|
78
|
+
const [message, setMessage] = useState("Read {{ steps.mail.output.count }} emails.");
|
|
79
|
+
return <DataInput label="Message" value={message} onChange={setMessage} multiline rows={3} available={available} samples={samples} />;
|
|
80
|
+
}
|
|
81
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "data-picker",
|
|
3
|
+
"title": "DataPicker",
|
|
4
|
+
"description": "Mapping data from earlier steps into a field. DataPicker is the menu (this run, this item inside a for-each, the questions a manual run asks, and every earlier step's output, with the fields inside it and a taste of their values where a real run left a sample); DataButton is the { } button that opens it; DataInput is a labelled text field (one line or several) with the menu beside it; DataPairs is a list of name and value rows with a menu on each value. A press inserts {{ steps.mail.output.messages }} where the cursor was.",
|
|
5
|
+
"useWhen": "A form edits a step's input and the value may come from an earlier step: the step-settings block does this for you. Use it on its own for a field of your own that takes `{{ … }}` references.",
|
|
6
|
+
"tags": [
|
|
7
|
+
"automation",
|
|
8
|
+
"workflow",
|
|
9
|
+
"data",
|
|
10
|
+
"mapping",
|
|
11
|
+
"expression",
|
|
12
|
+
"variable",
|
|
13
|
+
"reference",
|
|
14
|
+
"picker",
|
|
15
|
+
"insert",
|
|
16
|
+
"fields",
|
|
17
|
+
"step input",
|
|
18
|
+
"n8n",
|
|
19
|
+
"make"
|
|
20
|
+
],
|
|
21
|
+
"exports": [
|
|
22
|
+
"DataButton",
|
|
23
|
+
"DataInput",
|
|
24
|
+
"DataPairs",
|
|
25
|
+
"DataPicker",
|
|
26
|
+
"fieldsOf",
|
|
27
|
+
"menuGroups",
|
|
28
|
+
"preview"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
"index.js",
|
|
32
|
+
"data-picker.jsx",
|
|
33
|
+
"fields.js"
|
|
34
|
+
],
|
|
35
|
+
"requires": [
|
|
36
|
+
"automation-model"
|
|
37
|
+
]
|
|
38
|
+
}
|