@octaviaflow/core 3.1.0-beta.59 → 3.1.0-beta.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,11 @@ export interface ConditionOperator {
11
11
  symbol?: string;
12
12
  description?: string;
13
13
  }
14
+ export interface ConditionValueOption {
15
+ value: string;
16
+ label: string;
17
+ description?: string;
18
+ }
14
19
  export interface Condition {
15
20
  field: string;
16
21
  operator: string;
@@ -30,6 +35,12 @@ export interface ConditionBuilderProps extends Omit<ComponentPropsWithoutRef<"di
30
35
  onChange: (conditions: Condition[]) => void;
31
36
  fields: ConditionField[];
32
37
  operators: ConditionOperator[];
38
+ /** Optional per-row value suggestions. When this returns a non-empty list
39
+ * for a condition, that row's value field becomes an editable combobox: a
40
+ * free-text input with an attached dropdown button listing the options —
41
+ * clicking one fills the input, and the user can still type any value not in
42
+ * the list. Omit / return [] to keep a plain text input. */
43
+ getValueOptions?: (condition: Condition, index: number) => ConditionValueOption[];
33
44
  /** Auto-enables search above 8 options. Force on/off via boolean. */
34
45
  searchable?: boolean;
35
46
  allowGroups?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"ConditionBuilder.d.ts","sourceRoot":"","sources":["../../../src/components/ConditionBuilder/ConditionBuilder.tsx"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,wBAAwB,EAG7B,KAAK,SAAS,EAQf,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd;;4DAEwD;IACxD,YAAY,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,KAAK,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,CAAC,SAAS,GAAG,cAAc,CAAC,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACzD,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5C,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,qEAAqE;IACrE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC;4EACwE;IACxE,YAAY,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IAC5B;yEACqE;IACrE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5C,mDAAmD;IACnD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;mEAI+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA0OD,eAAO,MAAM,gBAAgB,kHA+M3B,CAAC"}
1
+ {"version":3,"file":"ConditionBuilder.d.ts","sourceRoot":"","sources":["../../../src/components/ConditionBuilder/ConditionBuilder.tsx"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,wBAAwB,EAG7B,KAAK,SAAS,EAQf,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd;;4DAEwD;IACxD,YAAY,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,KAAK,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,CAAC,SAAS,GAAG,cAAc,CAAC,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACzD,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5C,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B;;;;iEAI6D;IAC7D,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,KAAK,oBAAoB,EAAE,CAAC;IAClF,qEAAqE;IACrE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC;4EACwE;IACxE,YAAY,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IAC5B;yEACqE;IACrE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5C,mDAAmD;IACnD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;mEAI+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAiYD,eAAO,MAAM,gBAAgB,kHA4N3B,CAAC"}
@@ -1,2 +1,2 @@
1
- export { type Condition, ConditionBuilder, type ConditionBuilderProps, type ConditionField, type ConditionOperator, } from "./ConditionBuilder";
1
+ export { type Condition, ConditionBuilder, type ConditionBuilderProps, type ConditionField, type ConditionOperator, type ConditionValueOption, } from "./ConditionBuilder";
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ConditionBuilder/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EACd,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ConditionBuilder/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EACd,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC"}
package/dist/index.cjs CHANGED
@@ -9076,11 +9076,155 @@ function OptionDropdown({
9076
9076
  )
9077
9077
  ] });
9078
9078
  }
9079
+ function ValueCombobox({ value, options, onChange, placeholder = "Value", ariaLabel }) {
9080
+ const [open, setOpen] = (0, import_react59.useState)(false);
9081
+ const [activeIdx, setActiveIdx] = (0, import_react59.useState)(0);
9082
+ const wrapRef = (0, import_react59.useRef)(null);
9083
+ const inputRef = (0, import_react59.useRef)(null);
9084
+ const panelRef = (0, import_react59.useRef)(null);
9085
+ const listboxId = (0, import_react59.useId)();
9086
+ const [panelPos, setPanelPos] = (0, import_react59.useState)(null);
9087
+ const updatePanelPos = (0, import_react59.useCallback)(() => {
9088
+ if (!wrapRef.current) return;
9089
+ const r = wrapRef.current.getBoundingClientRect();
9090
+ setPanelPos({ top: r.bottom + 4, left: r.left, width: r.width });
9091
+ }, []);
9092
+ (0, import_react59.useLayoutEffect)(() => {
9093
+ if (!open) return;
9094
+ updatePanelPos();
9095
+ window.addEventListener("scroll", updatePanelPos, true);
9096
+ window.addEventListener("resize", updatePanelPos);
9097
+ return () => {
9098
+ window.removeEventListener("scroll", updatePanelPos, true);
9099
+ window.removeEventListener("resize", updatePanelPos);
9100
+ };
9101
+ }, [open, updatePanelPos]);
9102
+ const filtered = (0, import_react59.useMemo)(() => {
9103
+ const q2 = value.trim().toLowerCase();
9104
+ if (!q2) return options;
9105
+ return options.filter(
9106
+ (o) => o.label.toLowerCase().includes(q2) || o.value.toLowerCase().includes(q2)
9107
+ );
9108
+ }, [options, value]);
9109
+ (0, import_react59.useEffect)(() => {
9110
+ setActiveIdx(0);
9111
+ }, [value, open]);
9112
+ (0, import_react59.useEffect)(() => {
9113
+ if (!open) return;
9114
+ const onDoc = (e) => {
9115
+ const t = e.target;
9116
+ if (!wrapRef.current?.contains(t) && !panelRef.current?.contains(t)) setOpen(false);
9117
+ };
9118
+ document.addEventListener("mousedown", onDoc);
9119
+ return () => document.removeEventListener("mousedown", onDoc);
9120
+ }, [open]);
9121
+ const pick = (v) => {
9122
+ onChange(v);
9123
+ setOpen(false);
9124
+ inputRef.current?.focus();
9125
+ };
9126
+ const handleKey = (e) => {
9127
+ if (e.key === "ArrowDown") {
9128
+ e.preventDefault();
9129
+ if (!open) {
9130
+ setOpen(true);
9131
+ return;
9132
+ }
9133
+ setActiveIdx((i) => Math.min(i + 1, Math.max(filtered.length - 1, 0)));
9134
+ } else if (e.key === "ArrowUp") {
9135
+ if (!open) return;
9136
+ e.preventDefault();
9137
+ setActiveIdx((i) => Math.max(i - 1, 0));
9138
+ } else if (e.key === "Enter") {
9139
+ if (open && filtered[activeIdx]) {
9140
+ e.preventDefault();
9141
+ pick(filtered[activeIdx].value);
9142
+ }
9143
+ } else if (e.key === "Escape") {
9144
+ if (open) {
9145
+ e.preventDefault();
9146
+ setOpen(false);
9147
+ }
9148
+ }
9149
+ };
9150
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { ref: wrapRef, className: "ods-cb-combo", onKeyDown: handleKey, children: [
9151
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9152
+ "input",
9153
+ {
9154
+ ref: inputRef,
9155
+ type: "text",
9156
+ className: "ods-cb-combo__input",
9157
+ value,
9158
+ onChange: (e) => {
9159
+ onChange(e.target.value);
9160
+ if (!open) setOpen(true);
9161
+ },
9162
+ placeholder,
9163
+ "aria-label": ariaLabel,
9164
+ role: "combobox",
9165
+ "aria-expanded": open,
9166
+ "aria-controls": open ? listboxId : void 0,
9167
+ "aria-autocomplete": "list"
9168
+ }
9169
+ ),
9170
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9171
+ "button",
9172
+ {
9173
+ type: "button",
9174
+ className: cn("ods-cb-combo__toggle", open && "ods-cb-combo__toggle--open"),
9175
+ onClick: () => {
9176
+ setOpen((o) => !o);
9177
+ inputRef.current?.focus();
9178
+ },
9179
+ "aria-label": `${ariaLabel} options`,
9180
+ "aria-haspopup": "listbox",
9181
+ "aria-expanded": open,
9182
+ tabIndex: -1,
9183
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_icons9.ChevronDownIcon, { "aria-hidden": "true", className: "ods-cb-combo__chev" })
9184
+ }
9185
+ ),
9186
+ open && panelPos && typeof document !== "undefined" && (0, import_react_dom5.createPortal)(
9187
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9188
+ "div",
9189
+ {
9190
+ ref: panelRef,
9191
+ className: "ods-cb-dd__panel ods-cb-dd__panel--portal",
9192
+ role: "presentation",
9193
+ style: { position: "fixed", top: panelPos.top, left: panelPos.left, minWidth: panelPos.width },
9194
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("ul", { id: listboxId, role: "listbox", "aria-label": ariaLabel, className: "ods-cb-dd__list", children: [
9195
+ filtered.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { className: "ods-cb-dd__empty", children: "Type a custom value" }),
9196
+ filtered.map((opt, idx) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
9197
+ "button",
9198
+ {
9199
+ type: "button",
9200
+ role: "option",
9201
+ "aria-selected": opt.value === value,
9202
+ className: cn(
9203
+ "ods-cb-dd__opt",
9204
+ opt.value === value && "ods-cb-dd__opt--selected",
9205
+ idx === activeIdx && "ods-cb-dd__opt--active"
9206
+ ),
9207
+ onClick: () => pick(opt.value),
9208
+ onMouseEnter: () => setActiveIdx(idx),
9209
+ children: [
9210
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "ods-cb-dd__opt-text", children: opt.label }),
9211
+ opt.description && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "ods-cb-dd__opt-desc", children: opt.description })
9212
+ ]
9213
+ }
9214
+ ) }, opt.value))
9215
+ ] })
9216
+ }
9217
+ ),
9218
+ document.body
9219
+ )
9220
+ ] });
9221
+ }
9079
9222
  var ConditionBuilder = (0, import_react59.forwardRef)(function ConditionBuilder2({
9080
9223
  conditions,
9081
9224
  onChange,
9082
9225
  fields,
9083
9226
  operators,
9227
+ getValueOptions,
9084
9228
  searchable,
9085
9229
  joinMode = "global",
9086
9230
  joinOperator = "AND",
@@ -9213,17 +9357,28 @@ var ConditionBuilder = (0, import_react59.forwardRef)(function ConditionBuilder2
9213
9357
  minWidth: 140
9214
9358
  }
9215
9359
  ),
9216
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9217
- "input",
9218
- {
9219
- type: "text",
9220
- className: "ods-condition-row__value",
9221
- value: condition.value,
9222
- onChange: (e) => handleValueChange(index, e.target.value),
9223
- placeholder: "Value",
9224
- "aria-label": "Value"
9225
- }
9226
- ),
9360
+ (() => {
9361
+ const valueOpts = getValueOptions?.(condition, index) ?? [];
9362
+ return valueOpts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9363
+ ValueCombobox,
9364
+ {
9365
+ ariaLabel: "Value",
9366
+ value: condition.value,
9367
+ options: valueOpts,
9368
+ onChange: (v) => handleValueChange(index, v)
9369
+ }
9370
+ ) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9371
+ "input",
9372
+ {
9373
+ type: "text",
9374
+ className: "ods-condition-row__value",
9375
+ value: condition.value,
9376
+ onChange: (e) => handleValueChange(index, e.target.value),
9377
+ placeholder: "Value",
9378
+ "aria-label": "Value"
9379
+ }
9380
+ );
9381
+ })(),
9227
9382
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9228
9383
  "button",
9229
9384
  {