@adoptai/genui-components 0.1.59 → 0.1.60
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/dist/builders/BlockForm.d.ts +5 -1
- package/dist/builders/BlockForm.d.ts.map +1 -1
- package/dist/builders/BuilderForm.d.ts +22 -1
- package/dist/builders/BuilderForm.d.ts.map +1 -1
- package/dist/builders/index.d.ts +1 -1
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/composites/decision-card/resolver.cjs +289 -13
- package/dist/composites/decision-card/resolver.cjs.map +1 -1
- package/dist/composites/decision-card/resolver.d.ts +2 -1
- package/dist/composites/decision-card/resolver.d.ts.map +1 -1
- package/dist/composites/decision-card/resolver.js +289 -13
- package/dist/composites/decision-card/resolver.js.map +1 -1
- package/dist/index.cjs +409 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +409 -36
- package/dist/index.js.map +1 -1
- package/dist/renderer.cjs +318 -18
- package/dist/renderer.cjs.map +1 -1
- package/dist/renderer.js +318 -18
- package/dist/renderer.js.map +1 -1
- package/dist/resolver.cjs +318 -18
- package/dist/resolver.cjs.map +1 -1
- package/dist/resolver.js +318 -18
- package/dist/resolver.js.map +1 -1
- package/dist/schemas/decision-card.d.ts +37 -0
- package/dist/schemas/decision-card.d.ts.map +1 -1
- package/dist/schemas/index.cjs +29 -5
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.ts +37 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +29 -5
- package/dist/schemas/index.js.map +1 -1
- package/dist/tool-definitions.json +35 -3
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { BuilderPayload } from "./schemas";
|
|
2
2
|
import type { BuilderState } from "./hooks";
|
|
3
3
|
import type { FileUploadResult, EntitySearch, EntityCreate } from "./fields";
|
|
4
|
+
import type { FieldSuggestion } from "./BuilderForm";
|
|
4
5
|
/** Single-block builder presentation. Two cosmetic variants of the SAME form:
|
|
5
6
|
* - "escalation": compact, accent left-rail, no title (the host/dock owns it),
|
|
6
7
|
* outlined "Continue" CTA, no in-card cancel. A high-urgency interruption
|
|
@@ -26,6 +27,9 @@ export interface BlockFormProps {
|
|
|
26
27
|
dense?: boolean;
|
|
27
28
|
/** Cosmetic variant. Defaults to "form". */
|
|
28
29
|
variant?: BlockFormVariant;
|
|
30
|
+
/** Agent-proposed values rendered as Apply chips under matching fields. */
|
|
31
|
+
fieldSuggestions?: FieldSuggestion[];
|
|
32
|
+
onApplySuggestion?: (suggestion: FieldSuggestion) => void;
|
|
29
33
|
}
|
|
30
|
-
export declare function BlockForm({ builder, state, onSubmit, onCancel, disabled, onFileUpload, onEntitySearch, onEntityCreate, hideActions, dense, variant, }: BlockFormProps): import("react/jsx-runtime").JSX.Element | null;
|
|
34
|
+
export declare function BlockForm({ builder, state, onSubmit, onCancel, disabled, onFileUpload, onEntitySearch, onEntityCreate, hideActions, dense, variant, fieldSuggestions, onApplySuggestion, }: BlockFormProps): import("react/jsx-runtime").JSX.Element | null;
|
|
31
35
|
//# sourceMappingURL=BlockForm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockForm.d.ts","sourceRoot":"","sources":["../../src/builders/BlockForm.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"BlockForm.d.ts","sourceRoot":"","sources":["../../src/builders/BlockForm.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;;qFAOqF;AACrF,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,MAAM,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACzD,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B;0EACsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,cAAc,EACd,WAAW,EACX,KAAK,EACL,OAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GAClB,EAAE,cAAc,kDAyJhB"}
|
|
@@ -16,6 +16,21 @@ export interface BuilderSubmission {
|
|
|
16
16
|
}>;
|
|
17
17
|
values?: Record<string, unknown>;
|
|
18
18
|
}
|
|
19
|
+
/** An agent-proposed value for one field (e.g. surfaced from an escalation
|
|
20
|
+
* discussion thread). Rendered as a "Suggested: X — Apply" chip under the
|
|
21
|
+
* matching field; Apply writes the value into the draft, where the user can
|
|
22
|
+
* still edit it freely before submitting. */
|
|
23
|
+
export interface FieldSuggestion {
|
|
24
|
+
/** Field name the suggestion targets. */
|
|
25
|
+
field: string;
|
|
26
|
+
/** Block id when the builder has several; defaults to the first block. */
|
|
27
|
+
block_id?: string;
|
|
28
|
+
value: unknown;
|
|
29
|
+
/** Display override for the value (e.g. "$6.69M" for 6692000). */
|
|
30
|
+
label?: string;
|
|
31
|
+
/** Short provenance note, e.g. "verified against sheet 4 · D47". */
|
|
32
|
+
note?: string;
|
|
33
|
+
}
|
|
19
34
|
export interface BuilderFormProps {
|
|
20
35
|
builder: BuilderPayload;
|
|
21
36
|
onSubmit: (submission: BuilderSubmission) => void;
|
|
@@ -43,6 +58,12 @@ export interface BuilderFormProps {
|
|
|
43
58
|
* the failing fields. Lets the host (dock) scroll to + focus the offending
|
|
44
59
|
* field and show a summary instead of the submit silently doing nothing. */
|
|
45
60
|
onValidationError?: (failure: ValidationFailure) => void;
|
|
61
|
+
/** Agent-proposed field values (see {@link FieldSuggestion}). Honoured by
|
|
62
|
+
* the form/escalation presentations; a suggestion whose field/block doesn't
|
|
63
|
+
* exist is silently ignored. */
|
|
64
|
+
fieldSuggestions?: FieldSuggestion[];
|
|
65
|
+
/** Fired when the user applies a suggestion (after the draft is updated). */
|
|
66
|
+
onApplySuggestion?: (suggestion: FieldSuggestion) => void;
|
|
46
67
|
}
|
|
47
|
-
export declare function BuilderFormResolver({ builder, onSubmit, onCancel, disabled, onFileUpload, onEntitySearch, onEntityCreate, onChange, submitRef, hideActions, dense, onValidationError, }: BuilderFormProps): import("react/jsx-runtime").JSX.Element;
|
|
68
|
+
export declare function BuilderFormResolver({ builder, onSubmit, onCancel, disabled, onFileUpload, onEntitySearch, onEntityCreate, onChange, submitRef, hideActions, dense, onValidationError, fieldSuggestions, onApplySuggestion, }: BuilderFormProps): import("react/jsx-runtime").JSX.Element;
|
|
48
69
|
//# sourceMappingURL=BuilderForm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BuilderForm.d.ts","sourceRoot":"","sources":["../../src/builders/BuilderForm.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAI9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7E;;;kDAGkD;AAClD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;IAChD,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACzD,yEAAyE;IACzE,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B;;qDAEiD;IACjD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC9C;;uDAEmD;IACnD,SAAS,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxD;6EACyE;IACzE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;oDACgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;iFAE6E;IAC7E,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"BuilderForm.d.ts","sourceRoot":"","sources":["../../src/builders/BuilderForm.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAI9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7E;;;kDAGkD;AAClD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;IAChD,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;;6CAG6C;AAC7C,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACzD,yEAAyE;IACzE,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B;;qDAEiD;IACjD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC9C;;uDAEmD;IACnD,SAAS,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxD;6EACyE;IACzE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;oDACgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;iFAE6E;IAC7E,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACzD;;qCAEiC;IACjC,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,cAAc,EACd,QAAQ,EACR,SAAS,EACT,WAAW,EACX,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,EAAE,gBAAgB,2CA4HlB"}
|
package/dist/builders/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { builderSchema, builderBlockSchema, builderFieldSchema, builderFieldOpti
|
|
|
2
2
|
export type { BuilderPayload, BuilderBlock, BuilderField, BuilderFieldType, BuilderFieldOption, EntityOption, EntityCreateField, FileMapConfig, FileMapCategory, FileMapFile, FileMapValue, } from "./schemas";
|
|
3
3
|
export { validateBuilderPayload } from "./validateBuilder";
|
|
4
4
|
export { BuilderFormResolver } from "./BuilderForm";
|
|
5
|
-
export type { BuilderFormProps, BuilderSubmission } from "./BuilderForm";
|
|
5
|
+
export type { BuilderFormProps, BuilderSubmission, FieldSuggestion } from "./BuilderForm";
|
|
6
6
|
export { BuilderRecap } from "./BuilderRecap";
|
|
7
7
|
export type { BuilderRecapProps } from "./BuilderRecap";
|
|
8
8
|
export { BlockForm } from "./BlockForm";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builders/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,4BAA4B,EAC5B,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,WAAW,EACX,YAAY,GACb,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAG3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builders/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,4BAA4B,EAC5B,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,WAAW,EACX,YAAY,GACb,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAG3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -289,8 +289,15 @@ function useContainerWidth(ref) {
|
|
|
289
289
|
var KEYFRAMES = `
|
|
290
290
|
@keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
|
|
291
291
|
.dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
|
|
292
|
+
.dc-range{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:9999px;outline:none;cursor:pointer;background:transparent}
|
|
293
|
+
.dc-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:white;border:2px solid var(--dc-thumb,#ff5000);box-shadow:0 1px 3px rgba(0,0,0,0.18);cursor:grab;transition:transform 0.12s}
|
|
294
|
+
.dc-range::-webkit-slider-thumb:hover{transform:scale(1.12)}
|
|
295
|
+
.dc-range:active::-webkit-slider-thumb{cursor:grabbing}
|
|
296
|
+
.dc-range::-moz-range-thumb{width:12px;height:12px;border-radius:50%;background:white;border:2px solid var(--dc-thumb,#ff5000);box-shadow:0 1px 3px rgba(0,0,0,0.18);cursor:grab}
|
|
297
|
+
.dc-range::-moz-range-track{height:4px;border-radius:9999px;background:transparent}
|
|
292
298
|
@media (prefers-reduced-motion: reduce){
|
|
293
299
|
.dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
|
|
300
|
+
.dc-range::-webkit-slider-thumb{transition:none}
|
|
294
301
|
}`;
|
|
295
302
|
function SparkCheck({ size, color }) {
|
|
296
303
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -336,17 +343,239 @@ function FlagPill({ flag }) {
|
|
|
336
343
|
}
|
|
337
344
|
);
|
|
338
345
|
}
|
|
346
|
+
function formatFigure(value, unit) {
|
|
347
|
+
const body = Number.isInteger(value) ? `${value}` : `${Math.round(value * 100) / 100}`;
|
|
348
|
+
if (!unit) return body;
|
|
349
|
+
return unit === "%" ? `${body}%` : `${body} ${unit}`;
|
|
350
|
+
}
|
|
351
|
+
function clampToRange(raw, adjust) {
|
|
352
|
+
var _a;
|
|
353
|
+
const step = (_a = adjust.step) != null ? _a : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
|
|
354
|
+
const snapped = Math.round((raw - adjust.min) / step) * step + adjust.min;
|
|
355
|
+
const fixed = Math.round(snapped * 1e6) / 1e6;
|
|
356
|
+
return Math.min(adjust.max, Math.max(adjust.min, fixed));
|
|
357
|
+
}
|
|
358
|
+
function ValueAdjuster({
|
|
359
|
+
option,
|
|
360
|
+
accent,
|
|
361
|
+
border,
|
|
362
|
+
muted,
|
|
363
|
+
onConfirm,
|
|
364
|
+
onBack
|
|
365
|
+
}) {
|
|
366
|
+
var _a, _b;
|
|
367
|
+
const adjust = option.adjust;
|
|
368
|
+
const suggested = clampToRange((_a = option.value) != null ? _a : adjust.min, adjust);
|
|
369
|
+
const [value, setValue] = React4__default.default.useState(suggested);
|
|
370
|
+
const [text, setText] = React4__default.default.useState(String(suggested));
|
|
371
|
+
const step = (_b = adjust.step) != null ? _b : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
|
|
372
|
+
const pct = adjust.max > adjust.min ? (value - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
|
|
373
|
+
const suggestedPct = adjust.max > adjust.min ? (suggested - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
|
|
374
|
+
const moved = value !== suggested;
|
|
375
|
+
const commit = (raw) => {
|
|
376
|
+
const v = clampToRange(raw, adjust);
|
|
377
|
+
setValue(v);
|
|
378
|
+
setText(String(v));
|
|
379
|
+
};
|
|
380
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
381
|
+
"div",
|
|
382
|
+
{
|
|
383
|
+
className: "dc-rise",
|
|
384
|
+
"data-testid": "decision-card-adjuster",
|
|
385
|
+
style: {
|
|
386
|
+
display: "flex",
|
|
387
|
+
flexDirection: "column",
|
|
388
|
+
gap: 12,
|
|
389
|
+
border: `1px solid ${border}`,
|
|
390
|
+
borderRadius: 10,
|
|
391
|
+
padding: "12px 14px",
|
|
392
|
+
background: "#fafafa"
|
|
393
|
+
},
|
|
394
|
+
children: [
|
|
395
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 8 }, children: [
|
|
396
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.06em", color: muted }, children: [
|
|
397
|
+
"Adjust \xB7 ",
|
|
398
|
+
option.label
|
|
399
|
+
] }),
|
|
400
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
|
|
401
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
402
|
+
"button",
|
|
403
|
+
{
|
|
404
|
+
type: "button",
|
|
405
|
+
onClick: onBack,
|
|
406
|
+
"data-testid": "decision-card-adjust-back",
|
|
407
|
+
style: { border: "none", background: "none", padding: 0, cursor: "pointer", fontSize: 12, fontWeight: 600, color: muted },
|
|
408
|
+
children: "Back"
|
|
409
|
+
}
|
|
410
|
+
)
|
|
411
|
+
] }),
|
|
412
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 6 }, children: [
|
|
413
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
414
|
+
"input",
|
|
415
|
+
{
|
|
416
|
+
value: text,
|
|
417
|
+
onChange: (e) => {
|
|
418
|
+
setText(e.target.value);
|
|
419
|
+
const n = Number(e.target.value);
|
|
420
|
+
if (Number.isFinite(n)) setValue(clampToRange(n, adjust));
|
|
421
|
+
},
|
|
422
|
+
onBlur: () => commit(Number(text) || suggested),
|
|
423
|
+
onKeyDown: (e) => {
|
|
424
|
+
if (e.key === "Enter") {
|
|
425
|
+
const v = clampToRange(Number(text) || suggested, adjust);
|
|
426
|
+
commit(v);
|
|
427
|
+
onConfirm(v);
|
|
428
|
+
} else if (e.key === "ArrowUp") {
|
|
429
|
+
e.preventDefault();
|
|
430
|
+
commit(value + step);
|
|
431
|
+
} else if (e.key === "ArrowDown") {
|
|
432
|
+
e.preventDefault();
|
|
433
|
+
commit(value - step);
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
inputMode: "decimal",
|
|
437
|
+
"aria-label": `${option.label} value`,
|
|
438
|
+
"data-testid": "decision-card-adjust-input",
|
|
439
|
+
style: {
|
|
440
|
+
width: `${Math.max(3, String(text).length + 1)}ch`,
|
|
441
|
+
fontSize: 26,
|
|
442
|
+
fontWeight: 700,
|
|
443
|
+
fontVariantNumeric: "tabular-nums",
|
|
444
|
+
letterSpacing: "-0.02em",
|
|
445
|
+
color: "var(--foreground)",
|
|
446
|
+
border: "none",
|
|
447
|
+
borderBottom: `2px solid ${accent}`,
|
|
448
|
+
background: "transparent",
|
|
449
|
+
outline: "none",
|
|
450
|
+
padding: 0
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
),
|
|
454
|
+
adjust.unit && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13, fontWeight: 600, color: muted }, children: adjust.unit }),
|
|
455
|
+
moved && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
456
|
+
"button",
|
|
457
|
+
{
|
|
458
|
+
type: "button",
|
|
459
|
+
onClick: () => commit(suggested),
|
|
460
|
+
"data-testid": "decision-card-adjust-reset",
|
|
461
|
+
style: {
|
|
462
|
+
marginLeft: 8,
|
|
463
|
+
border: "none",
|
|
464
|
+
background: "none",
|
|
465
|
+
padding: 0,
|
|
466
|
+
cursor: "pointer",
|
|
467
|
+
fontSize: 11.5,
|
|
468
|
+
fontWeight: 600,
|
|
469
|
+
color: muted,
|
|
470
|
+
textDecoration: "underline",
|
|
471
|
+
textUnderlineOffset: 2
|
|
472
|
+
},
|
|
473
|
+
children: [
|
|
474
|
+
"Reset to suggested (",
|
|
475
|
+
formatFigure(suggested, adjust.unit),
|
|
476
|
+
")"
|
|
477
|
+
]
|
|
478
|
+
}
|
|
479
|
+
)
|
|
480
|
+
] }),
|
|
481
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
|
|
482
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", height: 16, display: "flex", alignItems: "center" }, children: [
|
|
483
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
484
|
+
"div",
|
|
485
|
+
{
|
|
486
|
+
"aria-hidden": "true",
|
|
487
|
+
style: {
|
|
488
|
+
position: "absolute",
|
|
489
|
+
left: 0,
|
|
490
|
+
right: 0,
|
|
491
|
+
height: 4,
|
|
492
|
+
borderRadius: 9999,
|
|
493
|
+
background: `linear-gradient(to right, ${accent} ${pct}%, #e8e8e8 ${pct}%)`
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
),
|
|
497
|
+
moved && /* @__PURE__ */ jsxRuntime.jsx(
|
|
498
|
+
"div",
|
|
499
|
+
{
|
|
500
|
+
"aria-hidden": "true",
|
|
501
|
+
title: `Suggested: ${formatFigure(suggested, adjust.unit)}`,
|
|
502
|
+
style: {
|
|
503
|
+
position: "absolute",
|
|
504
|
+
left: `${suggestedPct}%`,
|
|
505
|
+
transform: "translateX(-50%)",
|
|
506
|
+
width: 2,
|
|
507
|
+
height: 10,
|
|
508
|
+
borderRadius: 1,
|
|
509
|
+
background: muted,
|
|
510
|
+
opacity: 0.55
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
),
|
|
514
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
515
|
+
"input",
|
|
516
|
+
{
|
|
517
|
+
type: "range",
|
|
518
|
+
className: "dc-range",
|
|
519
|
+
min: adjust.min,
|
|
520
|
+
max: adjust.max,
|
|
521
|
+
step,
|
|
522
|
+
value,
|
|
523
|
+
onChange: (e) => commit(Number(e.target.value)),
|
|
524
|
+
"aria-label": `${option.label} slider`,
|
|
525
|
+
"data-testid": "decision-card-adjust-slider",
|
|
526
|
+
style: { position: "relative", ["--dc-thumb"]: accent }
|
|
527
|
+
}
|
|
528
|
+
)
|
|
529
|
+
] }),
|
|
530
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 10.5, fontWeight: 600, color: muted, fontVariantNumeric: "tabular-nums" }, children: [
|
|
531
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFigure(adjust.min, adjust.unit) }),
|
|
532
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFigure(adjust.max, adjust.unit) })
|
|
533
|
+
] })
|
|
534
|
+
] }),
|
|
535
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
536
|
+
"button",
|
|
537
|
+
{
|
|
538
|
+
type: "button",
|
|
539
|
+
onClick: () => onConfirm(value),
|
|
540
|
+
"data-testid": "decision-card-adjust-confirm",
|
|
541
|
+
style: {
|
|
542
|
+
alignSelf: "flex-start",
|
|
543
|
+
border: `1px solid ${accent}`,
|
|
544
|
+
background: accent,
|
|
545
|
+
color: "white",
|
|
546
|
+
borderRadius: 8,
|
|
547
|
+
fontSize: 13,
|
|
548
|
+
fontWeight: 600,
|
|
549
|
+
padding: "9px 16px",
|
|
550
|
+
cursor: "pointer",
|
|
551
|
+
fontVariantNumeric: "tabular-nums",
|
|
552
|
+
transition: "opacity 0.15s"
|
|
553
|
+
},
|
|
554
|
+
onMouseEnter: (e) => e.currentTarget.style.opacity = "0.88",
|
|
555
|
+
onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
|
|
556
|
+
children: [
|
|
557
|
+
option.label,
|
|
558
|
+
" \xB7 ",
|
|
559
|
+
formatFigure(value, adjust.unit)
|
|
560
|
+
]
|
|
561
|
+
}
|
|
562
|
+
)
|
|
563
|
+
]
|
|
564
|
+
}
|
|
565
|
+
);
|
|
566
|
+
}
|
|
339
567
|
function DecisionCardRenderer({
|
|
340
568
|
data,
|
|
341
569
|
resolved = null,
|
|
342
570
|
onResolve,
|
|
343
571
|
onOpenSource
|
|
344
572
|
}) {
|
|
345
|
-
var _a, _b;
|
|
573
|
+
var _a, _b, _c;
|
|
346
574
|
const { BORDER: BORDER2, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
|
|
347
575
|
const rootRef = React4__default.default.useRef(null);
|
|
348
576
|
const width = useContainerWidth(rootRef);
|
|
349
577
|
const stacked = width > 0 && width < STACK_BELOW;
|
|
578
|
+
const [adjustingIdx, setAdjustingIdx] = React4__default.default.useState(null);
|
|
350
579
|
const options = (_a = data.options) != null ? _a : [];
|
|
351
580
|
const recommendedIdx = Math.max(
|
|
352
581
|
0,
|
|
@@ -501,7 +730,20 @@ function DecisionCardRenderer({
|
|
|
501
730
|
]
|
|
502
731
|
}
|
|
503
732
|
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
504
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
733
|
+
adjustingIdx != null && ((_b = options[adjustingIdx]) == null ? void 0 : _b.adjust) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
734
|
+
ValueAdjuster,
|
|
735
|
+
{
|
|
736
|
+
option: options[adjustingIdx],
|
|
737
|
+
accent: ACCENT2,
|
|
738
|
+
border: BORDER2,
|
|
739
|
+
muted: MUTED2,
|
|
740
|
+
onBack: () => setAdjustingIdx(null),
|
|
741
|
+
onConfirm: (value) => {
|
|
742
|
+
setAdjustingIdx(null);
|
|
743
|
+
onResolve == null ? void 0 : onResolve(options[adjustingIdx].label, value);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
505
747
|
"div",
|
|
506
748
|
{
|
|
507
749
|
style: {
|
|
@@ -511,15 +753,21 @@ function DecisionCardRenderer({
|
|
|
511
753
|
gap: 8
|
|
512
754
|
},
|
|
513
755
|
children: options.map((opt, idx) => {
|
|
514
|
-
var _a2;
|
|
756
|
+
var _a2, _b2;
|
|
515
757
|
const primary = idx === recommendedIdx;
|
|
516
|
-
|
|
758
|
+
const adjustable = Boolean(opt.adjust);
|
|
759
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
517
760
|
"button",
|
|
518
761
|
{
|
|
519
762
|
type: "button",
|
|
520
|
-
onClick: () => onResolve == null ? void 0 : onResolve(opt.label),
|
|
763
|
+
onClick: () => adjustable ? setAdjustingIdx(idx) : onResolve == null ? void 0 : onResolve(opt.label),
|
|
764
|
+
"data-adjustable": adjustable || void 0,
|
|
521
765
|
style: {
|
|
522
766
|
width: stacked ? "100%" : "auto",
|
|
767
|
+
display: "inline-flex",
|
|
768
|
+
alignItems: "center",
|
|
769
|
+
justifyContent: stacked ? "flex-start" : "center",
|
|
770
|
+
gap: 7,
|
|
523
771
|
textAlign: stacked ? "left" : "center",
|
|
524
772
|
border: `1px solid ${primary ? ACCENT2 : BORDER2}`,
|
|
525
773
|
background: primary ? ACCENT2 : "white",
|
|
@@ -547,7 +795,28 @@ function DecisionCardRenderer({
|
|
|
547
795
|
e.currentTarget.style.background = "white";
|
|
548
796
|
}
|
|
549
797
|
},
|
|
550
|
-
children:
|
|
798
|
+
children: [
|
|
799
|
+
opt.label,
|
|
800
|
+
adjustable && typeof opt.value === "number" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
801
|
+
"span",
|
|
802
|
+
{
|
|
803
|
+
style: {
|
|
804
|
+
fontSize: 11.5,
|
|
805
|
+
fontWeight: 700,
|
|
806
|
+
fontVariantNumeric: "tabular-nums",
|
|
807
|
+
padding: "1px 7px",
|
|
808
|
+
borderRadius: 9999,
|
|
809
|
+
background: primary ? "rgba(255,255,255,0.22)" : "#f2f2f2",
|
|
810
|
+
color: primary ? "white" : MUTED2,
|
|
811
|
+
lineHeight: 1.5
|
|
812
|
+
},
|
|
813
|
+
children: [
|
|
814
|
+
formatFigure(opt.value, (_b2 = opt.adjust) == null ? void 0 : _b2.unit),
|
|
815
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { marginLeft: 4, opacity: 0.8 }, children: "\u270E" })
|
|
816
|
+
]
|
|
817
|
+
}
|
|
818
|
+
)
|
|
819
|
+
]
|
|
551
820
|
},
|
|
552
821
|
(_a2 = opt.id) != null ? _a2 : opt.label
|
|
553
822
|
);
|
|
@@ -586,7 +855,7 @@ function DecisionCardRenderer({
|
|
|
586
855
|
strokeLinejoin: "round"
|
|
587
856
|
}
|
|
588
857
|
) }),
|
|
589
|
-
(
|
|
858
|
+
(_c = data.source.label) != null ? _c : "View source for this figure"
|
|
590
859
|
]
|
|
591
860
|
}
|
|
592
861
|
)
|
|
@@ -595,20 +864,27 @@ function DecisionCardRenderer({
|
|
|
595
864
|
}
|
|
596
865
|
);
|
|
597
866
|
}
|
|
867
|
+
function composeResolution(p, option, value) {
|
|
868
|
+
var _a, _b, _c;
|
|
869
|
+
if (value == null) return option;
|
|
870
|
+
const unit = (_c = (_b = ((_a = p.options) != null ? _a : []).find((o) => o.label === option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
|
|
871
|
+
return `${option} \xB7 ${formatFigure(value, unit)}`;
|
|
872
|
+
}
|
|
598
873
|
function DecisionCardResolver(p) {
|
|
599
|
-
var _a, _b
|
|
874
|
+
var _a, _b;
|
|
600
875
|
const { resolvedDecisions, onDecisionResolve, onDecisionSource } = useGenUIInteraction();
|
|
601
876
|
const decisionId = (_a = p.id) != null ? _a : p.title;
|
|
602
877
|
const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
|
|
603
|
-
const initial =
|
|
878
|
+
const initial = hostResolved != null ? hostResolved : p.resolved ? composeResolution(p, p.resolved.option, p.resolved.value) : null;
|
|
604
879
|
const [localResolved, setLocalResolved] = React4__default.default.useState(initial);
|
|
605
880
|
React4__default.default.useEffect(() => {
|
|
606
881
|
if (hostResolved !== void 0) setLocalResolved(hostResolved);
|
|
607
882
|
}, [hostResolved]);
|
|
608
883
|
const resolved = hostResolved != null ? hostResolved : localResolved;
|
|
609
|
-
const handleResolve = (option) => {
|
|
610
|
-
|
|
611
|
-
|
|
884
|
+
const handleResolve = (option, value) => {
|
|
885
|
+
const resolution = composeResolution(p, option, value);
|
|
886
|
+
setLocalResolved(resolution);
|
|
887
|
+
onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, resolution);
|
|
612
888
|
};
|
|
613
889
|
const handleSource = () => {
|
|
614
890
|
var _a2;
|
|
@@ -617,7 +893,7 @@ function DecisionCardResolver(p) {
|
|
|
617
893
|
window.open(p.source.url, "_blank", "noopener,noreferrer");
|
|
618
894
|
}
|
|
619
895
|
};
|
|
620
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (
|
|
896
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_b = p.title) != null ? _b : "decision-card", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
621
897
|
DecisionCardRenderer,
|
|
622
898
|
{
|
|
623
899
|
data: p,
|