@verifiedinc-public/shared-ui-elements 12.16.0 → 12.18.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.
Files changed (54) hide show
  1. package/dist/components/NetworkRules/dialog/NetworkRulePresetDeleteDialog.d.ts +16 -0
  2. package/dist/components/NetworkRules/dialog/NetworkRulePresetDeleteDialog.mjs +1 -0
  3. package/dist/components/NetworkRules/dialog/NetworkRulePresetEditDialog.d.ts +34 -0
  4. package/dist/components/NetworkRules/dialog/NetworkRulePresetEditDialog.mjs +1 -0
  5. package/dist/components/NetworkRules/dialog/index.d.ts +2 -0
  6. package/dist/components/NetworkRules/editor/NetworkRuleEditorForm.d.ts +7 -1
  7. package/dist/components/NetworkRules/editor/NetworkRuleEditorForm.mjs +1 -1
  8. package/dist/components/NetworkRules/editor/fields/ConditionRow.d.ts +3 -1
  9. package/dist/components/NetworkRules/editor/fields/ConditionRow.mjs +1 -1
  10. package/dist/components/NetworkRules/editor/fields/ConditionValuesInput.d.ts +3 -1
  11. package/dist/components/NetworkRules/editor/fields/ConditionValuesInput.mjs +1 -1
  12. package/dist/components/NetworkRules/editor/fields/ConditionsField.d.ts +3 -1
  13. package/dist/components/NetworkRules/editor/fields/ConditionsField.mjs +1 -1
  14. package/dist/components/NetworkRules/editor/fields/MetadataField.d.ts +3 -1
  15. package/dist/components/NetworkRules/editor/fields/MetadataField.mjs +1 -1
  16. package/dist/components/NetworkRules/editor/fields/MetadataRow.d.ts +3 -1
  17. package/dist/components/NetworkRules/editor/fields/MetadataRow.mjs +1 -1
  18. package/dist/components/NetworkRules/editor/fields/NotesField.d.ts +4 -1
  19. package/dist/components/NetworkRules/editor/fields/NotesField.mjs +1 -1
  20. package/dist/components/NetworkRules/editor/fields/PresetOptionRow.d.ts +18 -0
  21. package/dist/components/NetworkRules/editor/fields/PresetOptionRow.mjs +1 -0
  22. package/dist/components/NetworkRules/editor/fields/PresetTextInput.d.ts +4 -1
  23. package/dist/components/NetworkRules/editor/fields/PresetTextInput.mjs +1 -1
  24. package/dist/components/NetworkRules/editor/fields/presetOptions.d.ts +4 -1
  25. package/dist/components/NetworkRules/editor/fields/presetOptions.mjs +1 -1
  26. package/dist/components/NetworkRules/editor/fields/values/TextValuesInput.d.ts +4 -1
  27. package/dist/components/NetworkRules/editor/fields/values/TextValuesInput.mjs +1 -1
  28. package/dist/components/NetworkRules/editor/useNetworkRulePresetManager.d.ts +27 -0
  29. package/dist/components/NetworkRules/editor/useNetworkRulePresetManager.mjs +1 -0
  30. package/dist/components/NetworkRules/hooks/index.d.ts +2 -0
  31. package/dist/components/NetworkRules/hooks/useRenameNetworkRulePreset.d.ts +8 -0
  32. package/dist/components/NetworkRules/hooks/useRenameNetworkRulePreset.mjs +1 -0
  33. package/dist/components/NetworkRules/hooks/useUpdateNetworkRulesPresets.d.ts +7 -0
  34. package/dist/components/NetworkRules/hooks/useUpdateNetworkRulesPresets.mjs +1 -0
  35. package/dist/components/NetworkRules/index.mjs +1 -1
  36. package/dist/components/NetworkRules/types.d.ts +31 -6
  37. package/dist/components/NetworkRules/utils/catalog.d.ts +7 -0
  38. package/dist/components/NetworkRules/utils/catalog.mjs +1 -1
  39. package/dist/components/NetworkRules/utils/index.d.ts +1 -0
  40. package/dist/components/NetworkRules/utils/presets.d.ts +28 -0
  41. package/dist/components/NetworkRules/utils/presets.mjs +1 -0
  42. package/dist/components/form/AddressInput/index.mjs +1 -1
  43. package/dist/components/form/NewOneClickForm/core/fields/employer.d.ts +5 -0
  44. package/dist/components/form/NewOneClickForm/core/fields/index.d.ts +5 -0
  45. package/dist/components/form/NewOneClickForm/core/validations/employer/employer.schema.d.ts +5 -0
  46. package/dist/components/form/NewOneClickForm/core/validations/employer/employer.schema.mjs +1 -1
  47. package/dist/components/form/NewOneClickForm/react/ui/fields/input/employer.field.mjs +1 -1
  48. package/dist/components/form/NewOneClickForm/react/ui/fields/readonly/employer.field.mjs +1 -1
  49. package/dist/components/form/NewOneClickForm/react/ui/fields/readonly/healthInsurance.field.mjs +1 -1
  50. package/dist/components/form/NewOneClickForm/react/ui/fields/shared.d.ts +2 -0
  51. package/dist/components/index.mjs +1 -1
  52. package/dist/index.mjs +1 -1
  53. package/dist/styles/theme.mjs +1 -1
  54. package/package.json +1 -1
@@ -0,0 +1,16 @@
1
+ export interface NetworkRulePresetDeleteDialogProps {
2
+ open: boolean;
3
+ /** The preset about to go. */
4
+ value?: string;
5
+ onConfirm: (value: string) => void | Promise<void>;
6
+ onClose: () => void;
7
+ isDeleting?: boolean;
8
+ /** Why the last attempt failed, e.g. the server refused the list. */
9
+ error?: string;
10
+ title?: string;
11
+ description?: string;
12
+ confirmLabel?: string;
13
+ cancelLabel?: string;
14
+ }
15
+ /** Removes one preset from a field's suggestions. Rules that carry the text keep it. */
16
+ export declare function NetworkRulePresetDeleteDialog({ open, value: valueProp, onConfirm, onClose, isDeleting, error, title, description, confirmLabel, cancelLabel, }: Readonly<NetworkRulePresetDeleteDialogProps>): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use strict";import{Dialog as C,DialogTitle as D,DialogContent as v,DialogContentText as f,Alert as p,DialogActions as x,Button as s,CircularProgress as b}from"@mui/material";import{useHeldWhileClosed as k}from"../hooks/useHeldWhileClosed.mjs";import{jsxs as i,jsx as e}from"react/jsx-runtime";function w({open:r,value:a,onConfirm:d,onClose:t,isDeleting:l=!1,error:n,title:c="Delete Preset?",description:h,confirmLabel:g="Delete",cancelLabel:u="Cancel"}){const o=k(r,a),m=h??(o===void 0?void 0:`"${o}" will no longer be suggested. Rules that already use it are not changed.`);return i(C,{open:r,onClose:l?void 0:t,maxWidth:"xs",fullWidth:!0,children:[e(D,{children:c}),i(v,{children:[e(f,{children:m}),n&&e(p,{severity:"error",sx:{mt:2},children:n})]}),i(x,{children:[e(s,{color:"neutral",onClick:t,disabled:l,children:u}),e(s,{color:"error",variant:"contained",disabled:l||o===void 0,startIcon:l?e(b,{size:16,color:"inherit"}):void 0,onClick:()=>{o!==void 0&&d(o)},children:g})]})]})}export{w as NetworkRulePresetDeleteDialog};
@@ -0,0 +1,34 @@
1
+ export interface NetworkRulePresetEditOptions {
2
+ /** The user ticked "Edit existing rules that use this preset". */
3
+ updateRules: boolean;
4
+ }
5
+ export interface NetworkRulePresetEditDialogProps {
6
+ open: boolean;
7
+ /** The preset as it is stored. */
8
+ value?: string;
9
+ /** Every preset of the same field, for the uniqueness check; `value` itself is allowed. */
10
+ presets?: readonly string[];
11
+ maxLength?: number;
12
+ /**
13
+ * Offer to change the rules that carry the preset as well. Off, the dialog says instead that
14
+ * rules are left alone.
15
+ */
16
+ canUpdateRules?: boolean;
17
+ /** Called with the trimmed new text. Not called when the text did not change. */
18
+ onSave: (value: string, options: NetworkRulePresetEditOptions) => void | Promise<void>;
19
+ onClose: () => void;
20
+ isSaving?: boolean;
21
+ /** Why the last save failed, e.g. the server refused the list. */
22
+ error?: string;
23
+ title?: string;
24
+ /** Shown when `canUpdateRules` is off. */
25
+ description?: string;
26
+ updateRulesLabel?: string;
27
+ saveLabel?: string;
28
+ cancelLabel?: string;
29
+ }
30
+ /**
31
+ * Renames one preset. Presets are suggestions, so rules that carry the old text keep it unless
32
+ * the user asks for them to follow.
33
+ */
34
+ export declare function NetworkRulePresetEditDialog({ open, value: valueProp, presets, maxLength, canUpdateRules, onSave, onClose, isSaving, error, title, description, updateRulesLabel, saveLabel, cancelLabel, }: Readonly<NetworkRulePresetEditDialogProps>): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use strict";import{useState as c,useEffect as F}from"react";import{Dialog as T,DialogTitle as j,DialogContent as y,TextField as A,FormControlLabel as B,Checkbox as V,DialogContentText as q,Alert as w,DialogActions as z,Button as f,CircularProgress as H}from"@mui/material";import{useHeldWhileClosed as I}from"../hooks/useHeldWhileClosed.mjs";import{validatePresetValue as N}from"../utils/presets.mjs";import{jsx as e,jsxs as h}from"react/jsx-runtime";function U({open:r,value:s,presets:C=[],maxLength:p,canUpdateRules:m=!1,onSave:D,onClose:l,isSaving:t=!1,error:g,title:L="Edit Preset",description:P="Rules that already use this preset are not changed.",updateRulesLabel:R="Edit existing rules that use this preset",saveLabel:S="Save",cancelLabel:W="Cancel"}){const n=I(r,s??""),[o,v]=c(n),[d,u]=c(!1),[x,b]=c(!1);F(()=>{r&&(v(s??""),u(!1),b(!1))},[r,s]);const i=N(o,{presets:C,current:n,maxLength:p}),k=o.trim()===n;return e(T,{open:r,onClose:t?void 0:l,maxWidth:"xs",fullWidth:!0,children:h("form",{noValidate:!0,onSubmit:a=>{if(a.preventDefault(),a.stopPropagation(),u(!0),!(t||i)){if(k){l();return}D(o.trim(),{updateRules:m&&x})}},children:[e(j,{children:L}),h(y,{children:[e(A,{autoFocus:!0,fullWidth:!0,required:!0,label:"Preset",value:o,onChange:a=>{v(a.target.value)},onBlur:()=>{u(!0)},disabled:t,error:d&&i!==void 0,helperText:d?i:void 0,inputProps:{maxLength:p},sx:{mt:1}}),m?e(B,{sx:{mt:1},label:R,control:e(V,{checked:x,onChange:(a,E)=>{b(E)},disabled:t})}):e(q,{sx:{mt:2},children:P}),g&&e(w,{severity:"error",sx:{mt:2},children:g})]}),h(z,{children:[e(f,{color:"neutral",onClick:l,disabled:t,children:W}),e(f,{type:"submit",variant:"contained",disabled:t||d&&i!==void 0,startIcon:t?e(H,{size:16,color:"inherit"}):void 0,children:S})]})]})})}export{U as NetworkRulePresetEditDialog};
@@ -1,2 +1,4 @@
1
1
  export * from './NetworkRuleDeleteDialog';
2
2
  export * from './NetworkRuleDiscardDialog';
3
+ export * from './NetworkRulePresetDeleteDialog';
4
+ export * from './NetworkRulePresetEditDialog';
@@ -6,6 +6,12 @@ export interface NetworkRuleEditorFormProps {
6
6
  defaultName?: string;
7
7
  /** Offer "Add … as a preset" for a typed note or free-text value; the grown lists arrive with `onSubmit`. */
8
8
  canCreatePresets?: boolean;
9
+ /**
10
+ * Offer edit and delete controls on saved presets. Unlike a new preset, a change is written
11
+ * through `services.updatePresets` as soon as it is confirmed, so it needs that service; without
12
+ * it nothing shows. Defaults to `canCreatePresets`.
13
+ */
14
+ canManagePresets?: boolean;
9
15
  onSubmit: (rule: NetworkRuleData, extras: NetworkRuleSubmitExtras) => void | Promise<void>;
10
16
  onCancel?: () => void;
11
17
  isSubmitting?: boolean;
@@ -20,4 +26,4 @@ export interface NetworkRuleEditorFormProps {
20
26
  hideActions?: boolean;
21
27
  onDirtyChange?: (isDirty: boolean) => void;
22
28
  }
23
- export declare function NetworkRuleEditorForm({ rule, defaultName, canCreatePresets, onSubmit, onCancel, isSubmitting, serverErrors, focusConditionIndex, submitLabel, cancelLabel, disabled, id, hideActions, onDirtyChange, }: Readonly<NetworkRuleEditorFormProps>): import("react").JSX.Element;
29
+ export declare function NetworkRuleEditorForm({ rule, defaultName, canCreatePresets, canManagePresets, onSubmit, onCancel, isSubmitting, serverErrors, focusConditionIndex, submitLabel, cancelLabel, disabled, id, hideActions, onDirtyChange, }: Readonly<NetworkRuleEditorFormProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use strict";import{useState as V,useMemo as z,useEffect as k,useRef as Q}from"react";import{Stack as f,Alert as L,Button as w,TextField as ee,FormControlLabel as re,Switch as oe,CircularProgress as te,Skeleton as C}from"@mui/material";import{zodResolver as ae}from"@hookform/resolvers/zod";import{addDays as ne}from"date-fns";import{useForm as se,useWatch as ie,FormProvider as le,Controller as y}from"react-hook-form";import{useNetworkRuleStatuses as de}from"../NetworkRules.context.mjs";import{useNetworkRulesCatalog as ue}from"../hooks/useNetworkRulesCatalog.mjs";import{getPresets as M}from"../utils/catalog.mjs";import{fromNetworkRuleFormValues as ce,toNetworkRuleFormValues as me,emptyConditionFormValues as fe}from"../utils/condition.mjs";import{ruleDateToDay as he}from"../utils/date.mjs";import{ConditionsField as ve}from"./fields/ConditionsField.mjs";import{DateField as W}from"./fields/DateField.mjs";import{MetadataField as pe}from"./fields/MetadataField.mjs";import{NotesField as ge}from"./fields/NotesField.mjs";import{StatusField as be}from"./fields/StatusField.mjs";import{createNetworkRuleFormSchema as Ce}from"./schema.mjs";import{jsx as e,jsxs as h,Fragment as ye}from"react/jsx-runtime";function A(i,d){const n=me(i);return!(i!=null&&i.uuid)&&!n.name&&d&&(n.name=d),n.conditions.length===0&&(n.conditions=[fe()]),n}function Se(i,d){const n=[],p=[];for(const u of d){const c=u.message??u.code;if(typeof u.index=="number"){const v=`conditions.${u.index}.values`;i.setError(v,{type:"server",message:c}),p.push(v)}else n.push(c)}return n.length>0&&i.setError("root.server",{type:"server",message:n.join(" ")}),p}function xe(){return h(f,{spacing:2,"aria-busy":!0,children:[e(C,{variant:"rounded",height:56}),e(C,{variant:"rounded",height:56}),e(C,{variant:"rounded",height:56}),e(C,{variant:"rounded",height:120})]})}function Fe({rule:i,defaultName:d,canCreatePresets:n=!1,onSubmit:p,onCancel:u,isSubmitting:c=!1,serverErrors:v,focusConditionIndex:I,submitLabel:O="Save",cancelLabel:U="Cancel",disabled:$=!1,id:q,hideActions:G=!1,onDirtyChange:S}){var E,D;const g=ue(),s=g.data,H=de()??s?.statuses??[],b=i?.uuid??"new",[R,J]=V(b),K=z(()=>ae(Ce(s?.metadata)),[s]),t=se({defaultValues:A(i,d),resolver:K,mode:"onSubmit",reValidateMode:"onChange"}),[m,P]=V({});k(()=>{b!==R&&(t.reset(A(i,d)),P({}),J(b))},[t,i,d,b,R]);const x=Q([]);k(()=>{t.clearErrors("root.server"),x.current.length>0&&t.clearErrors(x.current),x.current=Se(t,v??[])},[t,v]);const{isDirty:N}=t.formState;k(()=>{S?.(N)},[N,S]);const l=$||c,T=(D=(E=t.formState.errors.root)==null?void 0:E.server)==null?void 0:D.message,X=ie({control:t.control,name:"startDate"}),B=he(X),Y=B?ne(B,1):void 0,Z=z(()=>M(s,"notes",m),[s,m]),F=(r,a)=>{P(o=>{const j=o[r]??[];return j.includes(a)?o:{...o,[r]:[...j,a]}})},_=t.handleSubmit(async r=>{if(s===void 0)return;const a=Object.fromEntries(Object.keys(m).map(o=>[o,M(s,o,m)]));await p(ce(r),{presets:a})});return e(le,{...t,children:e("form",{id:q,noValidate:!0,onSubmit:r=>{r.preventDefault(),r.stopPropagation(),_(r)},children:h(f,{spacing:3,children:[g.isError&&e(L,{severity:"error",action:e(w,{color:"inherit",size:"small",onClick:()=>{g.refetch()},children:"Retry"}),children:"The rule catalog could not be loaded."}),T&&e(L,{severity:"error",children:T}),s===void 0?!g.isError&&e(xe,{}):h(ye,{children:[h(f,{direction:{xs:"column",md:"row"},spacing:2,children:[e(y,{control:t.control,name:"name",render:({field:r,fieldState:a})=>{var o;return e(ee,{...r,label:"Rule Name",required:!0,fullWidth:!0,disabled:l,error:a.error!==void 0,helperText:(o=a.error)==null?void 0:o.message,sx:{flex:2}})}}),e(f,{flex:1,minWidth:{md:220},children:e(be,{statuses:H,disabled:l})})]}),h(f,{direction:{xs:"column",md:"row"},spacing:2,children:[e(y,{control:t.control,name:"startDate",render:({field:r,fieldState:a})=>{var o;return e(W,{label:"Starts",value:r.value,onChange:r.onChange,onBlur:r.onBlur,disabled:l,error:a.error!==void 0,helperText:((o=a.error)==null?void 0:o.message)??"Starts applying at the start of this day (UTC)"})}}),e(y,{control:t.control,name:"endDate",render:({field:r,fieldState:a})=>{var o;return e(W,{label:"Ends",value:r.value,onChange:r.onChange,onBlur:r.onBlur,disabled:l,minDate:Y,error:a.error!==void 0,helperText:((o=a.error)==null?void 0:o.message)??"Stops applying at the start of this day (UTC)"})}})]}),e(ge,{presets:Z,onCreatePreset:n?r=>{F("notes",r)}:void 0,disabled:l}),e(y,{control:t.control,name:"enabled",render:({field:r})=>e(re,{label:"Enabled",control:e(oe,{checked:r.value,onChange:(a,o)=>{r.onChange(o)},onBlur:r.onBlur,inputRef:r.ref,disabled:l})})}),e(ve,{catalog:s,addedPresets:m,onCreatePreset:n?F:void 0,disabled:l,focusIndex:I}),e(pe,{catalog:s,addedPresets:m,onCreatePreset:n?F:void 0,disabled:l})]}),!G&&h(f,{direction:"row",spacing:1,justifyContent:"flex-end",children:[u&&e(w,{onClick:u,disabled:c,children:U}),e(w,{type:"submit",variant:"contained",disabled:l||s===void 0,startIcon:c?e(te,{size:16,color:"inherit"}):void 0,children:O})]})]})})})}export{Fe as NetworkRuleEditorForm};
1
+ "use strict";import{useState as A,useMemo as I,useEffect as w,useRef as te}from"react";import{Stack as p,Alert as L,Button as F,TextField as oe,FormControlLabel as ae,Switch as se,CircularProgress as ne,Skeleton as C}from"@mui/material";import{zodResolver as ie}from"@hookform/resolvers/zod";import{addDays as le}from"date-fns";import{useForm as de,useWatch as ue,FormProvider as ce,Controller as D}from"react-hook-form";import{useNetworkRuleStatuses as me}from"../NetworkRules.context.mjs";import{NetworkRulePresetDeleteDialog as fe}from"../dialog/NetworkRulePresetDeleteDialog.mjs";import{NetworkRulePresetEditDialog as he}from"../dialog/NetworkRulePresetEditDialog.mjs";import{useNetworkRulesCatalog as pe}from"../hooks/useNetworkRulesCatalog.mjs";import{getPresets as W}from"../utils/catalog.mjs";import{fromNetworkRuleFormValues as ve,toNetworkRuleFormValues as ge,emptyConditionFormValues as be}from"../utils/condition.mjs";import{ruleDateToDay as Pe}from"../utils/date.mjs";import{ConditionsField as Ce}from"./fields/ConditionsField.mjs";import{DateField as O}from"./fields/DateField.mjs";import{MetadataField as De}from"./fields/MetadataField.mjs";import{NotesField as ye}from"./fields/NotesField.mjs";import{StatusField as Ee}from"./fields/StatusField.mjs";import{createNetworkRuleFormSchema as Se}from"./schema.mjs";import{useNetworkRulePresetManager as xe}from"./useNetworkRulePresetManager.mjs";import{jsxs as m,jsx as e,Fragment as ke}from"react/jsx-runtime";function H(i,d){const s=ge(i);return!(i!=null&&i.uuid)&&!s.name&&d&&(s.name=d),s.conditions.length===0&&(s.conditions=[be()]),s}function we(i,d){const s=[],g=[];for(const f of d){const v=f.message??f.code;if(typeof f.index=="number"){const h=`conditions.${f.index}.values`;i.setError(h,{type:"server",message:v}),g.push(h)}else s.push(v)}return s.length>0&&i.setError("root.server",{type:"server",message:s.join(" ")}),g}function Fe(){return m(p,{spacing:2,"aria-busy":!0,children:[e(C,{variant:"rounded",height:56}),e(C,{variant:"rounded",height:56}),e(C,{variant:"rounded",height:56}),e(C,{variant:"rounded",height:120})]})}function Re({rule:i,defaultName:d,canCreatePresets:s=!1,canManagePresets:g=s,onSubmit:f,onCancel:v,isSubmitting:h=!1,serverErrors:R,focusConditionIndex:U,submitLabel:q="Save",cancelLabel:J="Cancel",disabled:K=!1,id:X,hideActions:Y=!1,onDirtyChange:y}){var N,T;const b=pe(),n=b.data,Z=me()??n?.statuses??[],P=i?.uuid??"new",[B,$]=A(P),G=I(()=>ie(Se(n?.metadata)),[n]),o=de({defaultValues:H(i,d),resolver:G,mode:"onSubmit",reValidateMode:"onChange"}),[c,E]=A({}),u=xe({form:o,catalog:n,addedPresets:c,setAddedPresets:E,enabled:g});w(()=>{P!==B&&(o.reset(H(i,d)),E({}),$(P))},[o,i,d,P,B]);const S=te([]);w(()=>{o.clearErrors("root.server"),S.current.length>0&&o.clearErrors(S.current),S.current=we(o,R??[])},[o,R]);const{isDirty:j}=o.formState;w(()=>{y?.(j)},[j,y]);const l=K||h,V=(T=(N=o.formState.errors.root)==null?void 0:N.server)==null?void 0:T.message,Q=ue({control:o.control,name:"startDate"}),M=Pe(Q),_=M?le(M,1):void 0,ee=I(()=>W(n,"notes",c),[n,c]),x=(r,a)=>{E(t=>{const z=t[r]??[];return z.includes(a)?t:{...t,[r]:[...z,a]}})},k=r=>r?a=>{r("notes",a)}:void 0,re=o.handleSubmit(async r=>{if(n===void 0)return;const a=Object.fromEntries(Object.keys(c).map(t=>[t,W(n,t,c)]));await f(ve(r),{presets:a})});return m(ce,{...o,children:[e("form",{id:X,noValidate:!0,onSubmit:r=>{r.preventDefault(),r.stopPropagation(),re(r)},children:m(p,{spacing:3,children:[b.isError&&e(L,{severity:"error",action:e(F,{color:"inherit",size:"small",onClick:()=>{b.refetch()},children:"Retry"}),children:"The rule catalog could not be loaded."}),V&&e(L,{severity:"error",children:V}),n===void 0?!b.isError&&e(Fe,{}):m(ke,{children:[m(p,{direction:{xs:"column",md:"row"},spacing:2,children:[e(D,{control:o.control,name:"name",render:({field:r,fieldState:a})=>{var t;return e(oe,{...r,label:"Rule Name",required:!0,fullWidth:!0,disabled:l,error:a.error!==void 0,helperText:(t=a.error)==null?void 0:t.message,sx:{flex:2}})}}),e(p,{flex:1,minWidth:{md:220},children:e(Ee,{statuses:Z,disabled:l})})]}),m(p,{direction:{xs:"column",md:"row"},spacing:2,children:[e(D,{control:o.control,name:"startDate",render:({field:r,fieldState:a})=>{var t;return e(O,{label:"Starts",value:r.value,onChange:r.onChange,onBlur:r.onBlur,disabled:l,error:a.error!==void 0,helperText:((t=a.error)==null?void 0:t.message)??"Starts applying at the start of this day (UTC)"})}}),e(D,{control:o.control,name:"endDate",render:({field:r,fieldState:a})=>{var t;return e(O,{label:"Ends",value:r.value,onChange:r.onChange,onBlur:r.onBlur,disabled:l,minDate:_,error:a.error!==void 0,helperText:((t=a.error)==null?void 0:t.message)??"Stops applying at the start of this day (UTC)"})}})]}),e(ye,{presets:ee,onCreatePreset:k(s?x:void 0),onEditPreset:k(u.onEditPreset),onDeletePreset:k(u.onDeletePreset),disabled:l}),e(D,{control:o.control,name:"enabled",render:({field:r})=>e(ae,{label:"Enabled",control:e(se,{checked:r.value,onChange:(a,t)=>{r.onChange(t)},onBlur:r.onBlur,inputRef:r.ref,disabled:l})})}),e(Ce,{catalog:n,addedPresets:c,onCreatePreset:s?x:void 0,onEditPreset:u.onEditPreset,onDeletePreset:u.onDeletePreset,disabled:l,focusIndex:U}),e(De,{catalog:n,addedPresets:c,onCreatePreset:s?x:void 0,onEditPreset:u.onEditPreset,onDeletePreset:u.onDeletePreset,disabled:l})]}),!Y&&m(p,{direction:"row",spacing:1,justifyContent:"flex-end",children:[v&&e(F,{onClick:v,disabled:h,children:J}),e(F,{type:"submit",variant:"contained",disabled:l||n===void 0,startIcon:h?e(ne,{size:16,color:"inherit"}):void 0,children:q})]})]})}),e(he,{...u.editDialogProps}),e(fe,{...u.deleteDialogProps})]})}export{Re as NetworkRuleEditorForm};
@@ -6,8 +6,10 @@ export interface ConditionRowProps {
6
6
  /** Presets created while editing, by condition key; shown after the catalog's. */
7
7
  addedPresets?: Readonly<Record<string, readonly string[]>>;
8
8
  onCreatePreset?: (key: string, value: string) => void;
9
+ onEditPreset?: (key: string, value: string) => void;
10
+ onDeletePreset?: (key: string, value: string) => void;
9
11
  canRemove?: boolean;
10
12
  disabled?: boolean;
11
13
  autoFocus?: boolean;
12
14
  }
13
- export declare function ConditionRow({ index, catalog, onRemove, addedPresets, onCreatePreset, canRemove, disabled, autoFocus, }: Readonly<ConditionRowProps>): import("react").JSX.Element;
15
+ export declare function ConditionRow({ index, catalog, onRemove, addedPresets, onCreatePreset, onEditPreset, onDeletePreset, canRemove, disabled, autoFocus, }: Readonly<ConditionRowProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use strict";import{Stack as C,Typography as j,TextField as S,MenuItem as b,IconButton as O}from"@mui/material";import{Delete as P}from"@mui/icons-material";import{useFormContext as q,useController as h,useWatch as K}from"react-hook-form";import{getKeyDef as k,isOperatorMulti as $,getPresets as M,getOperatorLabel as z}from"../../utils/catalog.mjs";import{ConditionValuesInput as A}from"./ConditionValuesInput.mjs";import{jsxs as H,jsx as l}from"react/jsx-runtime";function L({index:o,catalog:a,onRemove:D,addedPresets:R,onCreatePreset:v,canRemove:w=!0,disabled:s=!1,autoFocus:B}){var p,g,x;const{control:d,setValue:u,formState:I}=q(),i=h({control:d,name:`conditions.${o}.key`}),r=h({control:d,name:`conditions.${o}.operator`}),m=h({control:d,name:`conditions.${o}.values`}),c=K({control:d,name:`conditions.${o}.values`})??[],t=k(a,i.field.value),T=t?.operators??[],V=$(a,r.field.value),f=I.isSubmitted,W=t?M(a,t.key,R):[],F=e=>{var n;i.field.onChange(e);const y=((n=k(a,e))==null?void 0:n.operators)??[];u(`conditions.${o}.operator`,y.length===1?y[0]:"",{shouldDirty:!0,shouldValidate:f}),u(`conditions.${o}.values`,[],{shouldDirty:!0,shouldValidate:f})};return H(C,{direction:{xs:"column",md:"row"},spacing:1.5,alignItems:"flex-start",children:[l(j,{fontSize:20,fontWeight:300,sx:{display:"flex",alignItems:"center",justifyContent:{md:"flex-end"},minHeight:{md:56},minWidth:{md:48},flexShrink:0},children:o===0?"IF":"AND"}),l(S,{select:!0,required:!0,label:"Key",value:i.field.value,onChange:e=>{F(e.target.value)},onBlur:i.field.onBlur,inputRef:i.field.ref,disabled:s,autoFocus:B,error:i.fieldState.error!==void 0,helperText:(p=i.fieldState.error)==null?void 0:p.message,sx:{minWidth:{md:200},width:{xs:"100%",md:"auto"}},children:a.keys.map(e=>l(b,{value:e.key,children:e.label},e.key))}),l(S,{select:!0,required:!0,label:"Operator",value:r.field.value,onChange:e=>{const n=e.target.value;r.field.onChange(n),!$(a,n)&&c.length>1&&u(`conditions.${o}.values`,c.slice(0,1),{shouldDirty:!0,shouldValidate:f})},onBlur:r.field.onBlur,inputRef:r.field.ref,disabled:s||t===void 0,error:r.fieldState.error!==void 0,helperText:(g=r.fieldState.error)==null?void 0:g.message,sx:{minWidth:{md:180},width:{xs:"100%",md:"auto"}},children:T.map(e=>l(b,{value:e,children:z(a,e)},e))}),l(C,{flex:1,width:"100%",minWidth:0,children:l(A,{keyDef:t,multi:V,values:c,onChange:e=>{m.field.onChange(e)},presets:W,onCreatePreset:v&&t?e=>{v(t.key,e)}:void 0,disabled:s||r.field.value==="",error:m.fieldState.error!==void 0,helperText:(x=m.fieldState.error)==null?void 0:x.message})}),l(O,{"aria-label":`Remove condition ${o+1}`,color:"error",onClick:D,disabled:s||!w,sx:{mt:{md:1}},children:l(P,{})})]})}export{L as ConditionRow};
1
+ "use strict";import{Stack as C,Typography as E,TextField as S,MenuItem as b,IconButton as K}from"@mui/material";import{Delete as M}from"@mui/icons-material";import{useFormContext as O,useController as v,useWatch as z}from"react-hook-form";import{getKeyDef as k,isOperatorMulti as D,getPresets as A,getOperatorLabel as H}from"../../utils/catalog.mjs";import{ConditionValuesInput as L}from"./ConditionValuesInput.mjs";import{jsxs as N,jsx as t}from"react/jsx-runtime";function Z({index:o,catalog:i,onRemove:P,addedPresets:$,onCreatePreset:R,onEditPreset:w,onDeletePreset:I,canRemove:T=!0,disabled:s=!1,autoFocus:V}){var p,g,x;const{control:d,setValue:u,formState:W}=O(),a=v({control:d,name:`conditions.${o}.key`}),r=v({control:d,name:`conditions.${o}.operator`}),m=v({control:d,name:`conditions.${o}.values`}),c=z({control:d,name:`conditions.${o}.values`})??[],l=k(i,a.field.value),B=l?.operators??[],F=D(i,r.field.value),f=W.isSubmitted,j=l?A(i,l.key,$):[],h=e=>e&&l?n=>{e(l.key,n)}:void 0,q=e=>{var n;a.field.onChange(e);const y=((n=k(i,e))==null?void 0:n.operators)??[];u(`conditions.${o}.operator`,y.length===1?y[0]:"",{shouldDirty:!0,shouldValidate:f}),u(`conditions.${o}.values`,[],{shouldDirty:!0,shouldValidate:f})};return N(C,{direction:{xs:"column",md:"row"},spacing:1.5,alignItems:"flex-start",children:[t(E,{fontSize:20,fontWeight:300,sx:{display:"flex",alignItems:"center",justifyContent:{md:"flex-end"},minHeight:{md:56},minWidth:{md:48},flexShrink:0},children:o===0?"IF":"AND"}),t(S,{select:!0,required:!0,label:"Key",value:a.field.value,onChange:e=>{q(e.target.value)},onBlur:a.field.onBlur,inputRef:a.field.ref,disabled:s,autoFocus:V,error:a.fieldState.error!==void 0,helperText:(p=a.fieldState.error)==null?void 0:p.message,sx:{minWidth:{md:200},width:{xs:"100%",md:"auto"}},children:i.keys.map(e=>t(b,{value:e.key,children:e.label},e.key))}),t(S,{select:!0,required:!0,label:"Operator",value:r.field.value,onChange:e=>{const n=e.target.value;r.field.onChange(n),!D(i,n)&&c.length>1&&u(`conditions.${o}.values`,c.slice(0,1),{shouldDirty:!0,shouldValidate:f})},onBlur:r.field.onBlur,inputRef:r.field.ref,disabled:s||l===void 0,error:r.fieldState.error!==void 0,helperText:(g=r.fieldState.error)==null?void 0:g.message,sx:{minWidth:{md:180},width:{xs:"100%",md:"auto"}},children:B.map(e=>t(b,{value:e,children:H(i,e)},e))}),t(C,{flex:1,width:"100%",minWidth:0,children:t(L,{keyDef:l,multi:F,values:c,onChange:e=>{m.field.onChange(e)},presets:j,onCreatePreset:h(R),onEditPreset:h(w),onDeletePreset:h(I),disabled:s||r.field.value==="",error:m.fieldState.error!==void 0,helperText:(x=m.fieldState.error)==null?void 0:x.message})}),t(K,{"aria-label":`Remove condition ${o+1}`,color:"error",onClick:P,disabled:s||!T,sx:{mt:{md:1}},children:t(M,{})})]})}export{Z as ConditionRow};
@@ -8,9 +8,11 @@ export interface ConditionValuesInputProps {
8
8
  /** Free-text keys only. */
9
9
  presets?: readonly string[];
10
10
  onCreatePreset?: (value: string) => void;
11
+ onEditPreset?: (value: string) => void;
12
+ onDeletePreset?: (value: string) => void;
11
13
  error?: boolean;
12
14
  helperText?: string;
13
15
  disabled?: boolean;
14
16
  }
15
17
  /** Pick-list, remote search or free text, by the shape of the key's `values`. */
16
- export declare function ConditionValuesInput({ keyDef, multi, values, onChange, presets, onCreatePreset, error, helperText, disabled, }: Readonly<ConditionValuesInputProps>): import("react").JSX.Element;
18
+ export declare function ConditionValuesInput({ keyDef, multi, values, onChange, presets, onCreatePreset, onEditPreset, onDeletePreset, error, helperText, disabled, }: Readonly<ConditionValuesInputProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use strict";import{TextField as m}from"@mui/material";import{hasInlineOptions as d,hasRemoteSource as h}from"../../utils/catalog.mjs";import{InlineValuesInput as f}from"./values/InlineValuesInput.mjs";import{RemoteValuesInput as b}from"./values/RemoteValuesInput.mjs";import{TextValuesInput as x}from"./values/TextValuesInput.mjs";import{jsx as a}from"react/jsx-runtime";function I({keyDef:e,multi:r,values:s,onChange:t,presets:u,onCreatePreset:p,error:o,helperText:n,disabled:i}){const l=r?"Values":"Value";return e?d(e)?a(f,{options:e.values.options,values:s,onChange:t,multi:r,label:l,error:o,helperText:n,disabled:i}):h(e)?a(b,{keyDef:e,values:s,onChange:t,multi:r,label:l,error:o,helperText:n,disabled:i}):a(x,{values:s,onChange:t,multi:r,label:l,presets:u,onCreatePreset:p,error:o,helperText:n,disabled:i}):a(m,{fullWidth:!0,disabled:!0,label:l,placeholder:"Select a key first",InputLabelProps:{shrink:!0}})}export{I as ConditionValuesInput};
1
+ "use strict";import{TextField as h}from"@mui/material";import{hasInlineOptions as f,hasRemoteSource as b}from"../../utils/catalog.mjs";import{InlineValuesInput as x}from"./values/InlineValuesInput.mjs";import{RemoteValuesInput as I}from"./values/RemoteValuesInput.mjs";import{TextValuesInput as C}from"./values/TextValuesInput.mjs";import{jsx as l}from"react/jsx-runtime";function P({keyDef:e,multi:r,values:s,onChange:a,presets:u,onCreatePreset:p,onEditPreset:m,onDeletePreset:d,error:o,helperText:n,disabled:i}){const t=r?"Values":"Value";return e?f(e)?l(x,{options:e.values.options,values:s,onChange:a,multi:r,label:t,error:o,helperText:n,disabled:i}):b(e)?l(I,{keyDef:e,values:s,onChange:a,multi:r,label:t,error:o,helperText:n,disabled:i}):l(C,{values:s,onChange:a,multi:r,label:t,presets:u,onCreatePreset:p,onEditPreset:m,onDeletePreset:d,error:o,helperText:n,disabled:i}):l(h,{fullWidth:!0,disabled:!0,label:t,placeholder:"Select a key first",InputLabelProps:{shrink:!0}})}export{P as ConditionValuesInput};
@@ -3,7 +3,9 @@ export interface ConditionsFieldProps {
3
3
  catalog: NetworkRuleCatalog;
4
4
  addedPresets?: Readonly<Record<string, readonly string[]>>;
5
5
  onCreatePreset?: (key: string, value: string) => void;
6
+ onEditPreset?: (key: string, value: string) => void;
7
+ onDeletePreset?: (key: string, value: string) => void;
6
8
  disabled?: boolean;
7
9
  focusIndex?: number;
8
10
  }
9
- export declare function ConditionsField({ catalog, addedPresets, onCreatePreset, disabled, focusIndex, }: Readonly<ConditionsFieldProps>): import("react").JSX.Element;
11
+ export declare function ConditionsField({ catalog, addedPresets, onCreatePreset, onEditPreset, onDeletePreset, disabled, focusIndex, }: Readonly<ConditionsFieldProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use strict";import{Stack as l,Typography as c,Button as v,FormHelperText as F}from"@mui/material";import{Add as b}from"@mui/icons-material";import{useFormContext as A,useFieldArray as j}from"react-hook-form";import{emptyConditionFormValues as w}from"../../utils/condition.mjs";import{ConditionRow as I}from"./ConditionRow.mjs";import{jsxs as m,jsx as o}from"react/jsx-runtime";function P({catalog:p,addedPresets:u,onCreatePreset:f,disabled:n,focusIndex:C}){var t,r,s;const{control:g,formState:i}=A(),{fields:a,append:h,remove:x}=j({control:g,name:"conditions"}),d=((r=(t=i.errors.conditions)==null?void 0:t.root)==null?void 0:r.message)??((s=i.errors.conditions)==null?void 0:s.message);return m(l,{spacing:2,children:[m(l,{direction:"row",justifyContent:"space-between",alignItems:"center",children:[o(c,{fontWeight:700,children:"Conditions"}),o(v,{startIcon:o(b,{}),disabled:n,onClick:()=>{h(w())},children:"Add Condition"})]}),a.length===0&&o(c,{variant:"body2",color:"text.secondary",children:"No conditions yet. A rule needs at least one; all conditions must match."}),a.map((y,e)=>o(I,{index:e,catalog:p,addedPresets:u,onCreatePreset:f,disabled:n,autoFocus:e===C,onRemove:()=>{x(e)}},y.id)),d&&o(F,{error:!0,children:d})]})}export{P as ConditionsField};
1
+ "use strict";import{Stack as l,Typography as c,Button as F,FormHelperText as b}from"@mui/material";import{Add as j}from"@mui/icons-material";import{useFormContext as w,useFieldArray as A}from"react-hook-form";import{emptyConditionFormValues as I}from"../../utils/condition.mjs";import{ConditionRow as k}from"./ConditionRow.mjs";import{jsxs as m,jsx as e}from"react/jsx-runtime";function R({catalog:p,addedPresets:u,onCreatePreset:f,onEditPreset:g,onDeletePreset:h,disabled:t,focusIndex:C}){var n,r,s;const{control:x,formState:i}=w(),{fields:d,append:v,remove:y}=A({control:x,name:"conditions"}),a=((r=(n=i.errors.conditions)==null?void 0:n.root)==null?void 0:r.message)??((s=i.errors.conditions)==null?void 0:s.message);return m(l,{spacing:2,children:[m(l,{direction:"row",justifyContent:"space-between",alignItems:"center",children:[e(c,{fontWeight:700,children:"Conditions"}),e(F,{startIcon:e(j,{}),disabled:t,onClick:()=>{v(I())},children:"Add Condition"})]}),d.length===0&&e(c,{variant:"body2",color:"text.secondary",children:"No conditions yet. A rule needs at least one; all conditions must match."}),d.map((P,o)=>e(k,{index:o,catalog:p,addedPresets:u,onCreatePreset:f,onEditPreset:g,onDeletePreset:h,disabled:t,autoFocus:o===C,onRemove:()=>{y(o)}},P.id)),a&&e(b,{error:!0,children:a})]})}export{R as ConditionsField};
@@ -3,10 +3,12 @@ export interface MetadataFieldProps {
3
3
  catalog: NetworkRuleCatalog;
4
4
  addedPresets?: Readonly<Record<string, readonly string[]>>;
5
5
  onCreatePreset?: (field: string, value: string) => void;
6
+ onEditPreset?: (field: string, value: string) => void;
7
+ onDeletePreset?: (field: string, value: string) => void;
6
8
  disabled?: boolean;
7
9
  }
8
10
  /**
9
11
  * Typed key/value pairs returned with the decision. Optional: a rule may have none, and a catalog
10
12
  * without `metadata` offers no section at all, as the filter panel offers no controls.
11
13
  */
12
- export declare function MetadataField({ catalog, addedPresets, onCreatePreset, disabled, }: Readonly<MetadataFieldProps>): import("react").JSX.Element | null;
14
+ export declare function MetadataField({ catalog, addedPresets, onCreatePreset, onEditPreset, onDeletePreset, disabled, }: Readonly<MetadataFieldProps>): import("react").JSX.Element | null;
@@ -1 +1 @@
1
- "use strict";import{Stack as c,Typography as u,Button as k,FormHelperText as w}from"@mui/material";import{Add as R}from"@mui/icons-material";import{useFormContext as T,useFieldArray as b}from"react-hook-form";import{getPresets as h}from"../../utils/catalog.mjs";import{NETWORK_RULE_METADATA_PRESET_FIELDS as y,emptyMetadataFormValues as C}from"../../utils/metadata.mjs";import{MetadataRow as S}from"./MetadataRow.mjs";import{jsxs as f,jsx as e}from"react/jsx-runtime";function _({catalog:a,addedPresets:o,onCreatePreset:g,disabled:s=!1}){var d,n,i;const{control:v,formState:m}=T(),{fields:r,append:x,remove:P}=b({control:v,name:"metadata"}),{metadata:t}=a;if(t===void 0)return null;const l=((n=(d=m.errors.metadata)==null?void 0:d.root)==null?void 0:n.message)??((i=m.errors.metadata)==null?void 0:i.message),A=h(a,y.key,o),E=h(a,y.value,o),F=r.length>=t.limits.maxEntries;return f(c,{spacing:2,children:[f(c,{direction:"row",justifyContent:"space-between",alignItems:"center",children:[e(u,{fontWeight:700,children:"Metadata"}),e(k,{startIcon:e(R,{}),disabled:s||F,onClick:()=>{x(C(t.types[0]))},children:"Add Metadata"})]}),r.length===0&&e(u,{variant:"body2",color:"text.secondary",children:"No metadata yet. Pairs added here are returned with the network status so your app can act on them."}),r.map((M,p)=>e(S,{index:p,types:t.types,limits:t.limits,keyPresets:A,valuePresets:E,onCreatePreset:g,disabled:s,onRemove:()=>{P(p)}},M.id)),l&&e(w,{error:!0,children:l})]})}export{_ as MetadataField};
1
+ "use strict";import{Stack as c,Typography as u,Button as F,FormHelperText as R}from"@mui/material";import{Add as b}from"@mui/icons-material";import{useFormContext as w,useFieldArray as S}from"react-hook-form";import{getPresets as h}from"../../utils/catalog.mjs";import{NETWORK_RULE_METADATA_PRESET_FIELDS as y,emptyMetadataFormValues as _}from"../../utils/metadata.mjs";import{MetadataRow as j}from"./MetadataRow.mjs";import{jsxs as f,jsx as e}from"react/jsx-runtime";function D({catalog:a,addedPresets:o,onCreatePreset:P,onEditPreset:v,onDeletePreset:g,disabled:s=!1}){var n,d,i;const{control:x,formState:l}=w(),{fields:r,append:E,remove:A}=S({control:x,name:"metadata"}),{metadata:t}=a;if(t===void 0)return null;const m=((d=(n=l.errors.metadata)==null?void 0:n.root)==null?void 0:d.message)??((i=l.errors.metadata)==null?void 0:i.message),M=h(a,y.key,o),T=h(a,y.value,o),k=r.length>=t.limits.maxEntries;return f(c,{spacing:2,children:[f(c,{direction:"row",justifyContent:"space-between",alignItems:"center",children:[e(u,{fontWeight:700,children:"Metadata"}),e(F,{startIcon:e(b,{}),disabled:s||k,onClick:()=>{E(_(t.types[0]))},children:"Add Metadata"})]}),r.length===0&&e(u,{variant:"body2",color:"text.secondary",children:"No metadata yet. Pairs added here are returned with the network status so your app can act on them."}),r.map((C,p)=>e(j,{index:p,types:t.types,limits:t.limits,keyPresets:M,valuePresets:T,onCreatePreset:P,onEditPreset:v,onDeletePreset:g,disabled:s,onRemove:()=>{A(p)}},C.id)),m&&e(R,{error:!0,children:m})]})}export{D as MetadataField};
@@ -8,7 +8,9 @@ export interface MetadataRowProps {
8
8
  valuePresets?: readonly string[];
9
9
  /** Called with the preset field the value belongs to, as `ConditionRow` does with its key. */
10
10
  onCreatePreset?: (field: string, value: string) => void;
11
+ onEditPreset?: (field: string, value: string) => void;
12
+ onDeletePreset?: (field: string, value: string) => void;
11
13
  disabled?: boolean;
12
14
  }
13
15
  /** One `key: value` pair. No IF/AND: metadata is carried along, not matched on. */
14
- export declare function MetadataRow({ index, onRemove, types, limits, keyPresets, valuePresets, onCreatePreset, disabled, }: Readonly<MetadataRowProps>): import("react").JSX.Element;
16
+ export declare function MetadataRow({ index, onRemove, types, limits, keyPresets, valuePresets, onCreatePreset, onEditPreset, onDeletePreset, disabled, }: Readonly<MetadataRowProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use strict";import{Stack as f,TextField as h,MenuItem as y,IconButton as w}from"@mui/material";import{Delete as D}from"@mui/icons-material";import{useFormContext as M,useController as p}from"react-hook-form";import{NETWORK_RULE_METADATA_PRESET_FIELDS as P,metadataTypeLabel as N,NETWORK_RULE_METADATA_BOOLEAN_OPTIONS as V,isPartialNumberInput as S}from"../../utils/metadata.mjs";import{PresetTextInput as E}from"./PresetTextInput.mjs";import{jsxs as R,jsx as a}from"react/jsx-runtime";function $({index:i,onRemove:k,types:L,limits:c,keyPresets:_=[],valuePresets:A=[],onCreatePreset:v,disabled:d=!1}){var g,x,b;const{control:u,setValue:B,formState:W}=M(),r=p({control:u,name:`metadata.${i}.key`}),o=p({control:u,name:`metadata.${i}.type`}),t=p({control:u,name:`metadata.${i}.value`}),n=o.field.value,l=t.field.value,I=W.isSubmitted,C=(g=t.fieldState.error)==null?void 0:g.message,m={required:!0,label:"Value",onBlur:t.field.onBlur,inputRef:t.field.ref,disabled:d,error:C!==void 0,helperText:C},T=e=>v?s=>{v(e,s)}:void 0,O=e=>{o.field.onChange(e),e==="string"||e==="number"&&S(l)||e==="boolean"&&(l==="true"||l==="false")||B(`metadata.${i}.value`,"",{shouldDirty:!0,shouldValidate:I})};return R(f,{direction:{xs:"column",md:"row"},spacing:1.5,alignItems:"flex-start",children:[a(f,{sx:{minWidth:{md:200},width:{xs:"100%",md:"auto"}},children:a(E,{label:"Key",required:!0,value:r.field.value,onChange:r.field.onChange,onBlur:r.field.onBlur,inputRef:r.field.ref,presets:_,onCreatePreset:T(P.key),maxLength:c.maxKeyLength,placeholder:"Pick a preset or type a key",disabled:d,error:r.fieldState.error!==void 0,helperText:(x=r.fieldState.error)==null?void 0:x.message})}),a(h,{select:!0,required:!0,label:"Type",value:n,onChange:e=>{O(e.target.value)},onBlur:o.field.onBlur,inputRef:o.field.ref,disabled:d,error:o.fieldState.error!==void 0,helperText:(b=o.fieldState.error)==null?void 0:b.message,sx:{minWidth:{md:140},width:{xs:"100%",md:"auto"}},children:L.map(e=>a(y,{value:e,children:N(e)},e))}),R(f,{flex:1,width:"100%",minWidth:0,children:[n==="boolean"&&a(h,{...m,select:!0,fullWidth:!0,value:l==="true"||l==="false"?l:"",onChange:e=>{t.field.onChange(e.target.value)},children:V.map(e=>a(y,{value:e.value,children:e.label},e.value))}),n==="number"&&a(h,{...m,fullWidth:!0,value:l,onChange:e=>{const s=e.target.value;S(s)&&t.field.onChange(s)},placeholder:"Type a number",inputProps:{inputMode:"decimal"}}),n==="string"&&a(E,{...m,value:l,onChange:t.field.onChange,presets:A,onCreatePreset:T(P.value),maxLength:c.maxValueLength,placeholder:"Pick a preset or type a value"})]}),a(w,{"aria-label":`Remove metadata ${i+1}`,color:"error",onClick:k,disabled:d,sx:{mt:{md:1}},children:a(D,{})})]})}export{$ as MetadataRow};
1
+ "use strict";import{Stack as p,TextField as v,MenuItem as R,IconButton as N}from"@mui/material";import{Delete as $}from"@mui/icons-material";import{useFormContext as K,useController as c}from"react-hook-form";import{NETWORK_RULE_METADATA_PRESET_FIELDS as i,metadataTypeLabel as F,NETWORK_RULE_METADATA_BOOLEAN_OPTIONS as V,isPartialNumberInput as S}from"../../utils/metadata.mjs";import{PresetTextInput as k}from"./PresetTextInput.mjs";import{jsxs as L,jsx as a}from"react/jsx-runtime";function q({index:d,onRemove:D,types:B,limits:g,keyPresets:W=[],valuePresets:_=[],onCreatePreset:x,onEditPreset:b,onDeletePreset:P,disabled:s=!1}){var C,y,T;const{control:f,setValue:A,formState:I}=K(),r=c({control:f,name:`metadata.${d}.key`}),o=c({control:f,name:`metadata.${d}.type`}),l=c({control:f,name:`metadata.${d}.value`}),u=o.field.value,t=l.field.value,O=I.isSubmitted,E=(C=l.fieldState.error)==null?void 0:C.message,h={required:!0,label:"Value",onBlur:l.field.onBlur,inputRef:l.field.ref,disabled:s,error:E!==void 0,helperText:E},n=(e,m)=>e?M=>{e(m,M)}:void 0,w=e=>{o.field.onChange(e),e==="string"||e==="number"&&S(t)||e==="boolean"&&(t==="true"||t==="false")||A(`metadata.${d}.value`,"",{shouldDirty:!0,shouldValidate:O})};return L(p,{direction:{xs:"column",md:"row"},spacing:1.5,alignItems:"flex-start",children:[a(p,{sx:{minWidth:{md:200},width:{xs:"100%",md:"auto"}},children:a(k,{label:"Key",required:!0,value:r.field.value,onChange:r.field.onChange,onBlur:r.field.onBlur,inputRef:r.field.ref,presets:W,onCreatePreset:n(x,i.key),onEditPreset:n(b,i.key),onDeletePreset:n(P,i.key),maxLength:g.maxKeyLength,placeholder:"Pick a preset or type a key",disabled:s,error:r.fieldState.error!==void 0,helperText:(y=r.fieldState.error)==null?void 0:y.message})}),a(v,{select:!0,required:!0,label:"Type",value:u,onChange:e=>{w(e.target.value)},onBlur:o.field.onBlur,inputRef:o.field.ref,disabled:s,error:o.fieldState.error!==void 0,helperText:(T=o.fieldState.error)==null?void 0:T.message,sx:{minWidth:{md:140},width:{xs:"100%",md:"auto"}},children:B.map(e=>a(R,{value:e,children:F(e)},e))}),L(p,{flex:1,width:"100%",minWidth:0,children:[u==="boolean"&&a(v,{...h,select:!0,fullWidth:!0,value:t==="true"||t==="false"?t:"",onChange:e=>{l.field.onChange(e.target.value)},children:V.map(e=>a(R,{value:e.value,children:e.label},e.value))}),u==="number"&&a(v,{...h,fullWidth:!0,value:t,onChange:e=>{const m=e.target.value;S(m)&&l.field.onChange(m)},placeholder:"Type a number",inputProps:{inputMode:"decimal"}}),u==="string"&&a(k,{...h,value:t,onChange:l.field.onChange,presets:_,onCreatePreset:n(x,i.value),onEditPreset:n(b,i.value),onDeletePreset:n(P,i.value),maxLength:g.maxValueLength,placeholder:"Pick a preset or type a value"})]}),a(N,{"aria-label":`Remove metadata ${d+1}`,color:"error",onClick:D,disabled:s,sx:{mt:{md:1}},children:a($,{})})]})}export{q as MetadataRow};
@@ -2,6 +2,9 @@ export interface NotesFieldProps {
2
2
  presets?: readonly string[];
3
3
  /** When set, a typed note that is not a preset offers "Add … as a preset". */
4
4
  onCreatePreset?: (value: string) => void | Promise<void>;
5
+ /** When set, each preset row offers an edit (or delete) control. */
6
+ onEditPreset?: (value: string) => void;
7
+ onDeletePreset?: (value: string) => void;
5
8
  disabled?: boolean;
6
9
  helperText?: string;
7
10
  }
@@ -9,4 +12,4 @@ export interface NotesFieldProps {
9
12
  * One note, a preset or free text, shown as a chip so a preset reads as one.
10
13
  * `multiple` is only for the chip rendering: picking or typing replaces it.
11
14
  */
12
- export declare function NotesField({ presets, onCreatePreset, disabled, helperText, }: Readonly<NotesFieldProps>): import("react").JSX.Element;
15
+ export declare function NotesField({ presets, onCreatePreset, onEditPreset, onDeletePreset, disabled, helperText, }: Readonly<NotesFieldProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use strict";import{useState as v}from"react";import{Autocomplete as c,TextField as C}from"@mui/material";import{useFormContext as x,useController as b}from"react-hook-form";import{presetOptionLabel as i,filterPresetOptions as O}from"./presetOptions.mjs";import{jsx as m}from"react/jsx-runtime";function T({presets:d=[],onCreatePreset:n,disabled:h,helperText:g="Returned with the network status so your app can act on it"}){var u;const{control:f}=x(),{field:t,fieldState:p}=b({control:f,name:"notes"}),[l,a]=v(""),s=(u=t.value)!=null&&u.trim()?t.value:null;return m(c,{multiple:!0,freeSolo:!0,autoHighlight:!0,options:d,value:s?[s]:[],inputValue:l,disabled:h,getOptionLabel:i,isOptionEqualToValue:(o,e)=>i(o)===i(e),onInputChange:(o,e,r)=>{r!=="reset"&&a(e)},onChange:(o,e)=>{const r=e[e.length-1];r===void 0?t.onChange(null):typeof r=="string"?t.onChange(r):(t.onChange(r.inputValue),n?.(r.inputValue)),a("")},onBlur:()=>{l.trim()&&(t.onChange(l.trim()),a("")),t.onBlur()},filterOptions:(o,e)=>O(o,e,n!==void 0),renderInput:o=>{var e;return m(C,{...o,label:"Notes",placeholder:s?void 0:"Pick a preset or type a note",error:p.error!==void 0,helperText:((e=p.error)==null?void 0:e.message)??g})}})}export{T as NotesField};
1
+ "use strict";import{useState as O}from"react";import{Autocomplete as x,TextField as b}from"@mui/material";import{useFormContext as P,useController as V}from"react-hook-form";import{renderPresetOption as y}from"./PresetOptionRow.mjs";import{presetOptionLabel as s,filterPresetOptions as F}from"./presetOptions.mjs";import{jsx as m}from"react/jsx-runtime";function T({presets:f=[],onCreatePreset:l,onEditPreset:h,onDeletePreset:g,disabled:v,helperText:c="Returned with the network status so your app can act on it"}){var p;const{control:C}=P(),{field:o,fieldState:u}=V({control:C,name:"notes"}),[a,n]=O(""),i=(p=o.value)!=null&&p.trim()?o.value:null,d=t=>t?e=>{n(""),t(e)}:void 0;return m(x,{multiple:!0,freeSolo:!0,autoHighlight:!0,options:f,value:i?[i]:[],inputValue:a,disabled:v,getOptionLabel:s,isOptionEqualToValue:(t,e)=>s(t)===s(e),onInputChange:(t,e,r)=>{r!=="reset"&&n(e)},onChange:(t,e)=>{const r=e[e.length-1];r===void 0?o.onChange(null):typeof r=="string"?o.onChange(r):(o.onChange(r.inputValue),l?.(r.inputValue)),n("")},onBlur:()=>{a.trim()&&(o.onChange(a.trim()),n("")),o.onBlur()},filterOptions:(t,e)=>F(t,e,l!==void 0),renderOption:y({onEdit:d(h),onDelete:d(g)}),renderInput:t=>{var e;return m(b,{...t,label:"Notes",placeholder:i?void 0:"Pick a preset or type a note",error:u.error!==void 0,helperText:((e=u.error)==null?void 0:e.message)??c})}})}export{T as NotesField};
@@ -0,0 +1,18 @@
1
+ import { HTMLAttributes, Key, ReactNode } from 'react';
2
+ import { PresetOption } from './presetOptions';
3
+ export interface PresetManageHandlers {
4
+ onEdit?: (value: string) => void;
5
+ onDelete?: (value: string) => void;
6
+ }
7
+ export interface PresetOptionRowProps extends HTMLAttributes<HTMLLIElement>, PresetManageHandlers {
8
+ option: PresetOption;
9
+ }
10
+ /**
11
+ * One dropdown row: the preset, and for a saved one the controls to edit or delete it. The
12
+ * "Add … as a preset" row has nothing to manage, so it shows the label alone.
13
+ */
14
+ export declare function PresetOptionRow({ option, onEdit, onDelete, ...optionProps }: Readonly<PresetOptionRowProps>): import("react").JSX.Element;
15
+ /** An Autocomplete `renderOption` for the preset inputs; `key` is lifted off the spread as React wants. */
16
+ export declare function renderPresetOption(handlers: PresetManageHandlers): (props: HTMLAttributes<HTMLLIElement> & {
17
+ key?: Key;
18
+ }, option: PresetOption) => ReactNode;
@@ -0,0 +1 @@
1
+ "use strict";import{Box as d,Stack as m,Tooltip as l,IconButton as s}from"@mui/material";import{Edit as f,Delete as h}from"@mui/icons-material";import{presetOptionLabel as x}from"./presetOptions.mjs";import{jsx as t,jsxs as a}from"react/jsx-runtime";const P=e=>{e.stopPropagation()};function c({option:e,onEdit:o,onDelete:i,...r}){const n=typeof e=="string"?e:void 0,p=n!==void 0&&(o!==void 0||i!==void 0);return a("li",{...r,children:[t(d,{component:"span",sx:{flex:1,minWidth:0,overflowWrap:"anywhere"},children:x(e)}),p&&a(m,{direction:"row",spacing:.5,sx:{ml:1,flexShrink:0},onClick:P,children:[o&&t(l,{title:"Edit Preset",placement:"top",children:t(s,{size:"small",tabIndex:-1,"aria-label":"Edit Preset",onClick:()=>{o(n)},children:t(f,{fontSize:"small"})})}),i&&t(l,{title:"Delete Preset",placement:"top",children:t(s,{size:"small",color:"error",tabIndex:-1,"aria-label":"Delete Preset",onClick:()=>{i(n)},children:t(h,{fontSize:"small"})})})]})]})}function k(e){return(o,i)=>{const{key:r,...n}=o;return t(c,{...n,option:i,onEdit:e.onEdit,onDelete:e.onDelete},r)}}export{c as PresetOptionRow,k as renderPresetOption};
@@ -6,6 +6,9 @@ export interface PresetTextInputProps {
6
6
  onBlur?: () => void;
7
7
  presets?: readonly string[];
8
8
  onCreatePreset?: (value: string) => void;
9
+ /** When set, each preset row offers an edit (or delete) control. */
10
+ onEditPreset?: (value: string) => void;
11
+ onDeletePreset?: (value: string) => void;
9
12
  maxLength?: number;
10
13
  placeholder?: string;
11
14
  required?: boolean;
@@ -19,4 +22,4 @@ export interface PresetTextInputProps {
19
22
  * `TextValuesInput` is for a condition's several values. Leaving the field keeps the text but
20
23
  * creates no preset — see the note in `presetOptions.ts` before changing that.
21
24
  */
22
- export declare function PresetTextInput({ label, value, onChange, onBlur, presets, onCreatePreset, maxLength, placeholder, required, disabled, error, helperText, inputRef, }: Readonly<PresetTextInputProps>): import("react").JSX.Element;
25
+ export declare function PresetTextInput({ label, value, onChange, onBlur, presets, onCreatePreset, onEditPreset, onDeletePreset, maxLength, placeholder, required, disabled, error, helperText, inputRef, }: Readonly<PresetTextInputProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use strict";import{Autocomplete as c,TextField as O}from"@mui/material";import{presetOptionLabel as n,filterPresetOptions as T}from"./presetOptions.mjs";import{jsx as i}from"react/jsx-runtime";function P({label:a,value:l,onChange:r,onBlur:p,presets:s=[],onCreatePreset:o,maxLength:u,placeholder:d,required:h,disabled:f,error:m,helperText:g,inputRef:x}){return i(c,{freeSolo:!0,autoHighlight:!0,selectOnFocus:!0,handleHomeEndKeys:!0,options:s,value:l,inputValue:l,disabled:f,getOptionLabel:n,isOptionEqualToValue:(t,e)=>n(t)===n(e),filterOptions:(t,e)=>T(t,e,o!==void 0),onInputChange:(t,e,b)=>{b!=="reset"&&r(e)},onChange:(t,e)=>{e===null?r(""):typeof e=="string"?r(e):(r(e.inputValue),o?.(e.inputValue))},onBlur:p,renderInput:t=>i(O,{...t,label:a,required:h,placeholder:d,error:m,helperText:g,inputRef:x,inputProps:{...t.inputProps,maxLength:u}})})}export{P as PresetTextInput};
1
+ "use strict";import{Autocomplete as c,TextField as T}from"@mui/material";import{renderPresetOption as v}from"./PresetOptionRow.mjs";import{presetOptionLabel as o,filterPresetOptions as C}from"./presetOptions.mjs";import{jsx as i}from"react/jsx-runtime";function E({label:p,value:l,onChange:r,onBlur:a,presets:s=[],onCreatePreset:n,onEditPreset:u,onDeletePreset:d,maxLength:h,placeholder:m,required:f,disabled:g,error:x,helperText:O,inputRef:P}){return i(c,{freeSolo:!0,autoHighlight:!0,selectOnFocus:!0,handleHomeEndKeys:!0,options:s,value:l,inputValue:l,disabled:g,getOptionLabel:o,isOptionEqualToValue:(t,e)=>o(t)===o(e),filterOptions:(t,e)=>C(t,e,n!==void 0),renderOption:v({onEdit:u,onDelete:d}),onInputChange:(t,e,b)=>{b!=="reset"&&r(e)},onChange:(t,e)=>{e===null?r(""):typeof e=="string"?r(e):(r(e.inputValue),n?.(e.inputValue))},onBlur:a,renderInput:t=>i(T,{...t,label:p,required:f,placeholder:m,error:x,helperText:O,inputRef:P,inputProps:{...t.inputProps,maxLength:h}})})}export{E as PresetTextInput};
@@ -5,5 +5,8 @@ export type CreatePresetOption = {
5
5
  };
6
6
  export type PresetOption = string | CreatePresetOption;
7
7
  export declare const presetOptionLabel: (option: PresetOption) => string;
8
- /** The matching presets, plus "Add … as a preset" for typed text that is not one yet. */
8
+ /**
9
+ * The matching presets, plus "Add … as a preset" for typed text that is not one yet. A field at
10
+ * the server's cap offers no add row: the text still goes on the rule, just not into the presets.
11
+ */
9
12
  export declare function filterPresetOptions(options: PresetOption[], state: FilterOptionsState<PresetOption>, canCreate: boolean): PresetOption[];
@@ -1 +1 @@
1
- "use strict";import{createFilterOptions as p}from"@mui/material";const i=p(),l=t=>typeof t=="string"?t:t.label;function u(t,s,a){const o=i(t,s),e=s.inputValue.trim(),n=t.some(r=>typeof r=="string"&&r.toLowerCase()===e.toLowerCase());return e&&a&&!n&&o.push({inputValue:e,label:`Add "${e}" as a preset`}),o}export{u as filterPresetOptions,l as presetOptionLabel};
1
+ "use strict";import{createFilterOptions as n}from"@mui/material";import{isPresetListFull as l}from"../../utils/presets.mjs";const f=n(),u=t=>typeof t=="string"?t:t.label;function m(t,s,a){const o=f(t,s),e=s.inputValue.trim(),i=t.filter(r=>typeof r=="string"),p=i.some(r=>r.toLowerCase()===e.toLowerCase());return e&&a&&!p&&!l(i)&&o.push({inputValue:e,label:`Add "${e}" as a preset`}),o}export{m as filterPresetOptions,u as presetOptionLabel};
@@ -6,6 +6,9 @@ export interface TextValuesInputProps {
6
6
  presets?: readonly string[];
7
7
  /** When set, a typed value that is not a preset offers "Add … as a preset". */
8
8
  onCreatePreset?: (value: string) => void;
9
+ /** When set, each preset row offers an edit (or delete) control. */
10
+ onEditPreset?: (value: string) => void;
11
+ onDeletePreset?: (value: string) => void;
9
12
  error?: boolean;
10
13
  helperText?: string;
11
14
  disabled?: boolean;
@@ -15,4 +18,4 @@ export interface TextValuesInputProps {
15
18
  * Free-text chips with the presets as suggestions. As in the notes field, Enter takes the
16
19
  * highlighted suggestion: a matching preset, or "Add … as a preset" for a new value.
17
20
  */
18
- export declare function TextValuesInput({ values, onChange, multi, label, presets, onCreatePreset, error, helperText, disabled, placeholder, }: Readonly<TextValuesInputProps>): import("react").JSX.Element;
21
+ export declare function TextValuesInput({ values, onChange, multi, label, presets, onCreatePreset, onEditPreset, onDeletePreset, error, helperText, disabled, placeholder, }: Readonly<TextValuesInputProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use strict";import{useState as y,Fragment as O}from"react";import{Autocomplete as C,TextField as V,Chip as I}from"@mui/material";import{dedupeValues as S}from"../../../utils/condition.mjs";import{presetOptionLabel as u,filterPresetOptions as j}from"../presetOptions.mjs";import{OrSeparator as F}from"./OrSeparator.mjs";import{jsx as a,jsxs as L}from"react/jsx-runtime";function P({values:l,onChange:m,multi:d,label:f,presets:g=[],onCreatePreset:s,error:h,helperText:c,disabled:x,placeholder:b="Type a value and press Enter"}){const[n,p]=y(""),i=t=>{const e=S(t);m(d?e:e.slice(-1))};return a(C,{multiple:!0,freeSolo:!0,autoHighlight:!0,options:g,value:l,inputValue:n,disabled:x,limitTags:4,getOptionLabel:u,filterOptions:(t,e)=>j(t,e,s!==void 0),onInputChange:(t,e)=>{p(e)},onChange:(t,e)=>{const o=e.find(r=>typeof r!="string");o!==void 0&&typeof o!="string"&&s?.(o.inputValue),i(e.map(r=>typeof r=="string"?r:r.inputValue)),p("")},onBlur:()=>{n.trim()&&(i([...l,n]),p(""))},renderTags:(t,e)=>t.map((o,r)=>{const{key:T,...v}=e({index:r});return L(O,{children:[r>0&&a(F,{}),a(I,{...v,label:u(o)})]},T)}),renderInput:t=>a(V,{...t,label:f,placeholder:l.length===0?b:void 0,error:h,helperText:c})})}export{P as TextValuesInput};
1
+ "use strict";import{useState as P,Fragment as V}from"react";import{Autocomplete as E,TextField as I,Chip as S}from"@mui/material";import{dedupeValues as j}from"../../../utils/condition.mjs";import{renderPresetOption as F}from"../PresetOptionRow.mjs";import{presetOptionLabel as m,filterPresetOptions as L}from"../presetOptions.mjs";import{OrSeparator as k}from"./OrSeparator.mjs";import{jsx as a,jsxs as A}from"react/jsx-runtime";function B({values:s,onChange:u,multi:f,label:g,presets:h=[],onCreatePreset:l,onEditPreset:c,onDeletePreset:x,error:b,helperText:v,disabled:O,placeholder:T="Type a value and press Enter"}){const[i,n]=P(""),p=t=>{const e=j(t);u(f?e:e.slice(-1))},d=t=>t?e=>{n(""),t(e)}:void 0;return a(E,{multiple:!0,freeSolo:!0,autoHighlight:!0,options:h,value:s,inputValue:i,disabled:O,limitTags:4,getOptionLabel:m,filterOptions:(t,e)=>L(t,e,l!==void 0),renderOption:F({onEdit:d(c),onDelete:d(x)}),onInputChange:(t,e)=>{n(e)},onChange:(t,e)=>{const o=e.find(r=>typeof r!="string");o!==void 0&&typeof o!="string"&&l?.(o.inputValue),p(e.map(r=>typeof r=="string"?r:r.inputValue)),n("")},onBlur:()=>{i.trim()&&(p([...s,i]),n(""))},renderTags:(t,e)=>t.map((o,r)=>{const{key:y,...C}=e({index:r});return A(V,{children:[r>0&&a(k,{}),a(S,{...C,label:m(o)})]},y)}),renderInput:t=>a(I,{...t,label:g,placeholder:s.length===0?T:void 0,error:b,helperText:v})})}export{B as TextValuesInput};
@@ -0,0 +1,27 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+ import { UseFormReturn } from 'react-hook-form';
3
+ import { NetworkRulePresetDeleteDialogProps } from '../dialog/NetworkRulePresetDeleteDialog';
4
+ import { NetworkRulePresetEditDialogProps } from '../dialog/NetworkRulePresetEditDialog';
5
+ import { NetworkRuleCatalog, NetworkRuleFormValues, NetworkRulePresets } from '../types';
6
+ export interface UseNetworkRulePresetManagerOptions {
7
+ /** The rule being edited, which follows a rename when the user asks rules to. */
8
+ form: UseFormReturn<NetworkRuleFormValues>;
9
+ catalog: NetworkRuleCatalog | undefined;
10
+ /** Presets created while editing and not stored yet; those are changed in place, without a write. */
11
+ addedPresets: NetworkRulePresets;
12
+ setAddedPresets: Dispatch<SetStateAction<NetworkRulePresets>>;
13
+ /** Off, or on without `services.updatePresets`, gives no handlers, so the inputs show no controls. */
14
+ enabled: boolean;
15
+ }
16
+ export interface NetworkRulePresetManager {
17
+ onEditPreset?: (field: string, value: string) => void;
18
+ onDeletePreset?: (field: string, value: string) => void;
19
+ editDialogProps: NetworkRulePresetEditDialogProps;
20
+ deleteDialogProps: NetworkRulePresetDeleteDialogProps;
21
+ }
22
+ /**
23
+ * The edit and delete flows behind the preset dropdowns: which preset a dialog is about, the write
24
+ * of the field's revised list, and the error the dialog shows when that write fails. A rename
25
+ * touches rules only when the user ticks the box for it, and then also the rule open here.
26
+ */
27
+ export declare function useNetworkRulePresetManager({ form, catalog, addedPresets, setAddedPresets, enabled, }: UseNetworkRulePresetManagerOptions): NetworkRulePresetManager;
@@ -0,0 +1 @@
1
+ "use strict";import{useState as S}from"react";import{useNetworkRulesServices as T}from"../NetworkRules.context.mjs";import{useRenameNetworkRulePreset as L}from"../hooks/useRenameNetworkRulePreset.mjs";import{useUpdateNetworkRulesPresets as _}from"../hooks/useUpdateNetworkRulesPresets.mjs";import{getPresetMaxLength as b,getPresets as C,getSavedPresets as k}from"../utils/catalog.mjs";import{dedupeValues as M}from"../utils/condition.mjs";import{NETWORK_RULE_METADATA_PRESET_FIELDS as V}from"../utils/metadata.mjs";import{removePreset as w,replacePreset as A}from"../utils/presets.mjs";const x="The presets could not be saved.";function U(o,l,u,d){const m={shouldDirty:!0,shouldValidate:o.formState.isSubmitted},f=o.getValues();if(l==="notes"){f.notes===u&&o.setValue("notes",d,m);return}if(l===V.key){f.metadata.forEach((a,s)=>{a.key===u&&o.setValue(`metadata.${s}.key`,d,m)});return}if(l===V.value){f.metadata.forEach((a,s)=>{a.type==="string"&&a.value===u&&o.setValue(`metadata.${s}.value`,d,m)});return}f.conditions.forEach((a,s)=>{a.key===l&&a.values.includes(u)&&o.setValue(`conditions.${s}.values`,M(a.values.map(n=>n===u?d:n)),m)})}function $({form:o,catalog:l,addedPresets:u,setAddedPresets:d,enabled:m}){const{updatePresets:f,renamePreset:a}=T(),s=L(),n=_(),[t,g]=S(null),[v,y]=S(null),R=m&&f!==void 0,P=({field:e,value:r})=>(u[e]??[]).includes(r),p=()=>{g(null),y(null),s.reset(),n.reset()},h=e=>e?e.message||x:void 0,D={open:t!==null,value:t?.value,presets:t?C(l,t.field,u):void 0,maxLength:t?b(l,t.field):void 0,canUpdateRules:t!==null&&a!==void 0&&!P(t),isSaving:s.isPending,error:h(s.error),onClose:p,onSave:async(e,{updateRules:r})=>{if(!t)return;const{field:i,value:c}=t;if(P(t))d(E=>({...E,[i]:A(E[i]??[],c,e)}));else{try{await s.mutateAsync({field:i,from:c,to:e,presets:A(k(l,i),c,e),updateRules:r})}catch{return}r&&U(o,i,c,e)}p()}},N={open:v!==null,value:v?.value,isDeleting:n.isPending,error:h(n.error),onClose:p,onConfirm:async()=>{if(!v)return;const{field:e,value:r}=v;if(P(v))d(i=>({...i,[e]:w(i[e]??[],r)}));else try{await n.mutateAsync({[e]:w(k(l,e),r)})}catch{return}p()}};return{onEditPreset:R?(e,r)=>{s.reset(),g({field:e,value:r})}:void 0,onDeletePreset:R?(e,r)=>{n.reset(),y({field:e,value:r})}:void 0,editDialogProps:D,deleteDialogProps:N}}export{$ as useNetworkRulePresetManager};
@@ -1,4 +1,6 @@
1
1
  export * from './useNetworkRulesCatalog';
2
+ export * from './useUpdateNetworkRulesPresets';
3
+ export * from './useRenameNetworkRulePreset';
2
4
  export * from './useNetworkRuleSourceSearch';
3
5
  export * from './useResolvedConditionOptions';
4
6
  export * from './useHeldWhileClosed';
@@ -0,0 +1,8 @@
1
+ import { UseMutationResult } from '@tanstack/react-query';
2
+ import { NetworkRulePresetRename } from '../types';
3
+ /**
4
+ * Renames one saved preset through `services.renamePreset`, or through `updatePresets` when the
5
+ * host has no rename of its own, then refetches the catalog the presets ride on. The refetch is
6
+ * awaited, so a caller's spinner lasts until the dropdowns can show the new list.
7
+ */
8
+ export declare function useRenameNetworkRulePreset(): UseMutationResult<void, Error, NetworkRulePresetRename>;
@@ -0,0 +1 @@
1
+ "use strict";import{useQueryClient as a,useMutation as i}from"@tanstack/react-query";import{useNetworkRulesServices as u}from"../NetworkRules.context.mjs";import{networkRulesCatalogQueryKey as n}from"./useNetworkRulesCatalog.mjs";function c(){const{scope:t,renamePreset:s,updatePresets:r}=u(),o=a();return i({mutationFn:async e=>{if(s!==void 0)await s(e);else if(r!==void 0)await r({[e.field]:e.presets});else throw new Error("NetworkRulesServices.updatePresets is not configured")},onSuccess:async()=>{await o.invalidateQueries({queryKey:n(t)})}})}export{c as useRenameNetworkRulePreset};
@@ -0,0 +1,7 @@
1
+ import { UseMutationResult } from '@tanstack/react-query';
2
+ import { NetworkRulePresets } from '../types';
3
+ /**
4
+ * Writes preset lists through `services.updatePresets`, then refetches the catalog they ride on.
5
+ * The refetch is awaited, so a caller's spinner lasts until the dropdowns can show the new list.
6
+ */
7
+ export declare function useUpdateNetworkRulesPresets(): UseMutationResult<void, Error, NetworkRulePresets>;
@@ -0,0 +1 @@
1
+ "use strict";import{useQueryClient as o,useMutation as u}from"@tanstack/react-query";import{useNetworkRulesServices as a}from"../NetworkRules.context.mjs";import{networkRulesCatalogQueryKey as i}from"./useNetworkRulesCatalog.mjs";function n(){const{scope:s,updatePresets:e}=a(),t=o();return u({mutationFn:async r=>{if(e===void 0)throw new Error("NetworkRulesServices.updatePresets is not configured");await e(r)},onSuccess:async()=>{await t.invalidateQueries({queryKey:i(s)})}})}export{n as useUpdateNetworkRulesPresets};
@@ -1 +1 @@
1
- "use strict";import{NETWORK_RULE_STATUSES as e,getStatusPresentation as a}from"./statuses.mjs";import{NetworkRulesProvider as s,useNetworkRuleStatuses as t,useNetworkRulesServices as o}from"./NetworkRules.context.mjs";import{ConditionValuesInput as r}from"./editor/fields/ConditionValuesInput.mjs";import{DateField as l}from"./editor/fields/DateField.mjs";import{NETWORK_RULES_COLUMN_IDS as u,buildNetworkRulesColumns as i}from"./table/columns.mjs";import{NETWORK_RULES_FILTER_IDS as m,NETWORK_RULES_TEXT_OPERATORS as R,buildNetworkRulesFilterFields as N,conditionFilterId as d,conditionFilterKey as p}from"./table/filters.mjs";import{NETWORK_RULE_METADATA_BOOLEAN_OPTIONS as E,NETWORK_RULE_METADATA_PRESET_FIELDS as n,NETWORK_RULE_METADATA_TYPES as T,emptyMetadataFormValues as w,formatMetadataValue as k,fromMetadataFormValues as S,isExactNumberValue as _,isNumberValue as O,isPartialNumberInput as f,metadataTypeLabel as D,toMetadataFormValues as F,typeOfMetadataValue as L}from"./utils/metadata.mjs";import{NetworkRuleConditionsTable as b}from"./table/NetworkRuleConditionsTable.mjs";import{NetworkRuleDeleteDialog as g}from"./dialog/NetworkRuleDeleteDialog.mjs";import{NetworkRuleDiscardDialog as A}from"./dialog/NetworkRuleDiscardDialog.mjs";import{NetworkRuleEditorDialog as V}from"./editor/NetworkRuleEditorDialog.mjs";import{NetworkRuleEditorForm as y}from"./editor/NetworkRuleEditorForm.mjs";import{NetworkRuleExpandedPanel as C}from"./table/NetworkRuleExpandedPanel.mjs";import{NetworkRuleMetadataTable as c}from"./table/NetworkRuleMetadataTable.mjs";import{NetworkRuleRow as K}from"./table/NetworkRuleRow.mjs";import{NetworkRulesTable as M}from"./table/NetworkRulesTable.mjs";import{NetworkStatusChip as I}from"./shared/NetworkStatusChip.mjs";import{OptionChips as P}from"./shared/OptionChips.mjs";import{buildNetworkRulesListQuery as U}from"./table/query.mjs";import{createNetworkRuleFormSchema as h,networkRuleConditionFormSchema as W}from"./editor/schema.mjs";import{dayToRuleDate as v,formatRuleDate as x,ruleDateToDay as Q}from"./utils/date.mjs";import{dedupeValues as B,emptyConditionFormValues as X,fromNetworkRuleFormValues as H,toNetworkRuleFormValues as Y}from"./utils/condition.mjs";import{getKeyDef as j,getKeyLabel as z,getOperatorLabel as J,getPresets as $,getStatusLabel as q,hasInlineOptions as G,hasRemoteSource as Z,isOperatorMulti as ee,toOptions as ae}from"./utils/catalog.mjs";import{networkRulesCatalogQueryKey as se,useNetworkRulesCatalog as te}from"./hooks/useNetworkRulesCatalog.mjs";import{useHeldWhileClosed as oe}from"./hooks/useHeldWhileClosed.mjs";import{useNetworkRuleSourceSearch as re}from"./hooks/useNetworkRuleSourceSearch.mjs";import{useNetworkRulesDialogs as le}from"./hooks/useNetworkRulesDialogs.mjs";import{useResolvedConditionOptions as ue}from"./hooks/useResolvedConditionOptions.mjs";export{r as ConditionValuesInput,l as DateField,u as NETWORK_RULES_COLUMN_IDS,m as NETWORK_RULES_FILTER_IDS,R as NETWORK_RULES_TEXT_OPERATORS,E as NETWORK_RULE_METADATA_BOOLEAN_OPTIONS,n as NETWORK_RULE_METADATA_PRESET_FIELDS,T as NETWORK_RULE_METADATA_TYPES,e as NETWORK_RULE_STATUSES,b as NetworkRuleConditionsTable,g as NetworkRuleDeleteDialog,A as NetworkRuleDiscardDialog,V as NetworkRuleEditorDialog,y as NetworkRuleEditorForm,C as NetworkRuleExpandedPanel,c as NetworkRuleMetadataTable,K as NetworkRuleRow,s as NetworkRulesProvider,M as NetworkRulesTable,I as NetworkStatusChip,P as OptionChips,i as buildNetworkRulesColumns,N as buildNetworkRulesFilterFields,U as buildNetworkRulesListQuery,d as conditionFilterId,p as conditionFilterKey,h as createNetworkRuleFormSchema,v as dayToRuleDate,B as dedupeValues,X as emptyConditionFormValues,w as emptyMetadataFormValues,k as formatMetadataValue,x as formatRuleDate,S as fromMetadataFormValues,H as fromNetworkRuleFormValues,j as getKeyDef,z as getKeyLabel,J as getOperatorLabel,$ as getPresets,q as getStatusLabel,a as getStatusPresentation,G as hasInlineOptions,Z as hasRemoteSource,_ as isExactNumberValue,O as isNumberValue,ee as isOperatorMulti,f as isPartialNumberInput,D as metadataTypeLabel,W as networkRuleConditionFormSchema,se as networkRulesCatalogQueryKey,Q as ruleDateToDay,F as toMetadataFormValues,Y as toNetworkRuleFormValues,ae as toOptions,L as typeOfMetadataValue,oe as useHeldWhileClosed,re as useNetworkRuleSourceSearch,t as useNetworkRuleStatuses,te as useNetworkRulesCatalog,le as useNetworkRulesDialogs,o as useNetworkRulesServices,ue as useResolvedConditionOptions};
1
+ "use strict";import{NETWORK_RULE_STATUSES as e,getStatusPresentation as a}from"./statuses.mjs";import{NetworkRulesProvider as s,useNetworkRuleStatuses as t,useNetworkRulesServices as o}from"./NetworkRules.context.mjs";import{ConditionValuesInput as r}from"./editor/fields/ConditionValuesInput.mjs";import{DateField as l}from"./editor/fields/DateField.mjs";import{NETWORK_RULES_COLUMN_IDS as u,buildNetworkRulesColumns as i}from"./table/columns.mjs";import{NETWORK_RULES_FILTER_IDS as m,NETWORK_RULES_TEXT_OPERATORS as R,buildNetworkRulesFilterFields as N,conditionFilterId as d,conditionFilterKey as E}from"./table/filters.mjs";import{NETWORK_RULE_METADATA_BOOLEAN_OPTIONS as p,NETWORK_RULE_METADATA_PRESET_FIELDS as n,NETWORK_RULE_METADATA_TYPES as T,emptyMetadataFormValues as w,formatMetadataValue as k,fromMetadataFormValues as S,isExactNumberValue as _,isNumberValue as f,isPartialNumberInput as O,metadataTypeLabel as D,toMetadataFormValues as P,typeOfMetadataValue as L}from"./utils/metadata.mjs";import{NETWORK_RULE_PRESETS_MAX_ITEMS as F,isPresetListFull as g,removePreset as M,renamePresetInRule as b,replacePreset as A,validatePresetValue as V}from"./utils/presets.mjs";import{NetworkRuleConditionsTable as c}from"./table/NetworkRuleConditionsTable.mjs";import{NetworkRuleDeleteDialog as C}from"./dialog/NetworkRuleDeleteDialog.mjs";import{NetworkRuleDiscardDialog as K}from"./dialog/NetworkRuleDiscardDialog.mjs";import{NetworkRuleEditorDialog as y}from"./editor/NetworkRuleEditorDialog.mjs";import{NetworkRuleEditorForm as I}from"./editor/NetworkRuleEditorForm.mjs";import{NetworkRuleExpandedPanel as U}from"./table/NetworkRuleExpandedPanel.mjs";import{NetworkRuleMetadataTable as W}from"./table/NetworkRuleMetadataTable.mjs";import{NetworkRulePresetDeleteDialog as h}from"./dialog/NetworkRulePresetDeleteDialog.mjs";import{NetworkRulePresetEditDialog as v}from"./dialog/NetworkRulePresetEditDialog.mjs";import{NetworkRuleRow as x}from"./table/NetworkRuleRow.mjs";import{NetworkRulesTable as Q}from"./table/NetworkRulesTable.mjs";import{NetworkStatusChip as X}from"./shared/NetworkStatusChip.mjs";import{OptionChips as B}from"./shared/OptionChips.mjs";import{buildNetworkRulesListQuery as H}from"./table/query.mjs";import{createNetworkRuleFormSchema as Y,networkRuleConditionFormSchema as j}from"./editor/schema.mjs";import{dayToRuleDate as q,formatRuleDate as z,ruleDateToDay as G}from"./utils/date.mjs";import{dedupeValues as J,emptyConditionFormValues as Z,fromNetworkRuleFormValues as $,toNetworkRuleFormValues as ee}from"./utils/condition.mjs";import{getKeyDef as ae,getKeyLabel as se,getOperatorLabel as te,getPresetMaxLength as oe,getPresets as re,getSavedPresets as le,getStatusLabel as ue,hasInlineOptions as ie,hasRemoteSource as me,isOperatorMulti as Re,toOptions as Ne}from"./utils/catalog.mjs";import{networkRulesCatalogQueryKey as de,useNetworkRulesCatalog as Ee}from"./hooks/useNetworkRulesCatalog.mjs";import{useHeldWhileClosed as pe}from"./hooks/useHeldWhileClosed.mjs";import{useNetworkRuleSourceSearch as ne}from"./hooks/useNetworkRuleSourceSearch.mjs";import{useNetworkRulesDialogs as Te}from"./hooks/useNetworkRulesDialogs.mjs";import{useRenameNetworkRulePreset as we}from"./hooks/useRenameNetworkRulePreset.mjs";import{useResolvedConditionOptions as ke}from"./hooks/useResolvedConditionOptions.mjs";import{useUpdateNetworkRulesPresets as Se}from"./hooks/useUpdateNetworkRulesPresets.mjs";export{r as ConditionValuesInput,l as DateField,u as NETWORK_RULES_COLUMN_IDS,m as NETWORK_RULES_FILTER_IDS,R as NETWORK_RULES_TEXT_OPERATORS,p as NETWORK_RULE_METADATA_BOOLEAN_OPTIONS,n as NETWORK_RULE_METADATA_PRESET_FIELDS,T as NETWORK_RULE_METADATA_TYPES,F as NETWORK_RULE_PRESETS_MAX_ITEMS,e as NETWORK_RULE_STATUSES,c as NetworkRuleConditionsTable,C as NetworkRuleDeleteDialog,K as NetworkRuleDiscardDialog,y as NetworkRuleEditorDialog,I as NetworkRuleEditorForm,U as NetworkRuleExpandedPanel,W as NetworkRuleMetadataTable,h as NetworkRulePresetDeleteDialog,v as NetworkRulePresetEditDialog,x as NetworkRuleRow,s as NetworkRulesProvider,Q as NetworkRulesTable,X as NetworkStatusChip,B as OptionChips,i as buildNetworkRulesColumns,N as buildNetworkRulesFilterFields,H as buildNetworkRulesListQuery,d as conditionFilterId,E as conditionFilterKey,Y as createNetworkRuleFormSchema,q as dayToRuleDate,J as dedupeValues,Z as emptyConditionFormValues,w as emptyMetadataFormValues,k as formatMetadataValue,z as formatRuleDate,S as fromMetadataFormValues,$ as fromNetworkRuleFormValues,ae as getKeyDef,se as getKeyLabel,te as getOperatorLabel,oe as getPresetMaxLength,re as getPresets,le as getSavedPresets,ue as getStatusLabel,a as getStatusPresentation,ie as hasInlineOptions,me as hasRemoteSource,_ as isExactNumberValue,f as isNumberValue,Re as isOperatorMulti,O as isPartialNumberInput,g as isPresetListFull,D as metadataTypeLabel,j as networkRuleConditionFormSchema,de as networkRulesCatalogQueryKey,M as removePreset,b as renamePresetInRule,A as replacePreset,G as ruleDateToDay,P as toMetadataFormValues,ee as toNetworkRuleFormValues,Ne as toOptions,L as typeOfMetadataValue,pe as useHeldWhileClosed,ne as useNetworkRuleSourceSearch,t as useNetworkRuleStatuses,Ee as useNetworkRulesCatalog,Te as useNetworkRulesDialogs,o as useNetworkRulesServices,we as useRenameNetworkRulePreset,ke as useResolvedConditionOptions,Se as useUpdateNetworkRulesPresets,V as validatePresetValue};
@@ -109,14 +109,28 @@ export type NetworkRuleFormValues = {
109
109
  metadata: NetworkRuleMetadataFormValues[];
110
110
  conditions: NetworkRuleConditionFormValues[];
111
111
  };
112
+ /**
113
+ * Complete preset lists keyed by the field they suggest for: `notes` for the rule's note,
114
+ * `metadataKeys` and `metadataValues` for the metadata rows, otherwise the free-text condition
115
+ * key. Fields left out are untouched: the brand patch merges per field.
116
+ */
117
+ export type NetworkRulePresets = Record<string, string[]>;
118
+ /**
119
+ * One saved preset renamed. `presets` is the field's complete list with the change applied, ready
120
+ * to store as `updatePresets` would. `updateRules` is the user's choice to also change the rules
121
+ * that carry `from`; `renamePresetInRule` says what that means for one rule.
122
+ */
123
+ export type NetworkRulePresetRename = {
124
+ field: string;
125
+ from: string;
126
+ to: string;
127
+ presets: string[];
128
+ updateRules: boolean;
129
+ };
112
130
  /** Handed back with the submitted rule. */
113
131
  export type NetworkRuleSubmitExtras = {
114
- /**
115
- * Preset lists that grew while editing, complete and ready to store, keyed by the field they
116
- * suggest for: `notes` for the rule's note, `metadataKeys` and `metadataValues` for the metadata
117
- * rows, otherwise the free-text condition key. Empty when nothing was added.
118
- */
119
- presets: Record<string, string[]>;
132
+ /** Preset lists that grew while editing, ready to store. Empty when nothing was added. */
133
+ presets: NetworkRulePresets;
120
134
  };
121
135
  /** A server validation error; `index` points at the offending condition. */
122
136
  export type NetworkRuleServerError = {
@@ -142,6 +156,17 @@ export type NetworkRulesServices = {
142
156
  /** Namespaces the query keys when several providers share one query client, e.g. `${env}:${brandUuid}`. */
143
157
  scope?: string;
144
158
  getCatalog: (signal?: AbortSignal) => Promise<NetworkRuleCatalog>;
159
+ /**
160
+ * Stores the given fields' complete lists, leaving the others alone. With it the editor offers
161
+ * edit and delete controls on saved presets and refetches the catalog after each write.
162
+ */
163
+ updatePresets?: (presets: NetworkRulePresets) => Promise<void>;
164
+ /**
165
+ * Renames one saved preset: stores `presets` as `updatePresets` would and, when `updateRules` is
166
+ * set, changes the rules that carry the old text. With it the edit dialog offers that choice;
167
+ * without it a rename goes through `updatePresets` and rules are left alone.
168
+ */
169
+ renamePreset?: (rename: NetworkRulePresetRename) => Promise<void>;
145
170
  sources?: Record<string, NetworkRuleSourceService<any>>;
146
171
  /** Shared with the host app; otherwise the provider creates its own. */
147
172
  queryClient?: QueryClient;
@@ -18,6 +18,13 @@ export declare function hasRemoteSource(keyDef: NetworkRuleKeyDef | undefined):
18
18
  };
19
19
  /** One option per value, in order; a value `options` lacks is labelled by itself. */
20
20
  export declare function toOptions(values: readonly string[], options: readonly NetworkRuleOption[]): NetworkRuleOption[];
21
+ /** The brand's stored list for `notes`, a metadata field or a free-text condition key. */
22
+ export declare function getSavedPresets(catalog: NetworkRuleCatalog | undefined, field: string): string[];
23
+ /**
24
+ * How long a preset of `field` may be, when the catalog says: the metadata limits bound keys and
25
+ * string values. Notes and condition values have no served limit, so the server has the last word.
26
+ */
27
+ export declare function getPresetMaxLength(catalog: NetworkRuleCatalog | undefined, field: string): number | undefined;
21
28
  /**
22
29
  * Saved suggestions for `notes`, a metadata field or a free-text condition key, followed by any
23
30
  * the user added while editing (`added` is keyed the same way). One merge rule for every caller.