@timeax/digital-service-engine 0.0.1 → 0.0.3

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.
@@ -34,12 +34,13 @@ interface BaseFieldUI {
34
34
  name?: string;
35
35
  label: string;
36
36
  required?: boolean;
37
- /** Host-defined prop names → typed UI nodes */
38
- ui?: Record<string, Ui>;
39
37
  /** Host-defined prop names → runtime default values (untyped base) */
40
38
  defaults?: Record<string, unknown>;
41
39
  }
42
- type Ui = UiString | UiNumber | UiBoolean | UiAnyOf | UiArray | UiObject;
40
+ type Ui = (UiString | UiNumber | UiBoolean | UiAnyOf | UiArray | UiObject) & {
41
+ description: string;
42
+ label: string;
43
+ };
43
44
  /** string */
44
45
  interface UiString {
45
46
  type: "string";
@@ -74,8 +75,17 @@ interface UiAnyOf {
74
75
  /** arrays: homogeneous (item) or tuple (items) */
75
76
  interface UiArray {
76
77
  type: "array";
78
+ label: string;
79
+ description: string;
77
80
  item?: Ui;
78
81
  items?: Ui[];
82
+ editable?: boolean;
83
+ /**
84
+ * Optional: allowed shapes for new items.
85
+ * Key = label shown in UI picker
86
+ * Value = schema for the new element
87
+ */
88
+ shape?: Record<string, Ui>;
79
89
  minItems?: number;
80
90
  maxItems?: number;
81
91
  uniqueItems?: boolean;
@@ -83,7 +93,16 @@ interface UiArray {
83
93
  /** objects: nested props */
84
94
  interface UiObject {
85
95
  type: "object";
96
+ label: string;
97
+ description: string;
98
+ editable?: boolean;
86
99
  fields: Record<string, Ui>;
100
+ /**
101
+ * Optional: allowed shapes for dynamically added keys.
102
+ * Key = human-readable name shown in UI picker
103
+ * Value = schema applied to the value of the new key
104
+ */
105
+ shape?: Record<string, Ui>;
87
106
  required?: string[];
88
107
  order?: string[];
89
108
  }
@@ -192,6 +211,8 @@ type ServiceProps = {
192
211
  excludes_for_buttons?: Record<string, string[]>;
193
212
  schema_version?: string;
194
213
  fallbacks?: ServiceFallback;
214
+ name?: string;
215
+ notices?: ServicePropsNotice[];
195
216
  };
196
217
  type ServiceIdRef = number | string;
197
218
  type NodeIdRef = string;
@@ -201,6 +222,34 @@ type ServiceFallback = {
201
222
  /** Primary→fallback list used when no node-scoped entry is present */
202
223
  global?: Record<ServiceIdRef, ServiceIdRef[]>;
203
224
  };
225
+ type NoticeType = "public" | "private";
226
+ type NoticeSeverity = "info" | "warning" | "error";
227
+ /**
228
+ * “label” is lightweight + UI-friendly (best, sale, hot, etc).
229
+ * Others remain semantic / governance oriented.
230
+ */
231
+ type NoticeKind = "label" | "warning" | "deprecation" | "compat" | "migration" | "policy";
232
+ type NoticeTarget = {
233
+ scope: "global";
234
+ } | {
235
+ scope: "node";
236
+ node_kind: "tag" | "field" | "option";
237
+ node_id: string;
238
+ };
239
+ interface ServicePropsNotice {
240
+ id: string;
241
+ type: NoticeType;
242
+ kind: NoticeKind;
243
+ severity: NoticeSeverity;
244
+ target: NoticeTarget;
245
+ title: string;
246
+ description?: string;
247
+ reason?: string;
248
+ marked_at?: string;
249
+ icon?: string;
250
+ color?: string;
251
+ meta?: Record<string, unknown>;
252
+ }
204
253
 
205
254
  type NodeKind = "tag" | "field" | "comment" | "option";
206
255
  type EdgeKind = "child" | "bind" | "include" | "exclude" | "error" | "anchor";
@@ -440,6 +489,22 @@ type DgpServiceCapability = {
440
489
  };
441
490
  type DgpServiceMap = Record<string, DgpServiceCapability> & Record<number, DgpServiceCapability>;
442
491
 
492
+ type NodeRef$1 = {
493
+ kind: "tag";
494
+ id: string;
495
+ node: Tag;
496
+ } | {
497
+ kind: "field";
498
+ id: string;
499
+ node: Field;
500
+ } | {
501
+ kind: "option";
502
+ id: string;
503
+ node: FieldOption;
504
+ fieldId: string;
505
+ };
506
+ type NodeMap = Map<string, NodeRef$1>;
507
+
443
508
  type ValidationCode = "root_missing" | "cycle_in_tags" | "bad_bind_reference" | "duplicate_id" | "duplicate_tag_label" | "duplicate_field_name" | "label_missing" | "duplicate_visible_label" | "bad_option_key" | "option_include_exclude_conflict" | "service_field_missing_service_id" | "user_input_field_has_service_option" | "rate_mismatch_across_base" | "utility_without_base" | "unsupported_constraint" | "constraint_contradiction" | "custom_component_missing" | "policy_violation" | "field_unbound" | "constraint_overridden" | "unsupported_constraint_option" | "custom_component_unresolvable" | "quantity_multiple_markers" | "utility_with_service_id" | "utility_missing_rate" | "utility_invalid_mode" | "fallback_bad_node" | "fallback_unknown_service" | "fallback_cycle" | "fallback_no_primary" | "fallback_rate_violation" | "fallback_constraint_mismatch" | "fallback_no_tag_context";
444
509
  type ValidationError = {
445
510
  code: ValidationCode;
@@ -488,6 +553,7 @@ type DynamicRule = {
488
553
  };
489
554
  type ValidatorOptions = {
490
555
  serviceMap?: DgpServiceMap;
556
+ nodeMap?: NodeMap;
491
557
  allowUnsafe?: boolean;
492
558
  selectedOptionKeys?: string[];
493
559
  globalUtilityGuard?: boolean;
@@ -556,108 +622,12 @@ interface Builder {
556
622
  description: string;
557
623
  value: string;
558
624
  }[];
625
+ isTagId(id: string): boolean;
626
+ isFieldId(id: string): boolean;
627
+ isOptionId(id: string): boolean;
628
+ getNodeMap(): NodeMap;
559
629
  }
560
630
 
561
- type Env = "client" | "workspace";
562
- type VisibleGroup = {
563
- tagId?: string;
564
- tag?: Tag;
565
- fields: Field[];
566
- fieldIds: string[];
567
- parentTags?: Tag[];
568
- childrenTags?: Tag[];
569
- /** In order of selection: tag base (unless overridden) then selected options */
570
- services?: DgpServiceCapability[];
571
- };
572
- type VisibleGroupResult = {
573
- kind: "single";
574
- group: VisibleGroup;
575
- } | {
576
- kind: "multi";
577
- groups: string[];
578
- };
579
- type ChangeEvt = {
580
- ids: string[];
581
- primary?: string;
582
- };
583
- type Listener = (e: ChangeEvt) => void;
584
- type SelectionOptions = {
585
- env?: Env;
586
- rootTagId?: string;
587
- /** Resolve service capability from an id (used for `services` array) */
588
- resolveService?: (id: any) => DgpServiceCapability | undefined;
589
- };
590
- declare class Selection {
591
- private readonly builder;
592
- private readonly opts;
593
- private set;
594
- private primaryId;
595
- private currentTagId;
596
- private onChangeFns;
597
- constructor(builder: Builder, opts: SelectionOptions);
598
- replace(id?: string | null): void;
599
- add(id: string): void;
600
- remove(id: string): void;
601
- toggle(id: string): void;
602
- many(ids: Iterable<string>, primary?: string): void;
603
- clear(): void;
604
- all(): ReadonlySet<string>;
605
- has(id: string): boolean;
606
- primary(): string | undefined;
607
- currentTag(): string | undefined;
608
- onChange(fn: Listener): () => void;
609
- visibleGroup(): VisibleGroupResult;
610
- private emit;
611
- private updateCurrentTagFrom;
612
- private resolveTagContextId;
613
- private selectedButtonTriggerIds;
614
- private computeGroupForTag;
615
- private addServiceByRole;
616
- private findOptionById;
617
- }
618
-
619
- type EditorEvents = {
620
- "editor:command": {
621
- name: string;
622
- payload?: any;
623
- };
624
- "editor:change": {
625
- props: ServiceProps;
626
- reason: string;
627
- command?: string;
628
- };
629
- "editor:undo": {
630
- stackSize: number;
631
- index: number;
632
- };
633
- "editor:redo": {
634
- stackSize: number;
635
- index: number;
636
- };
637
- "editor:error": {
638
- message: string;
639
- code?: string;
640
- meta?: any;
641
- };
642
- };
643
- type Command = {
644
- name: string;
645
- do(): void;
646
- undo(): void;
647
- };
648
- type EditorOptions = {
649
- historyLimit?: number;
650
- validateAfterEach?: boolean;
651
- /** Sync existence check; return true if the service exists. */
652
- serviceExists?: (id: number) => boolean;
653
- /** Optional local index; used if serviceExists is not provided. */
654
- serviceMap?: Record<number, unknown>;
655
- /** Raw policies JSON; will be compiled on demand by filterServicesForVisibleGroup. */
656
- policiesRaw?: unknown;
657
- selectionProps?: SelectionOptions;
658
- };
659
- type ConnectKind = "bind" | "include" | "exclude";
660
-
661
631
  interface ButtonValue {
662
632
  id: string;
663
633
  value: string | number;
@@ -720,6 +690,7 @@ type OrderSnapshot = {
720
690
  builtAt: string;
721
691
  selection: {
722
692
  tag: string;
693
+ buttons: string[];
723
694
  fields: Array<{
724
695
  id: string;
725
696
  type: string;
@@ -737,6 +708,8 @@ type OrderSnapshot = {
737
708
  rule?: QuantityRule$1;
738
709
  defaultedFromHost?: boolean;
739
710
  };
711
+ min: number;
712
+ max: number;
740
713
  services: Array<string | number>;
741
714
  serviceMap: Record<string, Array<string | number>>;
742
715
  fallbacks?: {
@@ -761,6 +734,130 @@ type OrderSnapshot = {
761
734
  };
762
735
  };
763
736
 
737
+ type Env = "client" | "workspace";
738
+ type VisibleGroup = {
739
+ tagId?: string;
740
+ tag?: Tag;
741
+ fields: Field[];
742
+ fieldIds: string[];
743
+ parentTags?: Tag[];
744
+ childrenTags?: Tag[];
745
+ /** In order of selection: tag base (unless overridden) then selected options */
746
+ services?: DgpServiceCapability[];
747
+ };
748
+ type VisibleGroupResult = {
749
+ kind: "single";
750
+ group: VisibleGroup;
751
+ } | {
752
+ kind: "multi";
753
+ groups: string[];
754
+ };
755
+ type ChangeEvt = {
756
+ ids: string[];
757
+ primary?: string;
758
+ };
759
+ type Listener = (e: ChangeEvt) => void;
760
+ type SelectionOptions = {
761
+ env?: Env;
762
+ rootTagId?: string;
763
+ /** Resolve service capability from an id (used for `services` array) */
764
+ resolveService?: (id: any) => DgpServiceCapability | undefined;
765
+ };
766
+ declare class Selection {
767
+ private readonly builder;
768
+ private readonly opts;
769
+ private set;
770
+ private primaryId;
771
+ private currentTagId;
772
+ private onChangeFns;
773
+ constructor(builder: Builder, opts: SelectionOptions);
774
+ replace(id?: string | null): void;
775
+ add(id: string): void;
776
+ remove(id: string): void;
777
+ toggle(id: string): void;
778
+ many(ids: Iterable<string>, primary?: string): void;
779
+ clear(): void;
780
+ all(): ReadonlySet<string>;
781
+ has(id: string): boolean;
782
+ primary(): string | undefined;
783
+ currentTag(): string | undefined;
784
+ onChange(fn: Listener): () => void;
785
+ visibleGroup(): VisibleGroupResult;
786
+ /**
787
+ * Build a fieldId -> triggerKeys[] map from the current selection set.
788
+ *
789
+ * What counts as a "button selection" (trigger key):
790
+ * - field key where the field has button === true (e.g. "f:dripfeed")
791
+ * - option key (e.g. "o:fast")
792
+ * - composite key "fieldId::optionId" (e.g. "f:speed::o:fast")
793
+ *
794
+ * Grouping:
795
+ * - button-field trigger groups under its own fieldId
796
+ * - option/composite groups under the option's owning fieldId (from nodeMap)
797
+ *
798
+ * Deterministic:
799
+ * - preserves selection insertion order
800
+ * - de-dupes per field
801
+ */
802
+ buttonSelectionsByFieldId(): Record<string, string[]>;
803
+ /**
804
+ * Returns only selection keys that are valid "trigger buttons":
805
+ * - field keys where field.button === true
806
+ * - option keys
807
+ * - composite keys "fieldId::optionId" (validated by optionId)
808
+ * Excludes tags and non-button fields.
809
+ */
810
+ selectedButtons(): string[];
811
+ private emit;
812
+ private updateCurrentTagFrom;
813
+ private resolveTagContextId;
814
+ private computeGroupForTag;
815
+ private addServiceByRole;
816
+ private findOptionById;
817
+ }
818
+
819
+ type EditorEvents = {
820
+ "editor:command": {
821
+ name: string;
822
+ payload?: any;
823
+ };
824
+ "editor:change": {
825
+ props: ServiceProps;
826
+ reason: string;
827
+ command?: string;
828
+ };
829
+ "editor:undo": {
830
+ stackSize: number;
831
+ index: number;
832
+ };
833
+ "editor:redo": {
834
+ stackSize: number;
835
+ index: number;
836
+ };
837
+ "editor:error": {
838
+ message: string;
839
+ code?: string;
840
+ meta?: any;
841
+ };
842
+ };
843
+ type Command = {
844
+ name: string;
845
+ do(): void;
846
+ undo(): void;
847
+ };
848
+ type EditorOptions = {
849
+ historyLimit?: number;
850
+ validateAfterEach?: boolean;
851
+ /** Sync existence check; return true if the service exists. */
852
+ serviceExists?: (id: number) => boolean;
853
+ /** Optional local index; used if serviceExists is not provided. */
854
+ serviceMap?: Record<number, unknown>;
855
+ /** Raw policies JSON; will be compiled on demand by filterServicesForVisibleGroup. */
856
+ policiesRaw?: unknown;
857
+ selectionProps?: SelectionOptions;
858
+ };
859
+ type ConnectKind = "bind" | "include" | "exclude";
860
+
764
861
  /** Exported alias so the schema generator can target an array */
765
862
  type AdminPolicies = DynamicRule[];
766
863
 
@@ -1242,6 +1339,9 @@ declare class Editor {
1242
1339
  private stagedBefore?;
1243
1340
  private _lastPolicyDiagnostics?;
1244
1341
  constructor(builder: Builder, api: CanvasAPI, opts?: EditorOptions);
1342
+ isTagId(id: string): boolean;
1343
+ isFieldId(id: string): boolean;
1344
+ isOptionId(id: string): boolean;
1245
1345
  getProps(): ServiceProps;
1246
1346
  transact(label: string, fn: () => void): void;
1247
1347
  exec(cmd: Command): void;
@@ -1470,60 +1570,79 @@ declare class CanvasAPI {
1470
1570
  getServiceProps(): ServiceProps;
1471
1571
  }
1472
1572
 
1473
- type FormSnapshot = {
1474
- values: Record<string, Scalar | Scalar[]>;
1475
- selections: Record<string, string[]>;
1476
- };
1573
+ type Dict = Record<string, unknown>;
1574
+ type FormSnapshot = Dict;
1477
1575
  type FormApi = {
1478
- /** Scalar/array value by fieldId (non-option inputs) */
1479
- get: (fieldId: string) => Scalar | Scalar[] | undefined;
1480
- set: (fieldId: string, value: Scalar | Scalar[]) => void;
1481
- /** Option selections by fieldId (array of optionIds) */
1576
+ /** Value by fieldId (Wrapper uses name=field.id) */
1577
+ get: (fieldId: string) => unknown;
1578
+ /**
1579
+ * Programmatic set (NOT used by Wrapper).
1580
+ * If the field is mounted, writes into the core.
1581
+ * If not mounted, persists into core.bucket (via core.setValue) or local bag fallback.
1582
+ */
1583
+ set: (fieldId: string, value: unknown) => void;
1584
+ /** Option selections (legacy; kept for compatibility) */
1482
1585
  getSelections: (fieldId: string) => string[];
1483
1586
  setSelections: (fieldId: string, optionIds: string[]) => void;
1484
1587
  toggleSelection: (fieldId: string, optionId: string) => void;
1485
- /** Read-only snapshot for debugging */
1588
+ removeSelectionToken(token: string): void;
1589
+ /** Read-only snapshot for debugging (NO validation) */
1486
1590
  snapshot: () => FormSnapshot;
1487
1591
  /** Simple subscribe (re-render triggers) */
1488
1592
  subscribe: (fn: () => void) => () => void;
1593
+ /**
1594
+ * Validation gate:
1595
+ * local submit runs validation and returns mounted/visible values.
1596
+ * (This is NOT “submitting to a server”.)
1597
+ */
1598
+ submit: () => {
1599
+ values: Dict;
1600
+ valid: boolean;
1601
+ };
1489
1602
  };
1490
- declare function FormProvider({ initial, children, }: {
1491
- initial?: Partial<FormSnapshot>;
1492
- children: ReactNode;
1493
- }): react_jsx_runtime.JSX.Element;
1494
- /** Strict hook (throws if no provider) */
1495
1603
  declare function useFormApi(): FormApi;
1496
- /** Optional hook (returns null if no provider) */
1497
1604
  declare function useOptionalFormApi(): FormApi | null;
1498
- /** Field-scoped helpers */
1499
- declare function useFormField(fieldId: string): {
1500
- value: Scalar | Scalar[] | undefined;
1501
- set: (value: Scalar | Scalar[]) => void;
1502
- };
1503
- declare function useFormSelections(fieldId: string): {
1504
- selected: string[];
1505
- set: (optionIds: string[]) => void;
1506
- toggle: (optionId: string) => void;
1605
+ type FormProviderProps = {
1606
+ children: ReactNode;
1607
+ /** Optional schema (zod/jsonschema/etc, depending on your palette build) */
1608
+ schema?: any;
1609
+ /**
1610
+ * Same shape as the old OrderFlowProvider usage.
1611
+ * - values: seed values (persisted/rehydrated)
1612
+ * - selections: legacy (kept for compatibility)
1613
+ */
1614
+ initial?: {
1615
+ values?: Dict;
1616
+ selections?: Record<string, string[]>;
1617
+ };
1507
1618
  };
1619
+ declare function FormProvider({ children, schema, initial }: FormProviderProps): react_jsx_runtime.JSX.Element;
1508
1620
 
1509
1621
  /** Matches your InputWrapper’s expectations */
1510
1622
  type InputKind = string;
1511
- type InputVariant = 'default' | (string & {});
1512
- type InputAdapter = {
1513
- /** Prop name where the value goes on the host component (default: "value") */
1623
+ type InputVariant = "default" | (string & {});
1624
+ type AdapterCtx = {
1625
+ field: Field;
1626
+ props: ServiceProps;
1627
+ };
1628
+ type Adapter = {
1514
1629
  valueProp?: string;
1515
- /** Prop name of the change handler on the host component (default: "onChange") */
1516
1630
  changeProp?: string;
1517
- /**
1518
- * Normalize the host's change payload into a Scalar | Scalar[] your form will store.
1519
- * If omitted, `next as Scalar | Scalar[]` is used.
1520
- */
1521
- getValue?: (next: unknown, prev: unknown) => Scalar | Scalar[];
1631
+ errorProp?: string;
1632
+ /** normalize what the host emitted into what we store in form-palette */
1633
+ getValue?: (next: unknown, current: unknown, ctx: AdapterCtx) => unknown;
1634
+ /** REQUIRED if field.options exists */
1635
+ getSelectedOptions?: (next: unknown, current: unknown, ctx: AdapterCtx) => string[];
1636
+ /** For option-less action buttons (button: true with no options) */
1637
+ isActive?: (stored: unknown, ctx: AdapterCtx) => boolean;
1638
+ getInputPropsFromField?: (props: AdapterCtx) => any;
1639
+ toValue?: (value: any) => any;
1522
1640
  };
1523
1641
  type InputDescriptor = {
1524
1642
  Component: React.ComponentType<Record<string, unknown>>;
1525
- adapter?: InputAdapter;
1643
+ adapter?: Adapter;
1526
1644
  defaultProps?: Record<string, unknown>;
1645
+ ui?: Record<string, Ui>;
1527
1646
  };
1528
1647
  type VariantMap = Map<InputVariant, InputDescriptor>;
1529
1648
  type RegistryStore = Map<InputKind, VariantMap>;
@@ -1563,10 +1682,174 @@ declare function useInputs(): InputsCtxValue;
1563
1682
  type InputWrapperProps = {
1564
1683
  field: Field;
1565
1684
  disabled?: boolean;
1566
- /** Extra props to forward to the host component (low priority, overridden by adapter wiring). */
1567
1685
  extraProps?: Record<string, unknown>;
1686
+ templateStrings?: boolean;
1687
+ ctxOverrides?: Record<string, unknown>;
1688
+ className?: string;
1689
+ };
1690
+ declare function Wrapper({ field, disabled, extraProps, templateStrings, ctxOverrides, className, }: InputWrapperProps): react_jsx_runtime.JSX.Element | null;
1691
+
1692
+ type OrderFlowInit = {
1693
+ mode?: "prod" | "dev";
1694
+ /** required service map used for snapshot building / rules */
1695
+ services: DgpServiceMap;
1696
+ /** fallback policy overrides */
1697
+ fallback?: FallbackSettings;
1698
+ /** hydrate initial state from snapshot */
1699
+ hydrateFrom?: OrderSnapshot;
1700
+ /** initial tag (ignored if hydrateFrom exists and provides tag) */
1701
+ initialTagId?: string;
1702
+ /** default quantity used by snapshot builder (default 1) */
1703
+ hostDefaultQuantity?: number;
1704
+ /** selection resolver (optional) */
1705
+ resolveService?: (id: number | string) => DgpServiceCapability | undefined;
1706
+ /**
1707
+ * Host props provided to further enhance the nodes data
1708
+ */
1709
+ ctx?: Record<string, unknown>;
1710
+ normalizeRate?(svc: DgpServiceCapability): number;
1711
+ };
1712
+ type ProviderFlow = {
1713
+ builder: Builder;
1714
+ selection?: Selection;
1568
1715
  };
1569
- type OnChangeValue = ButtonValue | ButtonValue[];
1570
- declare function Wrapper({ field, disabled, extraProps, }: InputWrapperProps): react_jsx_runtime.JSX.Element | null;
1716
+ type OrderFlowProviderProps = {
1717
+ /**
1718
+ * Optional at mount time.
1719
+ * If absent, call initialize(...) later (via ref OR hook API).
1720
+ */
1721
+ serviceProps?: ServiceProps;
1722
+ builder?: Builder;
1723
+ flow?: ProviderFlow;
1724
+ builderOptions?: BuilderOptions;
1725
+ /** optional selection override (if not passed in flow) */
1726
+ selection?: Selection;
1727
+ /** Host input registry (maps kind/variant → components) */
1728
+ registry?: Registry;
1729
+ /** Optional now (deferred init supported). */
1730
+ init?: OrderFlowInit;
1731
+ children?: ReactNode;
1732
+ };
1733
+ type OrderFlowInitializeParams = {
1734
+ serviceProps?: ServiceProps;
1735
+ builder?: Builder;
1736
+ flow?: ProviderFlow;
1737
+ builderOptions?: BuilderOptions;
1738
+ selection?: Selection;
1739
+ init: OrderFlowInit;
1740
+ };
1741
+ type OrderFlowHandle = {
1742
+ /** whether provider has enough info to run */
1743
+ ready: () => boolean;
1744
+ /** (re)initialize the provider */
1745
+ initialize: (params: OrderFlowInitializeParams) => void;
1746
+ getActiveTag: () => string | undefined;
1747
+ selectTag: (tagId: string) => void;
1748
+ getVisibleGroup: () => ReturnType<Selection["visibleGroup"]>;
1749
+ getSelectionIds: () => string[];
1750
+ clearSelection: () => void;
1751
+ /** Apply snapshot into selection + form values/selections */
1752
+ setSnapshot: (snap: OrderSnapshot, opts?: {
1753
+ clearFirst?: boolean;
1754
+ }) => void;
1755
+ /** Reset tag + clear fields */
1756
+ reset: (opts?: {
1757
+ keepTag?: boolean;
1758
+ }) => void;
1759
+ refresh: () => void;
1760
+ };
1761
+ type NormalizedInit = Required<Pick<OrderFlowInit, "mode" | "hostDefaultQuantity">> & OrderFlowInit;
1762
+ type EnsureReadyResult = {
1763
+ builder: Builder;
1764
+ selection: Selection;
1765
+ init: NormalizedInit;
1766
+ };
1767
+ type CtxShape = {
1768
+ builder: Builder | null;
1769
+ selection: Selection | null;
1770
+ activeTagId?: string;
1771
+ setActiveTag: (id: string) => void;
1772
+ init: NormalizedInit | null;
1773
+ /** Form API from FormProvider (always available) */
1774
+ formApi: ReturnType<typeof useFormApi>;
1775
+ /** fallback policy (owned here; used by hook) */
1776
+ fallbackPolicy: FallbackSettings;
1777
+ setFallbackPolicy: (next: FallbackSettings) => void;
1778
+ /** imperative helpers exposed to hook */
1779
+ setSnapshot: (snap: OrderSnapshot, opts?: {
1780
+ clearFirst?: boolean;
1781
+ }) => void;
1782
+ reset: (opts?: {
1783
+ keepTag?: boolean;
1784
+ }) => void;
1785
+ /** guards */
1786
+ ready: () => boolean;
1787
+ ensureReady: (op?: string) => EnsureReadyResult;
1788
+ /** init API */
1789
+ initialize: (params: OrderFlowInitializeParams) => void;
1790
+ };
1791
+ declare function useOrderFlowContext(): CtxShape;
1792
+ declare const OrderFlowProvider: React.ForwardRefExoticComponent<OrderFlowProviderProps & React.RefAttributes<OrderFlowHandle>>;
1793
+
1794
+ type PricingPreview = {
1795
+ serviceId?: string | number;
1796
+ unitRate: number;
1797
+ base: number;
1798
+ utilities: number;
1799
+ total: number;
1800
+ utilityBreakdown: Array<{
1801
+ nodeId: string;
1802
+ mode: string;
1803
+ amount: number;
1804
+ }>;
1805
+ };
1806
+ type UseOrderFlowReturn = {
1807
+ ready: boolean;
1808
+ initialize: (params: OrderFlowInitializeParams) => void;
1809
+ activeTagId?: string;
1810
+ /** raw service props */
1811
+ raw: ServiceProps;
1812
+ /** visibility is Selection-only */
1813
+ visibleGroup: VisibleGroup | null;
1814
+ /**
1815
+ * Values are from form-palette (values()) and are already "visible-only"
1816
+ * because your UI mounts only visible fields.
1817
+ */
1818
+ formValuesByFieldId: Record<string, Scalar | Scalar[]>;
1819
+ /**
1820
+ * Selections are Selection-only now.
1821
+ * We keep this for compatibility with buildOrderSnapshot signature,
1822
+ * but we do NOT read it from form anymore.
1823
+ */
1824
+ optionSelectionsByFieldId: Record<string, string[]>;
1825
+ quantityPreview: number;
1826
+ services: Array<string | number>;
1827
+ serviceMap: Record<string, Array<string | number>>;
1828
+ pricingPreview: PricingPreview;
1829
+ min: number;
1830
+ max: number;
1831
+ selectTag: (tagId: string) => void;
1832
+ toggleOption: (fieldId: string, optionId?: string) => void;
1833
+ /** programmatic value set (rare; wrapper/field hook should handle most) */
1834
+ setValue: (fieldId: string, value: Scalar | Scalar[]) => void;
1835
+ clearField: (fieldId: string) => void;
1836
+ reset: (opts?: {
1837
+ keepTag?: boolean;
1838
+ }) => void;
1839
+ setSnapshot: (snap: OrderSnapshot, opts?: {
1840
+ clearFirst?: boolean;
1841
+ }) => void;
1842
+ /** VALIDATES via form.submit() */
1843
+ buildSnapshot: () => OrderSnapshot | undefined;
1844
+ fallbackPolicy: FallbackSettings;
1845
+ setFallbackPolicy: (next: FallbackSettings) => void;
1846
+ };
1847
+ declare function useOrderFlow(): UseOrderFlowReturn;
1848
+
1849
+ /**
1850
+ * Register all built-in entries.
1851
+ * - You said "variant is the only thing necessary", so we treat kind as a constant.
1852
+ */
1853
+ declare function registerEntries(registry: Registry): void;
1571
1854
 
1572
- export { type AdminPolicies, type BaseFieldUI, type ButtonValue, CanvasAPI, type CanvasEvents, type CanvasOptions, type CanvasState, type Command, type CommentAnchor, type CommentId, type CommentMessage, type CommentNode, type CommentThread, type ConnectKind, type ConstraintKey, type DgpServiceCapability, type DgpServiceMap, type DraftWire, type DynamicRule, type EdgeKind, type EdgeRoute, type EdgeView, type EditorEvents, type EditorOptions, type EditorSnapshot, EventBus, type EventMap, type FallbackDiagnostics, type FallbackSettings, type Field, type FieldOption, type FieldType, type FieldWithTypedDefaults, type FlagKey, type FlowNode, type FormApi, FormProvider, type FormSnapshot, type GraphEdge, type GraphNode, type GraphSnapshot, type IdType, type InputAdapter, type InputDescriptor, type InputKind, type InputVariant, type InputWrapperProps, type LayoutState, type NodeIdRef, type NodeKind, type NodePos, type NodePositions, type NodeView, type OnChangeValue, type OrderSnapshot, type PricingRole, Provider, type QuantityMark, type QuantityRule$1 as QuantityRule, type RatePolicy, type Registry, type Scalar, type ServiceEstimates, type ServiceFallback, type ServiceFallbacks, type ServiceFlag, type ServiceFlags, type ServiceIdRef, type ServiceProps, type ServiceWhereClause, type ServiceWhereOp, type SnapshotContext, type SpeedEstimate, type Tag, type ThreadId, type TimeRangeEstimate, type Ui, type UiAnyOf, type UiArray, type UiBoolean, type UiNumber, type UiObject, type UiString, type UiValue, type UtilityLineItem, type UtilityMark, type UtilityMode, type ValidationCode, type ValidationError, type ValidatorOptions, type Viewport, type WithQuantityDefault, Wrapper, createInputRegistry, resolveInputDescriptor, useFormApi, useFormField, useFormSelections, useInputs, useOptionalFormApi };
1855
+ export { type Adapter, type AdapterCtx, type AdminPolicies, type BaseFieldUI, type ButtonValue, CanvasAPI, type CanvasEvents, type CanvasOptions, type CanvasState, type Command, type CommentAnchor, type CommentId, type CommentMessage, type CommentNode, type CommentThread, type ConnectKind, type ConstraintKey, type DgpServiceCapability, type DgpServiceMap, type DraftWire, type DynamicRule, type EdgeKind, type EdgeRoute, type EdgeView, type EditorEvents, type EditorOptions, type EditorSnapshot, EventBus, type EventMap, type FallbackDiagnostics, type FallbackSettings, type Field, type FieldOption, type FieldType, type FieldWithTypedDefaults, type FlagKey, type FlowNode, type FormApi, FormProvider, type FormProviderProps, type FormSnapshot, type GraphEdge, type GraphNode, type GraphSnapshot, type IdType, type InputDescriptor, type InputKind, type InputVariant, type InputWrapperProps, type LayoutState, type NodeIdRef, type NodeKind, type NodePos, type NodePositions, type NodeView, type NoticeKind, type NoticeSeverity, type NoticeTarget, type NoticeType, OrderFlowProvider, type OrderSnapshot, type PricingRole, Provider, type QuantityMark, type QuantityRule$1 as QuantityRule, type RatePolicy, type Registry, type Scalar, type ServiceEstimates, type ServiceFallback, type ServiceFallbacks, type ServiceFlag, type ServiceFlags, type ServiceIdRef, type ServiceProps, type ServicePropsNotice, type ServiceWhereClause, type ServiceWhereOp, type SnapshotContext, type SpeedEstimate, type Tag, type ThreadId, type TimeRangeEstimate, type Ui, type UiAnyOf, type UiArray, type UiBoolean, type UiNumber, type UiObject, type UiString, type UiValue, type UtilityLineItem, type UtilityMark, type UtilityMode, type ValidationCode, type ValidationError, type ValidatorOptions, type Viewport, type WithQuantityDefault, Wrapper, createInputRegistry, registerEntries, resolveInputDescriptor, useFormApi, useInputs, useOptionalFormApi, useOrderFlow, useOrderFlowContext };