@asteby/metacore-runtime-react 13.2.0 → 13.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 13.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 23d737f: feat(runtime-react): rich declarative line-items — column totals, balance rule, pro layout
8
+
9
+ Makes the declarative form/modal renderer rich enough to replace a custom
10
+ federated modal for line-items entry (e.g. a journal entry's debit/credit grid),
11
+ driven entirely from the manifest:
12
+ - **Totals footer** — any `item_fields` column flagged `total: true` is summed
13
+ across rows and shown in a footer row (`computeLineItemTotals`). Numeric
14
+ columns render right-aligned with `tabular-nums`.
15
+ - **Balance rule** — a `type: "array"` field can declare
16
+ `balance: { debit_column, credit_column, message?, require_nonzero? }`. The
17
+ grid shows a live "Cuadrado" / "Descuadre: N" badge and the form blocks submit
18
+ until `Σ(debit_column) === Σ(credit_column)` (and, by default, > 0). Fully
19
+ generic — debit/credit are just the two column keys to reconcile. Typing a
20
+ value into one reconciled column clears its sibling on the same row.
21
+ - **Pro layout** — `DynamicForm` flows scalar header fields through a responsive
22
+ 2-column grid while line-items grids and textareas span full width, matching
23
+ the look of the hand-written federated journal modal without any custom React.
24
+
25
+ New pure helpers (`computeLineItemTotals`, `evaluateBalance`, `getBalanceRule`,
26
+ `toNumber`) are exported and unit-tested so hosts can reuse the math. Mirrors the
27
+ kernel v3 `ActionField.total` / `ActionField.balance` contract additions.
28
+
29
+ ## 13.3.0
30
+
31
+ ### Minor Changes
32
+
33
+ - 99477d6: feat(runtime-react): add `dynamic_select` field widget — async searchable FK picker
34
+
35
+ Declarative answer to "I don't want to type a raw FK UUID". A field with
36
+ `type: "dynamic_select"` (or `widget: "dynamic_select"`) + `ref` renders a
37
+ typeahead combobox that queries the canonical options endpoint as the user
38
+ types (`GET /api/options/<ref>?field=id&q=<text>&limit=<n>`), reusing
39
+ `useOptionsResolver` (debounced, abortable). Works both as a flat form field
40
+ and as a line-items column cell (e.g. the account_id per debit/credit row of a
41
+ journal entry). The metacore equivalent of 7leguas' `type: search`, driven
42
+ entirely from the manifest — addons get a searchable picker with zero custom
43
+ React, keeping custom federated frontends for genuinely page-level UIs (POS).
44
+
3
45
  ## 13.2.0
4
46
 
5
47
  ### Minor Changes
@@ -17,5 +17,41 @@ export declare function buildZodSchema(fields: ActionFieldDef[]): z.ZodObject<{
17
17
  export declare function getItemFields(field: ActionFieldDef): ActionFieldDef[];
18
18
  /** A field is a repeatable line-items group when it declares item columns. */
19
19
  export declare function isLineItemsField(field: ActionFieldDef): boolean;
20
+ /**
21
+ * Resolves the balance rule of a line-items field, tolerating both the
22
+ * camelCase authored shape and the snake_case the kernel serves. Returns
23
+ * normalized `{ debitColumn, creditColumn, message, requireNonzero }` or
24
+ * `undefined` when the field declares no balance constraint.
25
+ */
26
+ export declare function getBalanceRule(field: ActionFieldDef): {
27
+ debitColumn: string;
28
+ creditColumn: string;
29
+ message?: string;
30
+ requireNonzero: boolean;
31
+ } | undefined;
32
+ /** Coerces a cell value to a finite number, treating blanks/garbage as 0. */
33
+ export declare function toNumber(v: unknown): number;
34
+ /**
35
+ * Sums each `total`-flagged column of a line-items field across its rows.
36
+ * Pure — no React — so the renderer and unit tests share one implementation.
37
+ * Returns a map of column key → summed value. Rounds to cents to avoid float
38
+ * drift (0.1 + 0.2 noise) that would make a genuinely balanced entry look off.
39
+ */
40
+ export declare function computeLineItemTotals(field: ActionFieldDef, rows: any[] | undefined): Record<string, number>;
41
+ export interface BalanceState {
42
+ debit: number;
43
+ credit: number;
44
+ /** credit − debit, rounded to cents. Zero when balanced. */
45
+ diff: number;
46
+ balanced: boolean;
47
+ message?: string;
48
+ }
49
+ /**
50
+ * Evaluates a line-items field's balance rule against its rows. Returns
51
+ * `undefined` when the field declares no balance rule. `balanced` is true when
52
+ * the two summed columns are equal (and, unless `requireNonzero` is false,
53
+ * strictly positive). Pure — drives both the indicator and the submit gate.
54
+ */
55
+ export declare function evaluateBalance(field: ActionFieldDef, rows: any[] | undefined): BalanceState | undefined;
20
56
  export declare function resolveWidget(field: ActionFieldDef): string;
21
57
  //# sourceMappingURL=dynamic-form-schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-form-schema.d.ts","sourceRoot":"","sources":["../src/dynamic-form-schema.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAmB,MAAM,KAAK,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,SAAS,CAAA;AAiB9D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,GAAG,IAAI,CAEzF;AAcD,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE;;kBAMtD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,EAAE,CAGrE;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAE/D;AAqDD,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAU3D"}
1
+ {"version":3,"file":"dynamic-form-schema.d.ts","sourceRoot":"","sources":["../src/dynamic-form-schema.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAmB,MAAM,KAAK,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,SAAS,CAAA;AAiB9D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,GAAG,IAAI,CAEzF;AAcD,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE;;kBAMtD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,EAAE,CAGrE;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC1B,KAAK,EAAE,cAAc,GACtB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAatG;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAO3C;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACjC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,GAAG,EAAE,GAAG,SAAS,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC3B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,GAAG,EAAE,GAAG,SAAS,GACxB,YAAY,GAAG,SAAS,CAgB1B;AAqDD,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAa3D"}
@@ -57,6 +57,83 @@ export function getItemFields(field) {
57
57
  export function isLineItemsField(field) {
58
58
  return getItemFields(field).length > 0;
59
59
  }
60
+ /**
61
+ * Resolves the balance rule of a line-items field, tolerating both the
62
+ * camelCase authored shape and the snake_case the kernel serves. Returns
63
+ * normalized `{ debitColumn, creditColumn, message, requireNonzero }` or
64
+ * `undefined` when the field declares no balance constraint.
65
+ */
66
+ export function getBalanceRule(field) {
67
+ const b = field.balance;
68
+ if (!b)
69
+ return undefined;
70
+ const debitColumn = b.debitColumn ?? b.debit_column ?? '';
71
+ const creditColumn = b.creditColumn ?? b.credit_column ?? '';
72
+ if (!debitColumn || !creditColumn)
73
+ return undefined;
74
+ const reqRaw = b.requireNonzero ?? b.require_nonzero;
75
+ return {
76
+ debitColumn,
77
+ creditColumn,
78
+ message: b.message,
79
+ requireNonzero: reqRaw === undefined ? true : !!reqRaw,
80
+ };
81
+ }
82
+ /** Coerces a cell value to a finite number, treating blanks/garbage as 0. */
83
+ export function toNumber(v) {
84
+ if (typeof v === 'number')
85
+ return Number.isFinite(v) ? v : 0;
86
+ if (typeof v === 'string') {
87
+ const n = parseFloat(v);
88
+ return Number.isFinite(n) ? n : 0;
89
+ }
90
+ return 0;
91
+ }
92
+ /**
93
+ * Sums each `total`-flagged column of a line-items field across its rows.
94
+ * Pure — no React — so the renderer and unit tests share one implementation.
95
+ * Returns a map of column key → summed value. Rounds to cents to avoid float
96
+ * drift (0.1 + 0.2 noise) that would make a genuinely balanced entry look off.
97
+ */
98
+ export function computeLineItemTotals(field, rows) {
99
+ const cols = getItemFields(field).filter((c) => c.total);
100
+ const totals = {};
101
+ for (const c of cols)
102
+ totals[c.key] = 0;
103
+ if (Array.isArray(rows)) {
104
+ for (const row of rows) {
105
+ for (const c of cols)
106
+ totals[c.key] += toNumber(row?.[c.key]);
107
+ }
108
+ }
109
+ for (const k of Object.keys(totals))
110
+ totals[k] = Math.round(totals[k] * 100) / 100;
111
+ return totals;
112
+ }
113
+ /**
114
+ * Evaluates a line-items field's balance rule against its rows. Returns
115
+ * `undefined` when the field declares no balance rule. `balanced` is true when
116
+ * the two summed columns are equal (and, unless `requireNonzero` is false,
117
+ * strictly positive). Pure — drives both the indicator and the submit gate.
118
+ */
119
+ export function evaluateBalance(field, rows) {
120
+ const rule = getBalanceRule(field);
121
+ if (!rule)
122
+ return undefined;
123
+ let debit = 0;
124
+ let credit = 0;
125
+ if (Array.isArray(rows)) {
126
+ for (const row of rows) {
127
+ debit += toNumber(row?.[rule.debitColumn]);
128
+ credit += toNumber(row?.[rule.creditColumn]);
129
+ }
130
+ }
131
+ debit = Math.round(debit * 100) / 100;
132
+ credit = Math.round(credit * 100) / 100;
133
+ const diff = Math.round((credit - debit) * 100) / 100;
134
+ const balanced = diff === 0 && (!rule.requireNonzero || debit > 0);
135
+ return { debit, credit, diff, balanced, message: rule.message };
136
+ }
60
137
  function fieldToZod(field) {
61
138
  // Repeatable line-items group → array of row objects, each row built from
62
139
  // the item field columns. Required keeps at least one row.
@@ -116,6 +193,9 @@ export function resolveWidget(field) {
116
193
  switch (field.type) {
117
194
  case 'textarea': return 'textarea';
118
195
  case 'select': return 'select';
196
+ // Async searchable single-select against /api/options/<ref>. The
197
+ // declarative replacement for typing a raw FK UUID.
198
+ case 'dynamic_select': return 'dynamic_select';
119
199
  case 'boolean': return 'switch';
120
200
  case 'number': return 'number';
121
201
  case 'date': return 'date';
@@ -2,6 +2,7 @@ import type { ActionFieldDef } from './types';
2
2
  import { buildZodSchema, resolveWidget } from './dynamic-form-schema';
3
3
  export { buildZodSchema, resolveWidget };
4
4
  export { DynamicLineItems } from './dynamic-line-items';
5
+ export { DynamicSelectField } from './dynamic-select-field';
5
6
  export interface DynamicFormProps {
6
7
  fields: ActionFieldDef[];
7
8
  initialValues?: Record<string, any>;
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-form.d.ts","sourceRoot":"","sources":["../src/dynamic-form.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAoB,MAAM,uBAAuB,CAAA;AAIvF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,WAAW,CAAC,EACxB,MAAM,EACN,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,WAAuB,EACvB,WAAwB,EACxB,QAAgB,GACnB,EAAE,gBAAgB,2CAoElB"}
1
+ {"version":3,"file":"dynamic-form.d.ts","sourceRoot":"","sources":["../src/dynamic-form.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EACH,cAAc,EACd,aAAa,EAGhB,MAAM,uBAAuB,CAAA;AAK9B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAE3D,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,WAAW,CAAC,EACxB,MAAM,EACN,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,WAAuB,EACvB,WAAwB,EACxB,QAAgB,GACnB,EAAE,gBAAgB,2CAkGlB"}
@@ -4,16 +4,30 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  // outside the full record-edit modal.
5
5
  import { useEffect, useMemo, useState } from 'react';
6
6
  import { Input, Textarea, Label, Switch, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@asteby/metacore-ui/primitives';
7
- import { buildZodSchema, resolveWidget, isLineItemsField } from './dynamic-form-schema';
7
+ import { buildZodSchema, resolveWidget, isLineItemsField, evaluateBalance, } from './dynamic-form-schema';
8
8
  import { useOptionsResolver } from './use-options-resolver';
9
9
  import { DynamicLineItems } from './dynamic-line-items';
10
+ import { DynamicSelectField } from './dynamic-select-field';
10
11
  export { buildZodSchema, resolveWidget };
11
12
  export { DynamicLineItems } from './dynamic-line-items';
13
+ export { DynamicSelectField } from './dynamic-select-field';
12
14
  export function DynamicForm({ fields, initialValues, onSubmit, onCancel, submitLabel = 'Guardar', cancelLabel = 'Cancelar', disabled = false, }) {
13
15
  const [values, setValues] = useState({});
14
16
  const [errors, setErrors] = useState({});
15
17
  const [submitting, setSubmitting] = useState(false);
16
18
  const schema = useMemo(() => buildZodSchema(fields), [fields]);
19
+ // Line-items fields carrying a balance rule gate submit: an unbalanced entry
20
+ // (Σdebit ≠ Σcredit, or all-zero when require_nonzero) can't be saved. This
21
+ // is fully declarative — `evaluateBalance` returns undefined for fields with
22
+ // no rule, so non-balanced forms are unaffected.
23
+ const balanceBlocked = useMemo(() => {
24
+ for (const f of fields) {
25
+ const state = evaluateBalance(f, values[f.key]);
26
+ if (state && !state.balanced)
27
+ return true;
28
+ }
29
+ return false;
30
+ }, [fields, values]);
17
31
  useEffect(() => {
18
32
  const defaults = {};
19
33
  for (const f of fields) {
@@ -29,6 +43,8 @@ export function DynamicForm({ fields, initialValues, onSubmit, onCancel, submitL
29
43
  const update = (k, v) => setValues((prev) => ({ ...prev, [k]: v }));
30
44
  const handleSubmit = async (e) => {
31
45
  e.preventDefault();
46
+ if (balanceBlocked)
47
+ return;
32
48
  const result = schema.safeParse(values);
33
49
  if (!result.success) {
34
50
  const next = {};
@@ -49,7 +65,16 @@ export function DynamicForm({ fields, initialValues, onSubmit, onCancel, submitL
49
65
  setSubmitting(false);
50
66
  }
51
67
  };
52
- return (_jsxs("form", { onSubmit: handleSubmit, className: "grid gap-4", children: [fields.map((field) => (_jsxs("div", { className: "grid gap-2", children: [_jsxs(Label, { htmlFor: field.key, children: [field.label, field.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), _jsx(FieldRenderer, { field: field, value: values[field.key], onChange: (v) => update(field.key, v) }), errors[field.key] && (_jsx("span", { className: "text-red-500 text-sm", role: "alert", children: errors[field.key] }))] }, field.key))), _jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [onCancel && (_jsx(Button, { type: "button", variant: "outline", onClick: onCancel, disabled: submitting || disabled, children: cancelLabel })), _jsx(Button, { type: "submit", disabled: submitting || disabled, children: submitLabel })] })] }));
68
+ // Layout: scalar header fields flow through a responsive 2-column grid;
69
+ // line-items grids (and textareas) span the full width so the row table /
70
+ // memo gets room. Mirrors the pro look of the federated journal modal but
71
+ // stays fully declarative — driven only by field shape.
72
+ return (_jsxs("form", { onSubmit: handleSubmit, className: "grid gap-4", children: [_jsx("div", { className: "grid gap-4 sm:grid-cols-2", children: fields.map((field) => {
73
+ const fullWidth = isLineItemsField(field) ||
74
+ resolveWidget(field) === 'textarea' ||
75
+ resolveWidget(field) === 'richtext';
76
+ return (_jsxs("div", { className: 'grid gap-2 ' + (fullWidth ? 'sm:col-span-2' : ''), children: [_jsxs(Label, { htmlFor: field.key, children: [field.label, field.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), _jsx(FieldRenderer, { field: field, value: values[field.key], onChange: (v) => update(field.key, v) }), errors[field.key] && (_jsx("span", { className: "text-red-500 text-sm", role: "alert", children: errors[field.key] }))] }, field.key));
77
+ }) }), _jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [onCancel && (_jsx(Button, { type: "button", variant: "outline", onClick: onCancel, disabled: submitting || disabled, children: cancelLabel })), _jsx(Button, { type: "submit", disabled: submitting || disabled || balanceBlocked, children: submitLabel })] })] }));
53
78
  }
54
79
  function FieldRenderer({ field, value, onChange }) {
55
80
  // Repeatable line-items group → render the row grid. Its value is an array
@@ -58,6 +83,12 @@ function FieldRenderer({ field, value, onChange }) {
58
83
  return _jsx(DynamicLineItems, { field: field, value: value, onChange: onChange });
59
84
  }
60
85
  const widget = resolveWidget(field);
86
+ // Async searchable picker (typeahead against /api/options/<ref>?q=…).
87
+ // Preferred for FK fields with large option sets — no UUID typing, no
88
+ // dumping every row into a plain <select>.
89
+ if (widget === 'dynamic_select') {
90
+ return _jsx(DynamicSelectField, { field: field, value: value, onChange: onChange });
91
+ }
61
92
  // Ref-driven select: hook into useOptionsResolver so the canonical
62
93
  // /api/options/<ref>?field=id endpoint feeds the dropdown. This is
63
94
  // the path the kernel auto-derives for FK columns; legacy callers
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-line-items.d.ts","sourceRoot":"","sources":["../src/dynamic-line-items.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAI7C,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,EAAE,GAAG,SAAS,CAAA;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACrB;AAUD,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAgB,EAAE,EAAE,qBAAqB,2CAwEnG"}
1
+ {"version":3,"file":"dynamic-line-items.d.ts","sourceRoot":"","sources":["../src/dynamic-line-items.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAW7C,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,EAAE,GAAG,SAAS,CAAA;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACrB;AAkBD,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAgB,EAAE,EAAE,qBAAqB,2CAiJnG"}
@@ -9,9 +9,15 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  // row controls mutate the array; each cell is a widget resolved via
10
10
  // `resolveWidget`, matching the flat-field renderer in dynamic-form.tsx.
11
11
  import { Input, Textarea, Switch, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@asteby/metacore-ui/primitives';
12
- import { Plus, Trash2 } from 'lucide-react';
13
- import { resolveWidget, getItemFields } from './dynamic-form-schema';
12
+ import { Plus, Trash2, Check } from 'lucide-react';
13
+ import { resolveWidget, getItemFields, computeLineItemTotals, evaluateBalance, toNumber, } from './dynamic-form-schema';
14
+ import { DynamicSelectField } from './dynamic-select-field';
14
15
  import { useOptionsResolver } from './use-options-resolver';
16
+ const fmtNumber = (n) => n.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
17
+ /** Numeric columns render right-aligned (debit/credit/amount feel). */
18
+ function isNumericCol(col) {
19
+ return resolveWidget(col) === 'number';
20
+ }
15
21
  function emptyRow(itemFields) {
16
22
  const row = {};
17
23
  for (const f of itemFields) {
@@ -22,10 +28,53 @@ function emptyRow(itemFields) {
22
28
  export function DynamicLineItems({ field, value, onChange, disabled = false }) {
23
29
  const itemFields = getItemFields(field);
24
30
  const rows = Array.isArray(value) ? value : [];
31
+ // Columns flagged `total` get a per-column sum in the footer; the balance
32
+ // rule (if any) reconciles two of them. Both are declarative & generic.
33
+ const totals = computeLineItemTotals(field, rows);
34
+ const totalKeys = itemFields.filter((c) => c.total).map((c) => c.key);
35
+ const hasTotals = totalKeys.length > 0;
36
+ const balance = evaluateBalance(field, rows);
25
37
  const addRow = () => onChange([...rows, emptyRow(itemFields)]);
26
38
  const removeRow = (idx) => onChange(rows.filter((_, i) => i !== idx));
27
39
  const updateCell = (idx, key, cellValue) => onChange(rows.map((r, i) => (i === idx ? { ...r, [key]: cellValue } : r)));
28
- return (_jsxs("div", { className: "grid gap-2", "data-widget": "line_items", children: [_jsx("div", { className: "overflow-x-auto rounded-md border", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted/50", children: _jsxs("tr", { children: [itemFields.map((col) => (_jsxs("th", { className: "px-3 py-2 text-left font-medium", children: [col.label, col.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }, col.key))), _jsx("th", { className: "w-12 px-3 py-2", "aria-label": "acciones" })] }) }), _jsxs("tbody", { children: [rows.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: itemFields.length + 1, className: "px-3 py-4 text-center text-muted-foreground", children: "Sin renglones" }) })), rows.map((row, idx) => (_jsxs("tr", { className: "border-t align-top", children: [itemFields.map((col) => (_jsx("td", { className: "px-2 py-1.5", children: _jsx(CellRenderer, { field: col, value: row?.[col.key], onChange: (v) => updateCell(idx, col.key, v), disabled: disabled }) }, col.key))), _jsx("td", { className: "px-2 py-1.5 text-center", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeRow(idx), disabled: disabled, "aria-label": "Eliminar rengl\u00F3n", children: _jsx(Trash2, { className: "h-4 w-4 text-red-500" }) }) })] }, idx)))] })] }) }), _jsx("div", { children: _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: addRow, disabled: disabled, children: [_jsx(Plus, { className: "mr-1 h-4 w-4" }), "Agregar rengl\u00F3n"] }) })] }));
40
+ // When a balance rule reconciles two columns (e.g. debit credit), typing
41
+ // into one clears the sibling on the same row — mirrors the federated modal
42
+ // UX so a line is never both a debit and a credit.
43
+ const balancePair = balance
44
+ ? (() => {
45
+ const f = getItemFields(field);
46
+ void f;
47
+ const d = field.balance?.debitColumn ?? field.balance?.debit_column;
48
+ const c = field.balance?.creditColumn ?? field.balance?.credit_column;
49
+ return d && c ? [d, c] : null;
50
+ })()
51
+ : null;
52
+ const handleCell = (idx, key, cellValue) => {
53
+ if (balancePair && (key === balancePair[0] || key === balancePair[1])) {
54
+ const sibling = key === balancePair[0] ? balancePair[1] : balancePair[0];
55
+ const hasValue = toNumber(cellValue) > 0;
56
+ onChange(rows.map((r, i) => i === idx ? { ...r, [key]: cellValue, ...(hasValue ? { [sibling]: '' } : {}) } : r));
57
+ return;
58
+ }
59
+ updateCell(idx, key, cellValue);
60
+ };
61
+ return (_jsxs("div", { className: "grid gap-2", "data-widget": "line_items", children: [_jsx("div", { className: "overflow-x-auto rounded-md border", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted/50", children: _jsxs("tr", { children: [itemFields.map((col) => (_jsxs("th", { className: 'px-3 py-2 font-medium ' +
62
+ (isNumericCol(col) ? 'text-right' : 'text-left'), children: [col.label, col.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }, col.key))), _jsx("th", { className: "w-12 px-3 py-2", "aria-label": "acciones" })] }) }), _jsxs("tbody", { children: [rows.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: itemFields.length + 1, className: "px-3 py-4 text-center text-muted-foreground", children: "Sin renglones" }) })), rows.map((row, idx) => (_jsxs("tr", { className: "border-t align-top", children: [itemFields.map((col) => (_jsx("td", { className: "px-2 py-1.5", children: _jsx(CellRenderer, { field: col, value: row?.[col.key], onChange: (v) => handleCell(idx, col.key, v), disabled: disabled }) }, col.key))), _jsx("td", { className: "px-2 py-1.5 text-center", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeRow(idx), disabled: disabled, "aria-label": "Eliminar rengl\u00F3n", children: _jsx(Trash2, { className: "h-4 w-4 text-red-500" }) }) })] }, idx)))] }), hasTotals && rows.length > 0 && (_jsx("tfoot", { className: "border-t bg-muted/30", children: _jsxs("tr", { children: [itemFields.map((col, ci) => {
63
+ if (ci === 0) {
64
+ return (_jsx("td", { className: "px-3 py-2 text-left font-medium text-muted-foreground", children: "Totales" }, col.key));
65
+ }
66
+ return (_jsx("td", { className: 'px-3 py-2 ' +
67
+ (col.total
68
+ ? 'text-right font-semibold tabular-nums'
69
+ : ''), children: col.total ? fmtNumber(totals[col.key] ?? 0) : null }, col.key));
70
+ }), _jsx("td", {})] }) }))] }) }), _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: addRow, disabled: disabled, children: [_jsx(Plus, { className: "mr-1 h-4 w-4" }), "Agregar rengl\u00F3n"] }), balance && _jsx(BalanceBadge, { state: balance })] })] }));
71
+ }
72
+ function BalanceBadge({ state, }) {
73
+ if (state.balanced) {
74
+ return (_jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-md bg-primary/10 px-2.5 py-1 text-sm font-medium text-primary", "data-balance": "balanced", role: "status", children: [_jsx(Check, { className: "h-4 w-4" }), "Cuadrado"] }));
75
+ }
76
+ const diff = Math.abs(state.diff);
77
+ return (_jsx("span", { className: "inline-flex items-center gap-1.5 rounded-md bg-destructive/10 px-2.5 py-1 text-sm font-medium text-destructive", "data-balance": "unbalanced", role: "status", children: state.message ?? `Descuadre: ${fmtNumber(diff)}` }));
29
78
  }
30
79
  // Per-cell widget. Mirrors the flat FieldRenderer in dynamic-form.tsx but
31
80
  // without the per-field Label (the column header is the label) and sized for a
@@ -33,6 +82,11 @@ export function DynamicLineItems({ field, value, onChange, disabled = false }) {
33
82
  // a scalar widget).
34
83
  function CellRenderer({ field, value, onChange, disabled }) {
35
84
  const widget = resolveWidget(field);
85
+ // Async searchable picker per row cell — e.g. the account_id column of a
86
+ // journal entry's debit/credit lines. Same widget as the flat form.
87
+ if (widget === 'dynamic_select') {
88
+ return _jsx(DynamicSelectField, { field: field, value: value, onChange: onChange });
89
+ }
36
90
  if (widget === 'select' && field.ref) {
37
91
  return _jsx(RefCell, { field: field, value: value, onChange: onChange, disabled: disabled });
38
92
  }
@@ -0,0 +1,9 @@
1
+ import type { ActionFieldDef } from './types';
2
+ export interface DynamicSelectFieldProps {
3
+ field: ActionFieldDef;
4
+ value: any;
5
+ onChange: (v: any) => void;
6
+ }
7
+ export declare function DynamicSelectField({ field, value, onChange }: DynamicSelectFieldProps): import("react/jsx-runtime").JSX.Element;
8
+ export default DynamicSelectField;
9
+ //# sourceMappingURL=dynamic-select-field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAW7C,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;CAC7B;AAED,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,uBAAuB,2CA0GrF;AAED,eAAe,kBAAkB,CAAA"}
@@ -0,0 +1,74 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // DynamicSelectField — async, searchable single-select for declarative forms.
3
+ //
4
+ // This is the declarative answer to "I don't want to type a raw FK UUID".
5
+ // Instead of a plain <select> that dumps every option (RefSelect) or a free
6
+ // text input, it renders a typeahead combobox that queries the canonical
7
+ // options endpoint as the user types:
8
+ //
9
+ // GET /api/options/<ref>?field=id&q=<text>&limit=<n>
10
+ //
11
+ // reusing `useOptionsResolver` (which already debounce-aborts in-flight
12
+ // requests). It is the metacore equivalent of 7leguas' `search.go` / dynamic
13
+ // `type: search` field, but driven entirely from the manifest — so an addon
14
+ // declares `type: "dynamic_select"` + `ref` and gets a searchable picker with
15
+ // zero custom React.
16
+ //
17
+ // Resolution path (highest priority first):
18
+ // 1. field.ref → /options/<ref>?field=id (canonical, preferred)
19
+ // 2. field.searchEndpoint→ used verbatim as the options endpoint (escape hatch)
20
+ //
21
+ // Edit-mode caveat: resolving an EXISTING value's label requires the id to be
22
+ // in a fetched page (we match by id against loaded options, else show the raw
23
+ // value). A dedicated `?ids=` lookup is a follow-up; create flows — the common
24
+ // case — start empty and never hit this.
25
+ import { useEffect, useState } from 'react';
26
+ import { Button, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Popover, PopoverContent, PopoverTrigger, } from '@asteby/metacore-ui/primitives';
27
+ import { Check, ChevronsUpDown, Loader2 } from 'lucide-react';
28
+ import { useOptionsResolver } from './use-options-resolver';
29
+ function useDebounced(value, ms) {
30
+ const [debounced, setDebounced] = useState(value);
31
+ useEffect(() => {
32
+ const t = setTimeout(() => setDebounced(value), ms);
33
+ return () => clearTimeout(t);
34
+ }, [value, ms]);
35
+ return debounced;
36
+ }
37
+ export function DynamicSelectField({ field, value, onChange }) {
38
+ const [open, setOpen] = useState(false);
39
+ const [search, setSearch] = useState('');
40
+ const debounced = useDebounced(search, 250);
41
+ // Remember the label of the option the user actually picked so the trigger
42
+ // shows a name (not a UUID) without a round-trip.
43
+ const [picked, setPicked] = useState(null);
44
+ const { options, loading } = useOptionsResolver({
45
+ modelKey: '',
46
+ fieldKey: 'id',
47
+ ref: field.ref,
48
+ // searchEndpoint only drives the URL when there's no ref — ref is the
49
+ // canonical, kernel-derived path and wins.
50
+ endpoint: field.ref ? undefined : field.searchEndpoint,
51
+ query: debounced,
52
+ limit: 20,
53
+ // Don't fetch until the popover opens (and keep fetching as the query
54
+ // changes while open).
55
+ enabled: open,
56
+ });
57
+ const selectedLabel = (picked && String(picked.id) === String(value) ? picked.label : null) ??
58
+ options.find((o) => String(o.id) === String(value))?.label ??
59
+ (value ? String(value) : '');
60
+ const handlePick = (opt) => {
61
+ setPicked(opt);
62
+ onChange(String(opt.id));
63
+ setOpen(false);
64
+ setSearch('');
65
+ };
66
+ return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", role: "combobox", "aria-expanded": open, id: field.key, className: "w-full justify-between font-normal", "data-empty": !value, children: [_jsx("span", { className: 'truncate ' + (selectedLabel ? '' : 'text-muted-foreground'), children: selectedLabel || field.placeholder || 'Buscar…' }), _jsx(ChevronsUpDown, { className: "ml-2 size-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "p-0", align: "start",
67
+ // Match the trigger width without an arbitrary Tailwind class
68
+ // (those don't always survive a consuming app's Tailwind scan).
69
+ style: { width: 'var(--radix-popover-trigger-width)' }, children: _jsxs(Command, { shouldFilter: false, children: [_jsx(CommandInput, { placeholder: field.placeholder || 'Buscar…', value: search, onValueChange: setSearch }), _jsxs(CommandList, { children: [loading && (_jsxs("div", { className: "text-muted-foreground flex items-center justify-center gap-2 py-6 text-sm", children: [_jsx(Loader2, { className: "size-4 animate-spin" }), "Buscando\u2026"] })), !loading && options.length === 0 && (_jsx(CommandEmpty, { children: debounced ? 'Sin resultados' : 'Escribí para buscar…' })), !loading && options.length > 0 && (_jsx(CommandGroup, { className: "max-h-64 overflow-auto", children: options.map((opt) => {
70
+ const isSel = String(opt.id) === String(value);
71
+ return (_jsxs(CommandItem, { value: String(opt.id), onSelect: () => handlePick(opt), children: [_jsx(Check, { className: 'mr-2 size-4 ' + (isSel ? 'opacity-100' : 'opacity-0') }), _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate", children: opt.label }), opt.description && (_jsx("span", { className: "text-muted-foreground truncate text-xs", children: opt.description }))] })] }, String(opt.id)));
72
+ }) }))] })] }) })] }));
73
+ }
74
+ export default DynamicSelectField;
package/dist/types.d.ts CHANGED
@@ -100,7 +100,7 @@ export interface FieldValidation {
100
100
  max?: number;
101
101
  custom?: string;
102
102
  }
103
- export type FieldWidget = 'text' | 'textarea' | 'richtext' | 'color' | 'number' | 'date' | 'select' | 'switch';
103
+ export type FieldWidget = 'text' | 'textarea' | 'richtext' | 'color' | 'number' | 'date' | 'select' | 'dynamic_select' | 'switch';
104
104
  export interface ActionFieldDef {
105
105
  key: string;
106
106
  label: string;
@@ -131,6 +131,39 @@ export interface ActionFieldDef {
131
131
  * keyed by these item field keys. Rendered by `DynamicLineItems`.
132
132
  */
133
133
  itemFields?: ActionFieldDef[];
134
+ /**
135
+ * On an `itemFields` column: flags the column for summation in the
136
+ * line-items footer. The SDK renders a totals row summing every numeric
137
+ * column marked `total` (e.g. the debit and credit columns of a journal
138
+ * entry). Ignored on flat fields. Mirrors kernel v3 `ActionField.total`.
139
+ */
140
+ total?: boolean;
141
+ /**
142
+ * On a line-items (`type: "array"`) field: declares an optional, generic
143
+ * balance constraint between two summed columns. The SDK shows a balanced /
144
+ * out-of-balance indicator and blocks submit until the two sides match.
145
+ * Domain-agnostic — "debit"/"credit" are just the two column keys to
146
+ * reconcile. Mirrors kernel v3 `ActionField.balance`.
147
+ */
148
+ balance?: FieldBalanceRule;
149
+ }
150
+ /**
151
+ * Declarative reconciliation constraint on a line-items field: the summed value
152
+ * of `debitColumn` across all rows must equal the summed value of
153
+ * `creditColumn`. Tolerates the snake_case shape the kernel serves
154
+ * (`debit_column` / `credit_column` / `require_nonzero`). Generic by design.
155
+ */
156
+ export interface FieldBalanceRule {
157
+ debitColumn?: string;
158
+ creditColumn?: string;
159
+ /** snake_case alias served by the kernel manifest. */
160
+ debit_column?: string;
161
+ /** snake_case alias served by the kernel manifest. */
162
+ credit_column?: string;
163
+ message?: string;
164
+ /** When true (default) an all-zero entry is treated as out of balance. */
165
+ requireNonzero?: boolean;
166
+ require_nonzero?: boolean;
134
167
  }
135
168
  export interface ActionDefinition {
136
169
  key: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,cAAc,GAAG,MAAM,CAAA;IACnE,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACrF,cAAc,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjF,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,qBAAqB,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,eAAe,GAAG,OAAO,CAAA;IAC3I,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAC7B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACjC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC3E;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,UAAU,CAAC,EAAE,eAAe,CAAA;CAC/B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAA;IACxC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAC3B;AASD,MAAM,WAAW,eAAe;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AAID,MAAM,MAAM,WAAW,GACjB,MAAM,GACN,UAAU,GACV,UAAU,GACV,OAAO,GACP,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,gBAAgB,GAChB,QAAQ,CAAA;AAEd,MAAM,WAAW,cAAc;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC5C,YAAY,CAAC,EAAE,GAAG,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;IAC7B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,cAAc,EAAE,CAAA;IAC7B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,cAAc,EAAE,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;CACzC;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,CAAC,CAAA;IACP,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CAChB;AAKD,MAAM,WAAW,cAAc;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,cAAc,EAAE,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;CACzC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "13.2.0",
3
+ "version": "13.4.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",