@dowel-ui/react 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -7
- package/dist/components/ai-agent-plan/ai-agent-plan.d.ts +50 -0
- package/dist/components/ai-agent-plan/ai-agent-plan.d.ts.map +1 -0
- package/dist/components/ai-agent-plan/ai-agent-plan.js +156 -0
- package/dist/components/ai-agent-plan/ai-agent-plan.js.map +1 -0
- package/dist/components/ai-agent-plan/index.d.ts +2 -0
- package/dist/components/ai-agent-plan/index.js +2 -0
- package/dist/components/ai-agent-plan/meta.js +17 -0
- package/dist/components/ai-agent-plan/meta.js.map +1 -0
- package/dist/components/ai-agent-status/ai-agent-status.d.ts +1 -1
- package/dist/components/ai-approval-request/ai-approval-request.d.ts +67 -0
- package/dist/components/ai-approval-request/ai-approval-request.d.ts.map +1 -0
- package/dist/components/ai-approval-request/ai-approval-request.js +218 -0
- package/dist/components/ai-approval-request/ai-approval-request.js.map +1 -0
- package/dist/components/ai-approval-request/index.d.ts +2 -0
- package/dist/components/ai-approval-request/index.js +2 -0
- package/dist/components/ai-approval-request/meta.js +17 -0
- package/dist/components/ai-approval-request/meta.js.map +1 -0
- package/dist/components/ai-disclosure/ai-disclosure.d.ts +92 -0
- package/dist/components/ai-disclosure/ai-disclosure.d.ts.map +1 -0
- package/dist/components/ai-disclosure/ai-disclosure.js +122 -0
- package/dist/components/ai-disclosure/ai-disclosure.js.map +1 -0
- package/dist/components/ai-disclosure/index.d.ts +2 -0
- package/dist/components/ai-disclosure/index.js +2 -0
- package/dist/components/ai-disclosure/meta.js +17 -0
- package/dist/components/ai-disclosure/meta.js.map +1 -0
- package/dist/components/ai-response/ai-response.d.ts.map +1 -1
- package/dist/components/ai-response/ai-response.js +1 -0
- package/dist/components/ai-response/ai-response.js.map +1 -1
- package/dist/components/ai-structured-output/ai-structured-output.d.ts.map +1 -1
- package/dist/components/ai-structured-output/ai-structured-output.js +13 -2
- package/dist/components/ai-structured-output/ai-structured-output.js.map +1 -1
- package/dist/components/ai-tool/ai-tool.d.ts +1 -1
- package/dist/components/alert/alert.d.ts +1 -1
- package/dist/components/avatar/avatar.d.ts +1 -1
- package/dist/components/badge/badge.d.ts +1 -1
- package/dist/components/button/button.d.ts +1 -1
- package/dist/components/date-picker/date-picker.js +1 -1
- package/dist/components/diff-viewer/diff-model.d.ts +69 -0
- package/dist/components/diff-viewer/diff-model.d.ts.map +1 -0
- package/dist/components/diff-viewer/diff-model.js +180 -0
- package/dist/components/diff-viewer/diff-model.js.map +1 -0
- package/dist/components/diff-viewer/diff-viewer.d.ts +42 -0
- package/dist/components/diff-viewer/diff-viewer.d.ts.map +1 -0
- package/dist/components/diff-viewer/diff-viewer.js +212 -0
- package/dist/components/diff-viewer/diff-viewer.js.map +1 -0
- package/dist/components/diff-viewer/index.d.ts +3 -0
- package/dist/components/diff-viewer/index.js +3 -0
- package/dist/components/diff-viewer/meta.js +17 -0
- package/dist/components/diff-viewer/meta.js.map +1 -0
- package/dist/components/file-upload/file-upload.d.ts +46 -0
- package/dist/components/file-upload/file-upload.d.ts.map +1 -0
- package/dist/components/file-upload/file-upload.js +204 -0
- package/dist/components/file-upload/file-upload.js.map +1 -0
- package/dist/components/file-upload/index.d.ts +3 -0
- package/dist/components/file-upload/index.js +3 -0
- package/dist/components/file-upload/meta.js +17 -0
- package/dist/components/file-upload/meta.js.map +1 -0
- package/dist/components/file-upload/upload-queue.d.ts +87 -0
- package/dist/components/file-upload/upload-queue.d.ts.map +1 -0
- package/dist/components/file-upload/upload-queue.js +249 -0
- package/dist/components/file-upload/upload-queue.js.map +1 -0
- package/dist/components/log-viewer/index.d.ts +3 -0
- package/dist/components/log-viewer/index.js +3 -0
- package/dist/components/log-viewer/log-stream.d.ts +68 -0
- package/dist/components/log-viewer/log-stream.d.ts.map +1 -0
- package/dist/components/log-viewer/log-stream.js +120 -0
- package/dist/components/log-viewer/log-stream.js.map +1 -0
- package/dist/components/log-viewer/log-viewer.d.ts +51 -0
- package/dist/components/log-viewer/log-viewer.d.ts.map +1 -0
- package/dist/components/log-viewer/log-viewer.js +284 -0
- package/dist/components/log-viewer/log-viewer.js.map +1 -0
- package/dist/components/log-viewer/meta.js +17 -0
- package/dist/components/log-viewer/meta.js.map +1 -0
- package/dist/components/progress/progress.d.ts +1 -1
- package/dist/components/progress/progress.js +1 -0
- package/dist/components/progress/progress.js.map +1 -1
- package/dist/components/spinner/spinner.d.ts +1 -1
- package/dist/components/spinner/spinner.js +1 -0
- package/dist/components/spinner/spinner.js.map +1 -1
- package/dist/components/tags-input/index.d.ts +2 -0
- package/dist/components/tags-input/index.js +2 -0
- package/dist/components/tags-input/meta.js +17 -0
- package/dist/components/tags-input/meta.js.map +1 -0
- package/dist/components/tags-input/tags-input.d.ts +47 -0
- package/dist/components/tags-input/tags-input.d.ts.map +1 -0
- package/dist/components/tags-input/tags-input.js +182 -0
- package/dist/components/tags-input/tags-input.js.map +1 -0
- package/dist/components/time-range-picker/index.d.ts +3 -0
- package/dist/components/time-range-picker/index.js +3 -0
- package/dist/components/time-range-picker/meta.js +22 -0
- package/dist/components/time-range-picker/meta.js.map +1 -0
- package/dist/components/time-range-picker/time-expression.d.ts +88 -0
- package/dist/components/time-range-picker/time-expression.d.ts.map +1 -0
- package/dist/components/time-range-picker/time-expression.js +335 -0
- package/dist/components/time-range-picker/time-expression.js.map +1 -0
- package/dist/components/time-range-picker/time-range-picker.d.ts +65 -0
- package/dist/components/time-range-picker/time-range-picker.d.ts.map +1 -0
- package/dist/components/time-range-picker/time-range-picker.js +377 -0
- package/dist/components/time-range-picker/time-range-picker.js.map +1 -0
- package/dist/components/toast/toast.d.ts +1 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +14 -2
- package/dist/registry/components.d.ts.map +1 -1
- package/dist/registry/components.js +66 -50
- package/dist/registry/components.js.map +1 -1
- package/package.json +6 -4
- package/src/components/ai-agent-plan/ai-agent-plan.tsx +0 -0
- package/src/components/ai-agent-plan/index.ts +10 -0
- package/src/components/ai-agent-plan/meta.ts +19 -0
- package/src/components/ai-approval-request/ai-approval-request.tsx +368 -0
- package/src/components/ai-approval-request/index.ts +7 -0
- package/src/components/ai-approval-request/meta.ts +21 -0
- package/src/components/ai-disclosure/ai-disclosure.tsx +244 -0
- package/src/components/ai-disclosure/index.ts +9 -0
- package/src/components/ai-disclosure/meta.ts +23 -0
- package/src/components/ai-response/ai-response.tsx +1 -0
- package/src/components/ai-structured-output/ai-structured-output.tsx +25 -1
- package/src/components/diff-viewer/diff-model.ts +256 -0
- package/src/components/diff-viewer/diff-viewer.tsx +339 -0
- package/src/components/diff-viewer/index.ts +17 -0
- package/src/components/diff-viewer/meta.ts +20 -0
- package/src/components/file-upload/file-upload.tsx +322 -0
- package/src/components/file-upload/index.ts +20 -0
- package/src/components/file-upload/meta.ts +21 -0
- package/src/components/file-upload/upload-queue.ts +337 -0
- package/src/components/log-viewer/index.ts +21 -0
- package/src/components/log-viewer/log-stream.ts +176 -0
- package/src/components/log-viewer/log-viewer.tsx +424 -0
- package/src/components/log-viewer/meta.ts +21 -0
- package/src/components/progress/progress.tsx +3 -0
- package/src/components/spinner/spinner.tsx +5 -0
- package/src/components/tags-input/index.ts +1 -0
- package/src/components/tags-input/meta.ts +23 -0
- package/src/components/tags-input/tags-input.tsx +300 -0
- package/src/components/time-range-picker/index.ts +25 -0
- package/src/components/time-range-picker/meta.ts +22 -0
- package/src/components/time-range-picker/time-expression.ts +491 -0
- package/src/components/time-range-picker/time-range-picker.tsx +522 -0
- package/src/index.ts +8 -0
- package/src/registry/components.ts +16 -0
|
@@ -2,55 +2,63 @@ import { COMPONENT_CATEGORIES, COMPONENT_STATUSES } from "./schema.js";
|
|
|
2
2
|
import { meta } from "../components/accordion/meta.js";
|
|
3
3
|
import { meta as meta$1 } from "../components/activity-feed/meta.js";
|
|
4
4
|
import { meta as meta$2 } from "../components/ai-action-ledger/meta.js";
|
|
5
|
-
import { meta as meta$3 } from "../components/ai-agent-
|
|
6
|
-
import { meta as meta$4 } from "../components/ai-
|
|
7
|
-
import { meta as meta$5 } from "../components/ai-
|
|
8
|
-
import { meta as meta$6 } from "../components/ai-
|
|
9
|
-
import { meta as meta$7 } from "../components/ai-
|
|
10
|
-
import { meta as meta$8 } from "../components/ai-
|
|
11
|
-
import { meta as meta$9 } from "../components/ai-
|
|
12
|
-
import { meta as meta$10 } from "../components/ai-
|
|
13
|
-
import { meta as meta$11 } from "../components/ai-
|
|
14
|
-
import { meta as meta$12 } from "../components/ai-
|
|
15
|
-
import { meta as meta$13 } from "../components/ai-
|
|
16
|
-
import { meta as meta$14 } from "../components/ai-
|
|
17
|
-
import { meta as meta$15 } from "../components/
|
|
18
|
-
import { meta as meta$16 } from "../components/
|
|
19
|
-
import { meta as meta$17 } from "../components/
|
|
20
|
-
import { meta as meta$18 } from "../components/
|
|
21
|
-
import { meta as meta$19 } from "../components/
|
|
22
|
-
import { meta as meta$20 } from "../components/
|
|
23
|
-
import { meta as meta$21 } from "../components/
|
|
24
|
-
import { meta as meta$22 } from "../components/
|
|
25
|
-
import { meta as meta$23 } from "../components/
|
|
26
|
-
import { meta as meta$24 } from "../components/
|
|
27
|
-
import { meta as meta$25 } from "../components/
|
|
28
|
-
import { meta as meta$26 } from "../components/
|
|
29
|
-
import { meta as meta$27 } from "../components/
|
|
30
|
-
import { meta as meta$28 } from "../components/
|
|
31
|
-
import { meta as meta$29 } from "../components/
|
|
32
|
-
import { meta as meta$30 } from "../components/
|
|
33
|
-
import { meta as meta$31 } from "../components/
|
|
34
|
-
import { meta as meta$32 } from "../components/
|
|
35
|
-
import { meta as meta$33 } from "../components/
|
|
36
|
-
import { meta as meta$34 } from "../components/
|
|
37
|
-
import { meta as meta$35 } from "../components/
|
|
38
|
-
import { meta as meta$36 } from "../components/
|
|
39
|
-
import { meta as meta$37 } from "../components/
|
|
40
|
-
import { meta as meta$38 } from "../components/
|
|
41
|
-
import { meta as meta$39 } from "../components/
|
|
42
|
-
import { meta as meta$40 } from "../components/
|
|
43
|
-
import { meta as meta$41 } from "../components/
|
|
44
|
-
import { meta as meta$42 } from "../components/
|
|
45
|
-
import { meta as meta$43 } from "../components/
|
|
46
|
-
import { meta as meta$44 } from "../components/
|
|
47
|
-
import { meta as meta$45 } from "../components/
|
|
48
|
-
import { meta as meta$46 } from "../components/
|
|
49
|
-
import { meta as meta$47 } from "../components/
|
|
50
|
-
import { meta as meta$48 } from "../components/
|
|
51
|
-
import { meta as meta$49 } from "../components/
|
|
52
|
-
import { meta as meta$50 } from "../components/
|
|
53
|
-
import { meta as meta$51 } from "../components/
|
|
5
|
+
import { meta as meta$3 } from "../components/ai-agent-plan/meta.js";
|
|
6
|
+
import { meta as meta$4 } from "../components/ai-agent-status/meta.js";
|
|
7
|
+
import { meta as meta$5 } from "../components/ai-approval-request/meta.js";
|
|
8
|
+
import { meta as meta$6 } from "../components/ai-conversation/meta.js";
|
|
9
|
+
import { meta as meta$7 } from "../components/ai-disclosure/meta.js";
|
|
10
|
+
import { meta as meta$8 } from "../components/ai-inline-completion/meta.js";
|
|
11
|
+
import { meta as meta$9 } from "../components/ai-message/meta.js";
|
|
12
|
+
import { meta as meta$10 } from "../components/ai-model-selector/meta.js";
|
|
13
|
+
import { meta as meta$11 } from "../components/ai-prompt-input/meta.js";
|
|
14
|
+
import { meta as meta$12 } from "../components/ai-reasoning/meta.js";
|
|
15
|
+
import { meta as meta$13 } from "../components/ai-response/meta.js";
|
|
16
|
+
import { meta as meta$14 } from "../components/ai-sources/meta.js";
|
|
17
|
+
import { meta as meta$15 } from "../components/ai-structured-output/meta.js";
|
|
18
|
+
import { meta as meta$16 } from "../components/ai-token-usage/meta.js";
|
|
19
|
+
import { meta as meta$17 } from "../components/ai-tool/meta.js";
|
|
20
|
+
import { meta as meta$18 } from "../components/alert/meta.js";
|
|
21
|
+
import { meta as meta$19 } from "../components/avatar/meta.js";
|
|
22
|
+
import { meta as meta$20 } from "../components/badge/meta.js";
|
|
23
|
+
import { meta as meta$21 } from "../components/button/meta.js";
|
|
24
|
+
import { meta as meta$22 } from "../components/calendar/meta.js";
|
|
25
|
+
import { meta as meta$23 } from "../components/card/meta.js";
|
|
26
|
+
import { meta as meta$24 } from "../components/checkbox/meta.js";
|
|
27
|
+
import { meta as meta$25 } from "../components/code-block/meta.js";
|
|
28
|
+
import { meta as meta$26 } from "../components/combobox/meta.js";
|
|
29
|
+
import { meta as meta$27 } from "../components/command/meta.js";
|
|
30
|
+
import { meta as meta$28 } from "../components/data-table/meta.js";
|
|
31
|
+
import { meta as meta$29 } from "../components/date-picker/meta.js";
|
|
32
|
+
import { meta as meta$30 } from "../components/dialog/meta.js";
|
|
33
|
+
import { meta as meta$31 } from "../components/diff-viewer/meta.js";
|
|
34
|
+
import { meta as meta$32 } from "../components/drawer/meta.js";
|
|
35
|
+
import { meta as meta$33 } from "../components/dropdown-menu/meta.js";
|
|
36
|
+
import { meta as meta$34 } from "../components/empty-state/meta.js";
|
|
37
|
+
import { meta as meta$35 } from "../components/file-upload/meta.js";
|
|
38
|
+
import { meta as meta$36 } from "../components/form/meta.js";
|
|
39
|
+
import { meta as meta$37 } from "../components/input/meta.js";
|
|
40
|
+
import { meta as meta$38 } from "../components/label/meta.js";
|
|
41
|
+
import { meta as meta$39 } from "../components/log-viewer/meta.js";
|
|
42
|
+
import { meta as meta$40 } from "../components/meter/meta.js";
|
|
43
|
+
import { meta as meta$41 } from "../components/metric-delta/meta.js";
|
|
44
|
+
import { meta as meta$42 } from "../components/pagination/meta.js";
|
|
45
|
+
import { meta as meta$43 } from "../components/popover/meta.js";
|
|
46
|
+
import { meta as meta$44 } from "../components/progress/meta.js";
|
|
47
|
+
import { meta as meta$45 } from "../components/radio-group/meta.js";
|
|
48
|
+
import { meta as meta$46 } from "../components/record-diff/meta.js";
|
|
49
|
+
import { meta as meta$47 } from "../components/select/meta.js";
|
|
50
|
+
import { meta as meta$48 } from "../components/separator/meta.js";
|
|
51
|
+
import { meta as meta$49 } from "../components/sheet/meta.js";
|
|
52
|
+
import { meta as meta$50 } from "../components/skeleton/meta.js";
|
|
53
|
+
import { meta as meta$51 } from "../components/slider/meta.js";
|
|
54
|
+
import { meta as meta$52 } from "../components/spinner/meta.js";
|
|
55
|
+
import { meta as meta$53 } from "../components/switch/meta.js";
|
|
56
|
+
import { meta as meta$54 } from "../components/table/meta.js";
|
|
57
|
+
import { meta as meta$55 } from "../components/tabs/meta.js";
|
|
58
|
+
import { meta as meta$56 } from "../components/tags-input/meta.js";
|
|
59
|
+
import { meta as meta$57 } from "../components/time-range-picker/meta.js";
|
|
60
|
+
import { meta as meta$58 } from "../components/toast/meta.js";
|
|
61
|
+
import { meta as meta$59 } from "../components/tooltip/meta.js";
|
|
54
62
|
import { blockMetas } from "./blocks.js";
|
|
55
63
|
//#region src/registry/components.ts
|
|
56
64
|
/**
|
|
@@ -116,7 +124,15 @@ const componentMetas = [
|
|
|
116
124
|
meta$48,
|
|
117
125
|
meta$49,
|
|
118
126
|
meta$50,
|
|
119
|
-
meta$51
|
|
127
|
+
meta$51,
|
|
128
|
+
meta$52,
|
|
129
|
+
meta$53,
|
|
130
|
+
meta$54,
|
|
131
|
+
meta$55,
|
|
132
|
+
meta$56,
|
|
133
|
+
meta$57,
|
|
134
|
+
meta$58,
|
|
135
|
+
meta$59
|
|
120
136
|
];
|
|
121
137
|
//#endregion
|
|
122
138
|
export { COMPONENT_CATEGORIES, COMPONENT_STATUSES, blockMetas, componentMetas };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.js","names":["accordionMeta","activityFeedMeta","aiActionLedgerMeta","aiAgentStatusMeta","aiConversationMeta","aiInlineCompletionMeta","aiMessageMeta","aiModelSelectorMeta","aiPromptInputMeta","aiReasoningMeta","aiResponseMeta","aiSourcesMeta","aiStructuredOutputMeta","aiTokenUsageMeta","aiToolMeta","alertMeta","avatarMeta","badgeMeta","buttonMeta","calendarMeta","cardMeta","checkboxMeta","codeBlockMeta","comboboxMeta","commandMeta","dataTableMeta","datePickerMeta","dialogMeta","drawerMeta","dropdownMenuMeta","emptyStateMeta","formMeta","inputMeta","labelMeta","meterMeta","metricDeltaMeta","paginationMeta","popoverMeta","progressMeta","radioGroupMeta","recordDiffMeta","selectMeta","separatorMeta","sheetMeta","skeletonMeta","sliderMeta","spinnerMeta","switchMeta","tableMeta","tabsMeta","toastMeta","tooltipMeta"],"sources":["../../src/registry/components.ts"],"sourcesContent":["import type { ComponentMeta } from \"./schema\";\n\nimport { meta as accordionMeta } from \"@/components/accordion/meta\";\nimport { meta as activityFeedMeta } from \"@/components/activity-feed/meta\";\nimport { meta as aiActionLedgerMeta } from \"@/components/ai-action-ledger/meta\";\nimport { meta as aiAgentStatusMeta } from \"@/components/ai-agent-status/meta\";\nimport { meta as aiConversationMeta } from \"@/components/ai-conversation/meta\";\nimport { meta as aiInlineCompletionMeta } from \"@/components/ai-inline-completion/meta\";\nimport { meta as aiMessageMeta } from \"@/components/ai-message/meta\";\nimport { meta as aiModelSelectorMeta } from \"@/components/ai-model-selector/meta\";\nimport { meta as aiPromptInputMeta } from \"@/components/ai-prompt-input/meta\";\nimport { meta as aiReasoningMeta } from \"@/components/ai-reasoning/meta\";\nimport { meta as aiResponseMeta } from \"@/components/ai-response/meta\";\nimport { meta as aiSourcesMeta } from \"@/components/ai-sources/meta\";\nimport { meta as aiStructuredOutputMeta } from \"@/components/ai-structured-output/meta\";\nimport { meta as aiTokenUsageMeta } from \"@/components/ai-token-usage/meta\";\nimport { meta as aiToolMeta } from \"@/components/ai-tool/meta\";\nimport { meta as alertMeta } from \"@/components/alert/meta\";\nimport { meta as avatarMeta } from \"@/components/avatar/meta\";\nimport { meta as badgeMeta } from \"@/components/badge/meta\";\nimport { meta as buttonMeta } from \"@/components/button/meta\";\nimport { meta as calendarMeta } from \"@/components/calendar/meta\";\nimport { meta as cardMeta } from \"@/components/card/meta\";\nimport { meta as checkboxMeta } from \"@/components/checkbox/meta\";\nimport { meta as codeBlockMeta } from \"@/components/code-block/meta\";\nimport { meta as comboboxMeta } from \"@/components/combobox/meta\";\nimport { meta as commandMeta } from \"@/components/command/meta\";\nimport { meta as dataTableMeta } from \"@/components/data-table/meta\";\nimport { meta as datePickerMeta } from \"@/components/date-picker/meta\";\nimport { meta as dialogMeta } from \"@/components/dialog/meta\";\nimport { meta as drawerMeta } from \"@/components/drawer/meta\";\nimport { meta as dropdownMenuMeta } from \"@/components/dropdown-menu/meta\";\nimport { meta as emptyStateMeta } from \"@/components/empty-state/meta\";\nimport { meta as formMeta } from \"@/components/form/meta\";\nimport { meta as inputMeta } from \"@/components/input/meta\";\nimport { meta as labelMeta } from \"@/components/label/meta\";\nimport { meta as meterMeta } from \"@/components/meter/meta\";\nimport { meta as metricDeltaMeta } from \"@/components/metric-delta/meta\";\nimport { meta as paginationMeta } from \"@/components/pagination/meta\";\nimport { meta as popoverMeta } from \"@/components/popover/meta\";\nimport { meta as progressMeta } from \"@/components/progress/meta\";\nimport { meta as radioGroupMeta } from \"@/components/radio-group/meta\";\nimport { meta as recordDiffMeta } from \"@/components/record-diff/meta\";\nimport { meta as selectMeta } from \"@/components/select/meta\";\nimport { meta as separatorMeta } from \"@/components/separator/meta\";\nimport { meta as sheetMeta } from \"@/components/sheet/meta\";\nimport { meta as skeletonMeta } from \"@/components/skeleton/meta\";\nimport { meta as sliderMeta } from \"@/components/slider/meta\";\nimport { meta as spinnerMeta } from \"@/components/spinner/meta\";\nimport { meta as switchMeta } from \"@/components/switch/meta\";\nimport { meta as tableMeta } from \"@/components/table/meta\";\nimport { meta as tabsMeta } from \"@/components/tabs/meta\";\nimport { meta as toastMeta } from \"@/components/toast/meta\";\nimport { meta as tooltipMeta } from \"@/components/tooltip/meta\";\n\n/**\n * Every component in the registry.\n *\n * An explicit list rather than a glob: the registry build runs in plain Node,\n * where bundler-only globbing is unavailable, and a static list is also what\n * lets the bundle tree-shake. `meta.test.ts` fails if a component directory\n * exists that is missing from here, so it cannot silently fall out of date.\n *\n * Identifiers carry a `Meta` suffix because component names include reserved\n * words — `switch` cannot be a binding name.\n */\nexport const componentMetas: ComponentMeta[] = [\n accordionMeta,\n activityFeedMeta,\n aiActionLedgerMeta,\n aiAgentStatusMeta,\n aiConversationMeta,\n aiInlineCompletionMeta,\n aiMessageMeta,\n aiModelSelectorMeta,\n aiPromptInputMeta,\n aiReasoningMeta,\n aiResponseMeta,\n aiSourcesMeta,\n aiStructuredOutputMeta,\n aiTokenUsageMeta,\n aiToolMeta,\n alertMeta,\n avatarMeta,\n badgeMeta,\n buttonMeta,\n calendarMeta,\n cardMeta,\n checkboxMeta,\n codeBlockMeta,\n comboboxMeta,\n commandMeta,\n dataTableMeta,\n datePickerMeta,\n dialogMeta,\n drawerMeta,\n dropdownMenuMeta,\n emptyStateMeta,\n formMeta,\n inputMeta,\n labelMeta,\n meterMeta,\n metricDeltaMeta,\n paginationMeta,\n popoverMeta,\n progressMeta,\n radioGroupMeta,\n recordDiffMeta,\n selectMeta,\n separatorMeta,\n sheetMeta,\n skeletonMeta,\n sliderMeta,\n spinnerMeta,\n switchMeta,\n tableMeta,\n tabsMeta,\n toastMeta,\n tooltipMeta,\n];\n\n// This file is the `@dowel-ui/react/registry` entry point, so the block barrel is\n// re-exported here — the registry build reads both through one import.\nexport { blockMetas } from \"./blocks\";\nexport { COMPONENT_CATEGORIES, COMPONENT_STATUSES } from \"./schema\";\nexport type { ComponentCategory, ComponentMeta, ComponentStatus } from \"./schema\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"components.js","names":["accordionMeta","activityFeedMeta","aiActionLedgerMeta","aiAgentPlanMeta","aiAgentStatusMeta","aiApprovalRequestMeta","aiConversationMeta","aiDisclosureMeta","aiInlineCompletionMeta","aiMessageMeta","aiModelSelectorMeta","aiPromptInputMeta","aiReasoningMeta","aiResponseMeta","aiSourcesMeta","aiStructuredOutputMeta","aiTokenUsageMeta","aiToolMeta","alertMeta","avatarMeta","badgeMeta","buttonMeta","calendarMeta","cardMeta","checkboxMeta","codeBlockMeta","comboboxMeta","commandMeta","dataTableMeta","datePickerMeta","dialogMeta","diffViewerMeta","drawerMeta","dropdownMenuMeta","emptyStateMeta","fileUploadMeta","formMeta","inputMeta","labelMeta","logViewerMeta","meterMeta","metricDeltaMeta","paginationMeta","popoverMeta","progressMeta","radioGroupMeta","recordDiffMeta","selectMeta","separatorMeta","sheetMeta","skeletonMeta","sliderMeta","spinnerMeta","switchMeta","tableMeta","tabsMeta","tagsInputMeta","timeRangePickerMeta","toastMeta","tooltipMeta"],"sources":["../../src/registry/components.ts"],"sourcesContent":["import type { ComponentMeta } from \"./schema\";\n\nimport { meta as accordionMeta } from \"@/components/accordion/meta\";\nimport { meta as activityFeedMeta } from \"@/components/activity-feed/meta\";\nimport { meta as aiActionLedgerMeta } from \"@/components/ai-action-ledger/meta\";\nimport { meta as aiAgentPlanMeta } from \"@/components/ai-agent-plan/meta\";\nimport { meta as aiAgentStatusMeta } from \"@/components/ai-agent-status/meta\";\nimport { meta as aiApprovalRequestMeta } from \"@/components/ai-approval-request/meta\";\nimport { meta as aiConversationMeta } from \"@/components/ai-conversation/meta\";\nimport { meta as aiDisclosureMeta } from \"@/components/ai-disclosure/meta\";\nimport { meta as aiInlineCompletionMeta } from \"@/components/ai-inline-completion/meta\";\nimport { meta as aiMessageMeta } from \"@/components/ai-message/meta\";\nimport { meta as aiModelSelectorMeta } from \"@/components/ai-model-selector/meta\";\nimport { meta as aiPromptInputMeta } from \"@/components/ai-prompt-input/meta\";\nimport { meta as aiReasoningMeta } from \"@/components/ai-reasoning/meta\";\nimport { meta as aiResponseMeta } from \"@/components/ai-response/meta\";\nimport { meta as aiSourcesMeta } from \"@/components/ai-sources/meta\";\nimport { meta as aiStructuredOutputMeta } from \"@/components/ai-structured-output/meta\";\nimport { meta as aiTokenUsageMeta } from \"@/components/ai-token-usage/meta\";\nimport { meta as aiToolMeta } from \"@/components/ai-tool/meta\";\nimport { meta as alertMeta } from \"@/components/alert/meta\";\nimport { meta as avatarMeta } from \"@/components/avatar/meta\";\nimport { meta as badgeMeta } from \"@/components/badge/meta\";\nimport { meta as buttonMeta } from \"@/components/button/meta\";\nimport { meta as calendarMeta } from \"@/components/calendar/meta\";\nimport { meta as cardMeta } from \"@/components/card/meta\";\nimport { meta as checkboxMeta } from \"@/components/checkbox/meta\";\nimport { meta as codeBlockMeta } from \"@/components/code-block/meta\";\nimport { meta as comboboxMeta } from \"@/components/combobox/meta\";\nimport { meta as commandMeta } from \"@/components/command/meta\";\nimport { meta as dataTableMeta } from \"@/components/data-table/meta\";\nimport { meta as datePickerMeta } from \"@/components/date-picker/meta\";\nimport { meta as dialogMeta } from \"@/components/dialog/meta\";\nimport { meta as diffViewerMeta } from \"@/components/diff-viewer/meta\";\nimport { meta as drawerMeta } from \"@/components/drawer/meta\";\nimport { meta as dropdownMenuMeta } from \"@/components/dropdown-menu/meta\";\nimport { meta as emptyStateMeta } from \"@/components/empty-state/meta\";\nimport { meta as fileUploadMeta } from \"@/components/file-upload/meta\";\nimport { meta as formMeta } from \"@/components/form/meta\";\nimport { meta as inputMeta } from \"@/components/input/meta\";\nimport { meta as labelMeta } from \"@/components/label/meta\";\nimport { meta as logViewerMeta } from \"@/components/log-viewer/meta\";\nimport { meta as meterMeta } from \"@/components/meter/meta\";\nimport { meta as metricDeltaMeta } from \"@/components/metric-delta/meta\";\nimport { meta as paginationMeta } from \"@/components/pagination/meta\";\nimport { meta as popoverMeta } from \"@/components/popover/meta\";\nimport { meta as progressMeta } from \"@/components/progress/meta\";\nimport { meta as radioGroupMeta } from \"@/components/radio-group/meta\";\nimport { meta as recordDiffMeta } from \"@/components/record-diff/meta\";\nimport { meta as selectMeta } from \"@/components/select/meta\";\nimport { meta as separatorMeta } from \"@/components/separator/meta\";\nimport { meta as sheetMeta } from \"@/components/sheet/meta\";\nimport { meta as skeletonMeta } from \"@/components/skeleton/meta\";\nimport { meta as sliderMeta } from \"@/components/slider/meta\";\nimport { meta as spinnerMeta } from \"@/components/spinner/meta\";\nimport { meta as switchMeta } from \"@/components/switch/meta\";\nimport { meta as tableMeta } from \"@/components/table/meta\";\nimport { meta as tabsMeta } from \"@/components/tabs/meta\";\nimport { meta as tagsInputMeta } from \"@/components/tags-input/meta\";\nimport { meta as timeRangePickerMeta } from \"@/components/time-range-picker/meta\";\nimport { meta as toastMeta } from \"@/components/toast/meta\";\nimport { meta as tooltipMeta } from \"@/components/tooltip/meta\";\n\n/**\n * Every component in the registry.\n *\n * An explicit list rather than a glob: the registry build runs in plain Node,\n * where bundler-only globbing is unavailable, and a static list is also what\n * lets the bundle tree-shake. `meta.test.ts` fails if a component directory\n * exists that is missing from here, so it cannot silently fall out of date.\n *\n * Identifiers carry a `Meta` suffix because component names include reserved\n * words — `switch` cannot be a binding name.\n */\nexport const componentMetas: ComponentMeta[] = [\n accordionMeta,\n activityFeedMeta,\n aiActionLedgerMeta,\n aiAgentPlanMeta,\n aiAgentStatusMeta,\n aiApprovalRequestMeta,\n aiConversationMeta,\n aiDisclosureMeta,\n aiInlineCompletionMeta,\n aiMessageMeta,\n aiModelSelectorMeta,\n aiPromptInputMeta,\n aiReasoningMeta,\n aiResponseMeta,\n aiSourcesMeta,\n aiStructuredOutputMeta,\n aiTokenUsageMeta,\n aiToolMeta,\n alertMeta,\n avatarMeta,\n badgeMeta,\n buttonMeta,\n calendarMeta,\n cardMeta,\n checkboxMeta,\n codeBlockMeta,\n comboboxMeta,\n commandMeta,\n dataTableMeta,\n datePickerMeta,\n dialogMeta,\n diffViewerMeta,\n drawerMeta,\n dropdownMenuMeta,\n emptyStateMeta,\n fileUploadMeta,\n formMeta,\n inputMeta,\n labelMeta,\n logViewerMeta,\n meterMeta,\n metricDeltaMeta,\n paginationMeta,\n popoverMeta,\n progressMeta,\n radioGroupMeta,\n recordDiffMeta,\n selectMeta,\n separatorMeta,\n sheetMeta,\n skeletonMeta,\n sliderMeta,\n spinnerMeta,\n switchMeta,\n tableMeta,\n tabsMeta,\n tagsInputMeta,\n timeRangePickerMeta,\n toastMeta,\n tooltipMeta,\n];\n\n// This file is the `@dowel-ui/react/registry` entry point, so the block barrel is\n// re-exported here — the registry build reads both through one import.\nexport { blockMetas } from \"./blocks\";\nexport { COMPONENT_CATEGORIES, COMPONENT_STATUSES } from \"./schema\";\nexport type { ComponentCategory, ComponentMeta, ComponentStatus } from \"./schema\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0EA,MAAa,iBAAkC;CAC7CA;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;AACF"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dowel-ui/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Source-first React components for SaaS and AI products —
|
|
5
|
+
"description": "Source-first React components for SaaS and AI products — 60 accessible components you install as code you own, not as a dependency.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"react",
|
|
8
8
|
"ui",
|
|
@@ -63,8 +63,10 @@
|
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
65
|
"@tanstack/react-table": "9.2.4",
|
|
66
|
+
"@tanstack/react-virtual": "3.14.10",
|
|
66
67
|
"class-variance-authority": "0.7.1",
|
|
67
68
|
"clsx": "2.1.1",
|
|
69
|
+
"diff": "9.0.0",
|
|
68
70
|
"radix-ui": "1.6.7",
|
|
69
71
|
"react-day-picker": "10.0.1",
|
|
70
72
|
"tailwind-merge": "3.6.0"
|
|
@@ -93,8 +95,8 @@
|
|
|
93
95
|
"vite": "8.2.2",
|
|
94
96
|
"vitest": "4.1.10",
|
|
95
97
|
"zod": "4.5.4",
|
|
96
|
-
"@dowel-ui/config": "0.
|
|
97
|
-
"@dowel-ui/themes": "0.
|
|
98
|
+
"@dowel-ui/config": "0.4.0",
|
|
99
|
+
"@dowel-ui/themes": "0.4.0"
|
|
98
100
|
},
|
|
99
101
|
"scripts": {
|
|
100
102
|
"build": "tsdown",
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineMeta } from "@/registry/schema";
|
|
2
|
+
|
|
3
|
+
export const meta = defineMeta({
|
|
4
|
+
name: "ai-agent-plan",
|
|
5
|
+
title: "AI Agent Plan",
|
|
6
|
+
description: "What an agent intends to do — including when it changes its mind mid-run.",
|
|
7
|
+
category: "ai",
|
|
8
|
+
status: "stable",
|
|
9
|
+
dependencies: [],
|
|
10
|
+
registryDependencies: [],
|
|
11
|
+
files: ["ai-agent-plan.tsx"],
|
|
12
|
+
a11y:
|
|
13
|
+
"An ordered list, because a plan is a sequence and the order carries meaning an unordered " +
|
|
14
|
+
'list would discard. The running step carries aria-current="step", which marks the reader\'s ' +
|
|
15
|
+
"place without moving focus and fighting anyone reading ahead. Every status is stated in text " +
|
|
16
|
+
"as well as drawn, and the markers are aria-hidden so the status is not heard twice per step. " +
|
|
17
|
+
"The live region reports structural revisions only — announcing every status transition would " +
|
|
18
|
+
"talk over the reader continuously on a plan of any length.",
|
|
19
|
+
});
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useId, useMemo, useState, type ComponentPropsWithRef, type ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
import { disabledStyles, focusRing } from "@/lib/styles";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The gate between an agent deciding to act and it acting.
|
|
10
|
+
*
|
|
11
|
+
* Two things separate this from the confirmations that already exist.
|
|
12
|
+
*
|
|
13
|
+
* The first is that the proposed arguments are editable. Every implementation
|
|
14
|
+
* surveyed returns a boolean over a read-only payload, which forces a false
|
|
15
|
+
* choice: approve a call whose recipient is wrong, or deny it and make the
|
|
16
|
+
* model try again. "Approve this, but fix the address first" is the answer
|
|
17
|
+
* people actually want, and it is only possible if the arguments are fields.
|
|
18
|
+
* Edited values come back in the decision, and are marked as changed so an
|
|
19
|
+
* audit trail can tell the model's proposal from the human's correction.
|
|
20
|
+
*
|
|
21
|
+
* The second is that it renders while the arguments are still arriving. The
|
|
22
|
+
* common implementation returns null until the tool input is complete, which
|
|
23
|
+
* means nothing is on screen at the moment approval becomes relevant and the
|
|
24
|
+
* request appears abruptly, fully formed. Here the request is visible as it
|
|
25
|
+
* forms, with the decision held until there is something whole to decide on.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export type ApprovalScope = "once" | "always";
|
|
29
|
+
|
|
30
|
+
export type ApprovalDecision =
|
|
31
|
+
| {
|
|
32
|
+
approved: true;
|
|
33
|
+
scope: ApprovalScope;
|
|
34
|
+
arguments: Record<string, string>;
|
|
35
|
+
edited: string[];
|
|
36
|
+
}
|
|
37
|
+
| { approved: false; reason?: string };
|
|
38
|
+
|
|
39
|
+
export interface ApprovalField {
|
|
40
|
+
name: string;
|
|
41
|
+
label: string;
|
|
42
|
+
/** A textarea instead of a single line. For message bodies and prompts. */
|
|
43
|
+
multiline?: boolean;
|
|
44
|
+
/** Locked arguments are shown but not editable — an id, a resolved amount. */
|
|
45
|
+
readOnly?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ApprovalRequestProps extends Omit<
|
|
49
|
+
ComponentPropsWithRef<"section">,
|
|
50
|
+
"onSubmit" | "children"
|
|
51
|
+
> {
|
|
52
|
+
/** The tool the model wants to call, as it named it. */
|
|
53
|
+
tool: string;
|
|
54
|
+
/** What the call will do, in the reader's language rather than the API's. */
|
|
55
|
+
summary: string;
|
|
56
|
+
/** Proposed arguments. Missing keys are treated as still arriving. */
|
|
57
|
+
arguments: Record<string, string>;
|
|
58
|
+
/** Which arguments to show, in order, and which may be changed. */
|
|
59
|
+
fields: ApprovalField[];
|
|
60
|
+
onDecision: (decision: ApprovalDecision) => void;
|
|
61
|
+
/**
|
|
62
|
+
* True while the model is still producing the arguments. The request renders
|
|
63
|
+
* anyway; only the decision waits.
|
|
64
|
+
*/
|
|
65
|
+
streaming?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Said plainly above the controls when the call cannot be taken back. Not a
|
|
68
|
+
* severity colour — the sentence is the warning.
|
|
69
|
+
*/
|
|
70
|
+
irreversible?: string;
|
|
71
|
+
/** Set once decided, to render the outcome instead of the controls. */
|
|
72
|
+
decision?: ApprovalDecision;
|
|
73
|
+
children?: ReactNode;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function ApprovalRequest({
|
|
77
|
+
className,
|
|
78
|
+
tool,
|
|
79
|
+
summary,
|
|
80
|
+
arguments: proposed,
|
|
81
|
+
fields,
|
|
82
|
+
onDecision,
|
|
83
|
+
streaming = false,
|
|
84
|
+
irreversible,
|
|
85
|
+
decision,
|
|
86
|
+
children,
|
|
87
|
+
...props
|
|
88
|
+
}: ApprovalRequestProps) {
|
|
89
|
+
const headingId = useId();
|
|
90
|
+
const [edits, setEdits] = useState<Record<string, string>>({});
|
|
91
|
+
const [denying, setDenying] = useState(false);
|
|
92
|
+
const [reason, setReason] = useState("");
|
|
93
|
+
|
|
94
|
+
// The model's proposal with the human's corrections applied on top. Keeping
|
|
95
|
+
// them apart is what lets the component say which is which.
|
|
96
|
+
const values = useMemo(() => ({ ...proposed, ...edits }), [proposed, edits]);
|
|
97
|
+
|
|
98
|
+
const edited = useMemo(
|
|
99
|
+
() => Object.keys(edits).filter((name) => edits[name] !== proposed[name]),
|
|
100
|
+
[edits, proposed],
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const missing = fields.filter((field) => proposed[field.name] === undefined);
|
|
104
|
+
const settled = !streaming && missing.length === 0;
|
|
105
|
+
|
|
106
|
+
if (decision) {
|
|
107
|
+
return (
|
|
108
|
+
<section
|
|
109
|
+
data-slot="approval-request"
|
|
110
|
+
data-state={decision.approved ? "approved" : "denied"}
|
|
111
|
+
aria-labelledby={headingId}
|
|
112
|
+
className={cn(
|
|
113
|
+
"rounded-lg border p-4 text-sm",
|
|
114
|
+
decision.approved ? "border-border bg-muted/40" : "border-border bg-muted/40",
|
|
115
|
+
className,
|
|
116
|
+
)}
|
|
117
|
+
{...props}
|
|
118
|
+
>
|
|
119
|
+
<h3 id={headingId} className="text-sm font-medium">
|
|
120
|
+
{summary}
|
|
121
|
+
</h3>
|
|
122
|
+
<p data-slot="approval-outcome" className="mt-1 text-xs text-muted-foreground">
|
|
123
|
+
{decision.approved
|
|
124
|
+
? `Approved ${decision.scope === "always" ? "for every call to this tool" : "once"}` +
|
|
125
|
+
(decision.edited.length > 0
|
|
126
|
+
? `, with ${String(decision.edited.length)} argument${decision.edited.length === 1 ? "" : "s"} corrected`
|
|
127
|
+
: "")
|
|
128
|
+
: `Denied${decision.reason ? `: ${decision.reason}` : ""}`}
|
|
129
|
+
</p>
|
|
130
|
+
</section>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<section
|
|
136
|
+
data-slot="approval-request"
|
|
137
|
+
data-state={settled ? "pending" : "forming"}
|
|
138
|
+
aria-labelledby={headingId}
|
|
139
|
+
// Busy while the arguments are still arriving, so a reader is told the
|
|
140
|
+
// request is not yet whole rather than acting on half of it.
|
|
141
|
+
aria-busy={!settled}
|
|
142
|
+
className={cn("rounded-lg border border-border bg-card p-4", className)}
|
|
143
|
+
{...props}
|
|
144
|
+
>
|
|
145
|
+
<div className="flex flex-wrap items-baseline justify-between gap-2">
|
|
146
|
+
<h3 id={headingId} className="text-sm font-medium">
|
|
147
|
+
{summary}
|
|
148
|
+
</h3>
|
|
149
|
+
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-2xs text-muted-foreground">
|
|
150
|
+
{tool}
|
|
151
|
+
</code>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<dl className="mt-3 flex flex-col gap-2.5">
|
|
155
|
+
{fields.map((field) => {
|
|
156
|
+
const arrived = proposed[field.name] !== undefined;
|
|
157
|
+
const changed = edited.includes(field.name);
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<ApprovalArgument
|
|
161
|
+
key={field.name}
|
|
162
|
+
field={field}
|
|
163
|
+
value={values[field.name] ?? ""}
|
|
164
|
+
arrived={arrived}
|
|
165
|
+
changed={changed}
|
|
166
|
+
onChange={(next) => {
|
|
167
|
+
setEdits((current) => ({ ...current, [field.name]: next }));
|
|
168
|
+
}}
|
|
169
|
+
/>
|
|
170
|
+
);
|
|
171
|
+
})}
|
|
172
|
+
</dl>
|
|
173
|
+
|
|
174
|
+
{children}
|
|
175
|
+
|
|
176
|
+
{irreversible ? (
|
|
177
|
+
<p data-slot="approval-warning" className="mt-3 text-xs text-destructive">
|
|
178
|
+
{irreversible}
|
|
179
|
+
</p>
|
|
180
|
+
) : null}
|
|
181
|
+
|
|
182
|
+
{denying ? (
|
|
183
|
+
<div className="mt-3 flex flex-col gap-2">
|
|
184
|
+
<label htmlFor={`${headingId}-reason`} className="text-xs text-muted-foreground">
|
|
185
|
+
Why not? The model sees this.
|
|
186
|
+
</label>
|
|
187
|
+
<textarea
|
|
188
|
+
id={`${headingId}-reason`}
|
|
189
|
+
rows={2}
|
|
190
|
+
value={reason}
|
|
191
|
+
onChange={(event) => {
|
|
192
|
+
setReason(event.target.value);
|
|
193
|
+
}}
|
|
194
|
+
className={cn(
|
|
195
|
+
"w-full resize-none rounded-md border border-input bg-background px-2 py-1.5 text-sm",
|
|
196
|
+
focusRing,
|
|
197
|
+
)}
|
|
198
|
+
/>
|
|
199
|
+
<div className="flex flex-wrap gap-2">
|
|
200
|
+
<Action
|
|
201
|
+
variant="destructive"
|
|
202
|
+
onClick={() => {
|
|
203
|
+
onDecision({ approved: false, reason: reason.trim() || undefined });
|
|
204
|
+
}}
|
|
205
|
+
>
|
|
206
|
+
Deny
|
|
207
|
+
</Action>
|
|
208
|
+
<Action
|
|
209
|
+
onClick={() => {
|
|
210
|
+
setDenying(false);
|
|
211
|
+
}}
|
|
212
|
+
>
|
|
213
|
+
Back
|
|
214
|
+
</Action>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
) : (
|
|
218
|
+
<div className="mt-4 flex flex-wrap items-center gap-2">
|
|
219
|
+
<Action
|
|
220
|
+
variant="primary"
|
|
221
|
+
disabled={!settled}
|
|
222
|
+
onClick={() => {
|
|
223
|
+
onDecision({ approved: true, scope: "once", arguments: values, edited });
|
|
224
|
+
}}
|
|
225
|
+
>
|
|
226
|
+
{edited.length > 0 ? "Approve with changes" : "Approve once"}
|
|
227
|
+
</Action>
|
|
228
|
+
|
|
229
|
+
{/* Scope is a separate decision from approval, and blanket consent
|
|
230
|
+
should never be the easiest button to reach. */}
|
|
231
|
+
<Action
|
|
232
|
+
disabled={!settled}
|
|
233
|
+
onClick={() => {
|
|
234
|
+
onDecision({ approved: true, scope: "always", arguments: values, edited });
|
|
235
|
+
}}
|
|
236
|
+
>
|
|
237
|
+
Always allow {tool}
|
|
238
|
+
</Action>
|
|
239
|
+
|
|
240
|
+
<Action
|
|
241
|
+
onClick={() => {
|
|
242
|
+
setDenying(true);
|
|
243
|
+
}}
|
|
244
|
+
>
|
|
245
|
+
Deny…
|
|
246
|
+
</Action>
|
|
247
|
+
|
|
248
|
+
{!settled ? (
|
|
249
|
+
<span aria-live="polite" className="text-xs text-muted-foreground">
|
|
250
|
+
Waiting for the model to finish the request
|
|
251
|
+
</span>
|
|
252
|
+
) : null}
|
|
253
|
+
</div>
|
|
254
|
+
)}
|
|
255
|
+
</section>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function ApprovalArgument({
|
|
260
|
+
field,
|
|
261
|
+
value,
|
|
262
|
+
arrived,
|
|
263
|
+
changed,
|
|
264
|
+
onChange,
|
|
265
|
+
}: {
|
|
266
|
+
field: ApprovalField;
|
|
267
|
+
value: string;
|
|
268
|
+
arrived: boolean;
|
|
269
|
+
changed: boolean;
|
|
270
|
+
onChange: (value: string) => void;
|
|
271
|
+
}) {
|
|
272
|
+
const id = useId();
|
|
273
|
+
const changedId = useId();
|
|
274
|
+
const editable = !field.readOnly && arrived;
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<div
|
|
278
|
+
data-slot="approval-argument"
|
|
279
|
+
data-changed={changed || undefined}
|
|
280
|
+
className="flex flex-col gap-1"
|
|
281
|
+
>
|
|
282
|
+
<dt className="flex items-baseline gap-1">
|
|
283
|
+
<label htmlFor={editable ? id : undefined} className="text-xs text-muted-foreground">
|
|
284
|
+
{field.label}
|
|
285
|
+
</label>
|
|
286
|
+
{/* Outside the label, and attached as a description instead. Inside it,
|
|
287
|
+
editing a field would rename the field — a screen reader user would
|
|
288
|
+
hear its accessible name change under them mid-edit. Marked in text
|
|
289
|
+
rather than by border colour alone, because an audit trail has to
|
|
290
|
+
tell the model's proposal from the human's correction. */}
|
|
291
|
+
{changed ? (
|
|
292
|
+
<span id={changedId} className="text-xs text-warning">
|
|
293
|
+
· changed from the model’s proposal
|
|
294
|
+
</span>
|
|
295
|
+
) : null}
|
|
296
|
+
</dt>
|
|
297
|
+
<dd className="m-0">
|
|
298
|
+
{!arrived ? (
|
|
299
|
+
<span
|
|
300
|
+
aria-hidden="true"
|
|
301
|
+
className="block h-8 w-full animate-pulse-soft rounded-md bg-muted"
|
|
302
|
+
/>
|
|
303
|
+
) : editable ? (
|
|
304
|
+
field.multiline ? (
|
|
305
|
+
<textarea
|
|
306
|
+
id={id}
|
|
307
|
+
aria-describedby={changed ? changedId : undefined}
|
|
308
|
+
rows={3}
|
|
309
|
+
value={value}
|
|
310
|
+
onChange={(event) => {
|
|
311
|
+
onChange(event.target.value);
|
|
312
|
+
}}
|
|
313
|
+
className={cn(
|
|
314
|
+
"w-full resize-none rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs",
|
|
315
|
+
changed && "border-warning",
|
|
316
|
+
focusRing,
|
|
317
|
+
)}
|
|
318
|
+
/>
|
|
319
|
+
) : (
|
|
320
|
+
<input
|
|
321
|
+
id={id}
|
|
322
|
+
type="text"
|
|
323
|
+
aria-describedby={changed ? changedId : undefined}
|
|
324
|
+
value={value}
|
|
325
|
+
onChange={(event) => {
|
|
326
|
+
onChange(event.target.value);
|
|
327
|
+
}}
|
|
328
|
+
className={cn(
|
|
329
|
+
"w-full rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs",
|
|
330
|
+
changed && "border-warning",
|
|
331
|
+
focusRing,
|
|
332
|
+
)}
|
|
333
|
+
/>
|
|
334
|
+
)
|
|
335
|
+
) : (
|
|
336
|
+
<p className="rounded-md bg-muted px-2 py-1.5 font-mono text-xs break-words">
|
|
337
|
+
{value}
|
|
338
|
+
</p>
|
|
339
|
+
)}
|
|
340
|
+
</dd>
|
|
341
|
+
</div>
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function Action({
|
|
346
|
+
className,
|
|
347
|
+
variant = "default",
|
|
348
|
+
...props
|
|
349
|
+
}: ComponentPropsWithRef<"button"> & { variant?: "default" | "primary" | "destructive" }) {
|
|
350
|
+
return (
|
|
351
|
+
<button
|
|
352
|
+
type="button"
|
|
353
|
+
className={cn(
|
|
354
|
+
"rounded-md border px-2.5 py-1 text-xs font-medium transition-colors",
|
|
355
|
+
variant === "primary" &&
|
|
356
|
+
"border-primary bg-primary text-primary-foreground hover:bg-primary-hover",
|
|
357
|
+
variant === "destructive" &&
|
|
358
|
+
"border-destructive bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
359
|
+
variant === "default" &&
|
|
360
|
+
"border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
361
|
+
focusRing,
|
|
362
|
+
disabledStyles,
|
|
363
|
+
className,
|
|
364
|
+
)}
|
|
365
|
+
{...props}
|
|
366
|
+
/>
|
|
367
|
+
);
|
|
368
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineMeta } from "@/registry/schema";
|
|
2
|
+
|
|
3
|
+
export const meta = defineMeta({
|
|
4
|
+
name: "ai-approval-request",
|
|
5
|
+
title: "AI Approval Request",
|
|
6
|
+
description: "Approve a tool call — after correcting the arguments the model got wrong.",
|
|
7
|
+
category: "ai",
|
|
8
|
+
status: "stable",
|
|
9
|
+
dependencies: [],
|
|
10
|
+
registryDependencies: [],
|
|
11
|
+
files: ["ai-approval-request.tsx"],
|
|
12
|
+
a11y:
|
|
13
|
+
"The proposed arguments are a description list of real labelled form controls, so each value " +
|
|
14
|
+
"is associated with its name and editable ones are reachable by keyboard. A corrected " +
|
|
15
|
+
"argument is marked in text rather than by border colour alone, because an audit trail has " +
|
|
16
|
+
"to distinguish the model's proposal from the human's edit. The request is aria-busy while " +
|
|
17
|
+
"arguments are still arriving and the decision controls stay disabled until it is whole — " +
|
|
18
|
+
"rendering nothing until then, as the common implementation does, means nothing is on screen " +
|
|
19
|
+
"at the moment approval becomes relevant. Irreversibility is stated as a sentence, never as a " +
|
|
20
|
+
"severity colour.",
|
|
21
|
+
});
|