@asteby/metacore-runtime-react 9.0.0 → 9.2.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 (46) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/column-visibility.d.ts +22 -0
  3. package/dist/column-visibility.d.ts.map +1 -0
  4. package/dist/column-visibility.js +40 -0
  5. package/dist/dynamic-columns.d.ts.map +1 -1
  6. package/dist/dynamic-columns.js +4 -1
  7. package/dist/dynamic-form-schema.d.ts +5 -0
  8. package/dist/dynamic-form-schema.d.ts.map +1 -1
  9. package/dist/dynamic-form-schema.js +34 -0
  10. package/dist/dynamic-form.d.ts.map +1 -1
  11. package/dist/dynamic-form.js +18 -2
  12. package/dist/dynamic-relation.d.ts.map +1 -1
  13. package/dist/dynamic-relation.js +59 -22
  14. package/dist/dynamic-table.d.ts.map +1 -1
  15. package/dist/dynamic-table.js +17 -3
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +4 -0
  19. package/dist/types.d.ts +44 -0
  20. package/dist/types.d.ts.map +1 -1
  21. package/dist/use-options-resolver.d.ts +87 -0
  22. package/dist/use-options-resolver.d.ts.map +1 -0
  23. package/dist/use-options-resolver.js +147 -0
  24. package/dist/use-org-config-bridge.d.ts +28 -0
  25. package/dist/use-org-config-bridge.d.ts.map +1 -0
  26. package/dist/use-org-config-bridge.js +50 -0
  27. package/package.json +3 -2
  28. package/src/__tests__/column-visibility.test.ts +116 -0
  29. package/src/__tests__/use-options-resolver.test.ts +127 -0
  30. package/src/column-visibility.ts +43 -0
  31. package/src/dynamic-columns.tsx +4 -1
  32. package/src/dynamic-form-schema.ts +36 -0
  33. package/src/dynamic-form.tsx +40 -2
  34. package/src/dynamic-relation.tsx +55 -20
  35. package/src/dynamic-table.tsx +20 -2
  36. package/src/index.ts +19 -0
  37. package/src/types.ts +49 -0
  38. package/src/use-options-resolver.ts +232 -0
  39. package/src/use-org-config-bridge.ts +60 -0
  40. package/tsconfig.json +2 -1
  41. package/dist/__tests__/dynamic-form.test.d.ts +0 -2
  42. package/dist/__tests__/dynamic-form.test.d.ts.map +0 -1
  43. package/dist/__tests__/dynamic-form.test.js +0 -93
  44. package/dist/__tests__/dynamic-relation.test.d.ts +0 -2
  45. package/dist/__tests__/dynamic-relation.test.d.ts.map +0 -1
  46. package/dist/__tests__/dynamic-relation.test.js +0 -228
package/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 9.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 150a907: feat: useOptionsResolver hook + locale-aware Validation via OrgConfigProvider
8
+
9
+ **runtime-react:**
10
+ - New `useOptionsResolver(args)` hook that consumes the v0.9.0 kernel
11
+ envelope `{ success, data, meta: { type, count } }` from
12
+ `GET /api/options/:model?field=…`. Replaces the ad-hoc `/data/<model>`
13
+ reads `<DynamicRelation>` used to do.
14
+ - `<DynamicForm>` now renders a Ref-driven `<RefSelect>` whenever an
15
+ `ActionFieldDef.ref` is present — apps stop hardcoding option lists for
16
+ belongs_to FKs.
17
+ - `<DynamicRelation>` (kind="many_to_many") prefers the canonical options
18
+ endpoint via `useOptionsResolver`. The legacy `referencesEndpoint` prop
19
+ remains a working escape hatch for apps wired against custom routes.
20
+ - `ColumnDefinition.ref` and `ColumnDefinition.validation` are now part of
21
+ the metadata contract the SDK reads. `ActionFieldDef.ref` joins the
22
+ field-level type so addons can declare ref-aware modal fields.
23
+ - New `setOrgConfigBridge` / `resolveValidatorToken` surface lets apps
24
+ feed a `useOrgConfig`-backed resolver into the SDK's validator
25
+ pipeline. Validators with `custom: '$org.<key>'` are resolved at form
26
+ build time; unresolved tokens degrade to no-op so missing config does
27
+ not crash forms.
28
+ - New `registerValidator(slug, fn)` lets apps install their own
29
+ region-specific validators (e.g. `mx.rfc`, `co.nit`) without leaking
30
+ fiscal vocabulary into the SDK.
31
+
32
+ **app-providers:**
33
+ - New `OrgConfigProvider` + `useOrgConfig()` companion to
34
+ `PlatformConfigProvider`. Apps wire a per-org config fetcher and the
35
+ provider exposes typed `currency`, `locale`, `validators` plus a
36
+ `resolveValidator(refOrKey)` helper for the `$org.<key>` reference
37
+ contract the kernel ≥ v0.9.0 emits.
38
+
39
+ ## 9.1.0
40
+
41
+ ### Minor Changes
42
+
43
+ - 2e50839: feat(runtime-react): leer `visibility` y `searchable` en metadata de columnas.
44
+ - `ColumnDefinition` tipa los nuevos campos `visibility?` (`"all" | "table" | "modal" | "list"`) y `searchable?` que el kernel ya emite (`manifest.ColumnDef`). Backwards compat: zero-value preserva el comportamiento previo.
45
+ - `<DynamicTable>` ahora oculta del listado las columnas con `visibility === "modal"` (y `"list"`) además del legacy `hidden`. Las columnas sin `visibility` o con `"all" | "table"` siguen visibles.
46
+ - Cuando al menos una columna declara `searchable` el SDK acota el global search a esas columnas vía el nuevo query param `search_columns=<keys>`. Si todas las columnas se opt-out (`searchable: false`), el SDK deja de mandar `search` al backend. Si ninguna columna trae el flag (kernel anterior a v0.8.x), no se cambia nada.
47
+ - Nuevos helpers públicos `isColumnVisibleInTable(col)` y `getSearchableColumnKeys(metadata)` exportados desde el barrel; tests con metadata mock cubren los pasos legacy + opt-in + opt-out total.
48
+
3
49
  ## 9.0.0
4
50
 
5
51
  ### Minor Changes
@@ -0,0 +1,22 @@
1
+ import type { ColumnDefinition, TableMetadata } from './types';
2
+ /**
3
+ * Whether a column should render in a list/index table view.
4
+ *
5
+ * A column is hidden when its `visibility` is scoped away from the table
6
+ * (`'modal'`: only the create/edit dialog; `'list'`: only API payloads) or
7
+ * when the legacy `hidden` boolean is set. Empty / `'all'` / `'table'` keep
8
+ * the column visible — preserving zero-value behaviour for metadata emitted
9
+ * by older kernels that don't set `visibility` at all.
10
+ */
11
+ export declare function isColumnVisibleInTable(col: ColumnDefinition): boolean;
12
+ /**
13
+ * Returns the keys of columns that opt into the model's full-text search,
14
+ * or `null` when no column declares `searchable` at all.
15
+ *
16
+ * `null` is the legacy signal: the host should NOT narrow the search request
17
+ * (every column participates, matching pre-Searchable kernels). An empty
18
+ * array is meaningful — it means every column has been explicitly opted out
19
+ * and the host should disable the global search input.
20
+ */
21
+ export declare function getSearchableColumnKeys(metadata: Pick<TableMetadata, 'columns'>): string[] | null;
22
+ //# sourceMappingURL=column-visibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-visibility.d.ts","sourceRoot":"","sources":["../src/column-visibility.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAKrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACnC,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GACzC,MAAM,EAAE,GAAG,IAAI,CAKjB"}
@@ -0,0 +1,40 @@
1
+ // Pure helpers that map kernel `manifest.ColumnDef` metadata flags
2
+ // (Visibility, Searchable) into client-side decisions:
3
+ // - which columns the dynamic table should render
4
+ // - which column keys are in scope for the global search
5
+ //
6
+ // Kept side-effect free and free of React/UI imports so the same logic can
7
+ // be tested with plain unit tests against mock metadata.
8
+ /**
9
+ * Whether a column should render in a list/index table view.
10
+ *
11
+ * A column is hidden when its `visibility` is scoped away from the table
12
+ * (`'modal'`: only the create/edit dialog; `'list'`: only API payloads) or
13
+ * when the legacy `hidden` boolean is set. Empty / `'all'` / `'table'` keep
14
+ * the column visible — preserving zero-value behaviour for metadata emitted
15
+ * by older kernels that don't set `visibility` at all.
16
+ */
17
+ export function isColumnVisibleInTable(col) {
18
+ if (col.hidden)
19
+ return false;
20
+ const v = col.visibility;
21
+ if (!v)
22
+ return true;
23
+ return v === 'all' || v === 'table';
24
+ }
25
+ /**
26
+ * Returns the keys of columns that opt into the model's full-text search,
27
+ * or `null` when no column declares `searchable` at all.
28
+ *
29
+ * `null` is the legacy signal: the host should NOT narrow the search request
30
+ * (every column participates, matching pre-Searchable kernels). An empty
31
+ * array is meaningful — it means every column has been explicitly opted out
32
+ * and the host should disable the global search input.
33
+ */
34
+ export function getSearchableColumnKeys(metadata) {
35
+ const cols = metadata.columns ?? [];
36
+ const declared = cols.some(c => typeof c.searchable === 'boolean');
37
+ if (!declared)
38
+ return null;
39
+ return cols.filter(c => c.searchable === true).map(c => c.key);
40
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAER,iBAAiB,EACpB,MAAM,wBAAwB,CAAA;AAE/B,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAwHD;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,OAAO,GAAE,qBAA0B,GACpC,iBAAiB,CAmXnB;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBACL,CAAA"}
1
+ {"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAER,iBAAiB,EACpB,MAAM,wBAAwB,CAAA;AAE/B,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAwHD;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,OAAO,GAAE,qBAA0B,GACpC,iBAAiB,CAqXnB;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBACL,CAAA"}
@@ -18,6 +18,7 @@ import { DataTableColumnHeader, FilterableColumnHeader, } from '@asteby/metacore
18
18
  import { generateBadgeStyles, getInitials } from '@asteby/metacore-ui/lib';
19
19
  import { OptionsContext } from './options-context';
20
20
  import { DynamicIcon } from './dynamic-icon';
21
+ import { isColumnVisibleInTable } from './column-visibility';
21
22
  const defaultGetImageUrl = (path) => path;
22
23
  const getNestedValue = (obj, path) => path.split('.').reduce((acc, part) => acc && acc[part], obj);
23
24
  const lowerFirst = (value) => {
@@ -123,7 +124,9 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
123
124
  },
124
125
  ];
125
126
  metadata.columns.forEach((col) => {
126
- if (col.hidden)
127
+ // Honors both the legacy `hidden` boolean and the kernel's
128
+ // `visibility` scope (skips `'modal'` and `'list'`).
129
+ if (!isColumnVisibleInTable(col))
127
130
  return;
128
131
  const translatedLabel = col.label;
129
132
  const filterConfig = filterConfigs?.get(col.key);
@@ -1,5 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import type { ActionFieldDef } from './types';
3
+ /**
4
+ * Apps register validator implementations by slug. The slug is the value
5
+ * `OrgConfig.validators[<key>]` returns for a $org.<key> reference.
6
+ */
7
+ export declare function registerValidator(slug: string, fn: (s: z.ZodString) => z.ZodString): void;
3
8
  export declare function buildZodSchema(fields: ActionFieldDef[]): z.ZodObject<{
4
9
  [x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
5
10
  }, z.core.$strip>;
@@ -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;AAM9D,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE;;kBAMtD;AAuCD,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;AA4CD,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAU3D"}
@@ -2,6 +2,36 @@
2
2
  // callers (and unit tests) can use the zod schema without pulling in React or
3
3
  // metacore-ui primitives.
4
4
  import { z } from 'zod';
5
+ import { resolveValidatorToken } from './use-org-config-bridge';
6
+ /**
7
+ * Built-in validators the SDK knows how to apply by symbolic name. Apps
8
+ * that wire `OrgConfigProvider` map `$org.<key>` references to one of
9
+ * these slugs (or to a custom slug they register). Unknown slugs are a
10
+ * no-op so unresolved $org references degrade to "no extra check"
11
+ * rather than a runtime crash — matches the kernel's pass-through
12
+ * semantics for unresolved references.
13
+ */
14
+ const builtinValidators = {
15
+ // The SDK ships ZERO fiscal vocabulary by default. Apps register
16
+ // their own validators (mx.rfc, co.nit, pe.ruc, etc.) via
17
+ // `registerValidator` so kernel/SDK stay region-agnostic.
18
+ };
19
+ /**
20
+ * Apps register validator implementations by slug. The slug is the value
21
+ * `OrgConfig.validators[<key>]` returns for a $org.<key> reference.
22
+ */
23
+ export function registerValidator(slug, fn) {
24
+ builtinValidators[slug] = fn;
25
+ }
26
+ function applyCustomValidator(s, customToken) {
27
+ if (!customToken)
28
+ return s;
29
+ const resolved = resolveValidatorToken(customToken);
30
+ if (!resolved)
31
+ return s;
32
+ const fn = builtinValidators[resolved];
33
+ return fn ? fn(s) : s;
34
+ }
5
35
  // Builds a zod object schema from an ActionFieldDef[]. Required fields stay
6
36
  // non-empty; optional fields accept undefined / "". Validation rules
7
37
  // (regex/min/max) layer on top: for numeric columns they bound the value, for
@@ -46,6 +76,10 @@ function fieldToZod(field) {
46
76
  s = s.email('Email inválido');
47
77
  if (field.type === 'url')
48
78
  s = s.url('URL inválida');
79
+ // Custom validator: a literal slug (`mx.rfc`) OR a `$org.<key>`
80
+ // reference resolved through the OrgConfigProvider. Unknown slugs
81
+ // pass through as no-ops so apps never crash on missing config.
82
+ s = applyCustomValidator(s, v.custom);
49
83
  if (field.required) {
50
84
  return s.min(Math.max(typeof v.min === 'number' ? v.min : 1, 1), `${field.label} es requerido`);
51
85
  }
@@ -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,EAAE,MAAM,uBAAuB,CAAA;AAErE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;AAExC,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,2CA4DlB"}
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,EAAE,MAAM,uBAAuB,CAAA;AAGrE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;AAExC,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,2CAgElB"}
@@ -5,6 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
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
7
  import { buildZodSchema, resolveWidget } from './dynamic-form-schema';
8
+ import { useOptionsResolver } from './use-options-resolver';
8
9
  export { buildZodSchema, resolveWidget };
9
10
  export function DynamicForm({ fields, initialValues, onSubmit, onCancel, submitLabel = 'Guardar', cancelLabel = 'Cancelar', disabled = false, }) {
10
11
  const [values, setValues] = useState({});
@@ -42,10 +43,17 @@ export function DynamicForm({ fields, initialValues, onSubmit, onCancel, submitL
42
43
  setSubmitting(false);
43
44
  }
44
45
  };
45
- 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: "*" })] }), renderField(field, values[field.key], (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 })] })] }));
46
+ 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 })] })] }));
46
47
  }
47
- function renderField(field, value, onChange) {
48
+ function FieldRenderer({ field, value, onChange }) {
48
49
  const widget = resolveWidget(field);
50
+ // Ref-driven select: hook into useOptionsResolver so the canonical
51
+ // /api/options/<ref>?field=id endpoint feeds the dropdown. This is
52
+ // the path the kernel auto-derives for FK columns; legacy callers
53
+ // shipping inline `options` keep working in the branch below.
54
+ if (widget === 'select' && field.ref) {
55
+ return _jsx(RefSelect, { field: field, value: value, onChange: onChange });
56
+ }
49
57
  switch (widget) {
50
58
  case 'textarea':
51
59
  return _jsx(Textarea, { id: field.key, value: value || '', onChange: (e) => onChange(e.target.value), placeholder: field.placeholder });
@@ -68,3 +76,11 @@ function renderField(field, value, onChange) {
68
76
  return _jsx(Input, { id: field.key, type: field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : 'text', value: value || '', onChange: (e) => onChange(e.target.value), placeholder: field.placeholder });
69
77
  }
70
78
  }
79
+ function RefSelect({ field, value, onChange }) {
80
+ const { options, loading } = useOptionsResolver({
81
+ modelKey: '', // unused — `ref` drives the URL
82
+ fieldKey: 'id',
83
+ ref: field.ref,
84
+ });
85
+ return (_jsxs(Select, { value: value || '', onValueChange: onChange, disabled: loading, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: loading ? 'Cargando…' : (field.placeholder || 'Seleccionar...') }) }), _jsx(SelectContent, { children: options.map((opt) => (_jsx(SelectItem, { value: String(opt.id), children: opt.label }, String(opt.id)))) })] }));
86
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-relation.d.ts","sourceRoot":"","sources":["../src/dynamic-relation.tsx"],"names":[],"mappings":"AAyCA,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EACH,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,aAAa,EACb,wBAAwB,EACxB,eAAe,EACf,cAAc,GACjB,MAAM,4BAA4B,CAAA;AAEnC,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,wBAAwB,EAAE,MAAM,CAAA;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB,EAAE,MAAM,CAAA;IACzB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,WAAW,EAAE,MAAM,CAAA;CACtB;AAiBD,UAAU,WAAW;IACjB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACzC,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,6BAA8B,SAAQ,WAAW;IAC9D,IAAI,EAAE,aAAa,CAAA;IACnB,yFAAyF;IACzF,KAAK,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAA;IAClB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,8BAA+B,SAAQ,WAAW;IAC/D,IAAI,EAAE,cAAc,CAAA;IACpB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;IACf,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAA;IAClB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,MAAM,oBAAoB,GAC1B,6BAA6B,GAC7B,8BAA8B,CAAA;AAEpC,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,2CAK1D"}
1
+ {"version":3,"file":"dynamic-relation.d.ts","sourceRoot":"","sources":["../src/dynamic-relation.tsx"],"names":[],"mappings":"AA0CA,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EACH,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,aAAa,EACb,wBAAwB,EACxB,eAAe,EACf,cAAc,GACjB,MAAM,4BAA4B,CAAA;AAEnC,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,wBAAwB,EAAE,MAAM,CAAA;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB,EAAE,MAAM,CAAA;IACzB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,WAAW,EAAE,MAAM,CAAA;CACtB;AAiBD,UAAU,WAAW;IACjB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACzC,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,6BAA8B,SAAQ,WAAW;IAC9D,IAAI,EAAE,aAAa,CAAA;IACnB,yFAAyF;IACzF,KAAK,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAA;IAClB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,8BAA+B,SAAQ,WAAW;IAC/D,IAAI,EAAE,cAAc,CAAA;IACpB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;IACf,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAA;IAClB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,MAAM,oBAAoB,GAC1B,6BAA6B,GAC7B,8BAA8B,CAAA;AAEpC,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,2CAK1D"}
@@ -10,6 +10,7 @@ import { Plus, Trash2, Pencil } from 'lucide-react';
10
10
  import { useApi } from './api-context';
11
11
  import { useMetadataCache } from './metadata-cache';
12
12
  import { DynamicForm } from './dynamic-form';
13
+ import { useOptionsResolver } from './use-options-resolver';
13
14
  import { buildCreatePayload, buildPivotAttachPayload, buildPivotRowIndex, buildRelationFilterParams, deriveRelationFormFields, diffSelection, extractSelectedTargetIds, pickOptionLabel, relationRowKey, } from './dynamic-relation-helpers';
14
15
  export { buildCreatePayload, buildPivotAttachPayload, buildPivotRowIndex, buildRelationFilterParams, deriveRelationFormFields, diffSelection, extractSelectedTargetIds, pickOptionLabel, relationRowKey, } from './dynamic-relation-helpers';
15
16
  const DEFAULT_STRINGS = {
@@ -140,33 +141,58 @@ function ManyToManyRelation({ kind, through, references, foreignKey, referencesK
140
141
  const labels = { ...DEFAULT_STRINGS, ...(strings || {}) };
141
142
  const refKey = referencesKey || `${references}_id`;
142
143
  const pivotPath = pivotEndpoint || `/data/${through}`;
143
- const targetPath = referencesEndpoint || `/data/${references}`;
144
+ // referencesEndpoint is preserved as a legacy escape hatch — when set
145
+ // we keep the old `/data/<references>` raw fetch path (so apps that
146
+ // depend on a custom server route do not break). When unset we use
147
+ // the canonical `/api/options/:references` endpoint via
148
+ // useOptionsResolver, which is what the kernel auto-derives Ref to.
149
+ const useResolver = !referencesEndpoint;
150
+ const legacyTargetPath = referencesEndpoint || `/data/${references}`;
144
151
  const cachedTargetMeta = getMetadata(references);
145
152
  const [targetMeta, setTargetMeta] = useState(cachedTargetMeta || null);
146
153
  const [targetRows, setTargetRows] = useState([]);
147
154
  const [pivotRows, setPivotRows] = useState([]);
148
155
  const [loading, setLoading] = useState(true);
149
156
  const [syncing, setSyncing] = useState(false);
150
- const fetchAll = useCallback(async () => {
157
+ // Canonical path: SDK options resolver. Only fires when no legacy
158
+ // override is set. The hook is a no-op when `useResolver` is false.
159
+ const resolved = useOptionsResolver({
160
+ modelKey: '',
161
+ fieldKey: 'id',
162
+ ref: useResolver ? references : undefined,
163
+ enabled: useResolver,
164
+ });
165
+ const fetchPivotAndMeta = useCallback(async () => {
151
166
  setLoading(true);
152
167
  try {
153
168
  const params = buildRelationFilterParams(foreignKey, parentId);
154
- const [metaRes, pivotRes, targetRes] = await Promise.all([
155
- targetMeta ? Promise.resolve(null) : api.get(`/metadata/table/${references}`),
169
+ const tasks = [
156
170
  api.get(pivotPath, { params }),
157
- api.get(targetPath),
158
- ]);
159
- if (metaRes && metaRes.data?.success) {
160
- const fresh = metaRes.data.data;
161
- setTargetMeta(fresh);
162
- cacheMetadata(references, fresh);
171
+ ];
172
+ if (!targetMeta)
173
+ tasks.push(api.get(`/metadata/table/${references}`));
174
+ // Legacy fallback path: the resolver is disabled, fetch the
175
+ // target rows the old way so callers that depend on a custom
176
+ // route keep working.
177
+ if (!useResolver)
178
+ tasks.push(api.get(legacyTargetPath));
179
+ const results = await Promise.all(tasks);
180
+ const pivotRes = results[0];
181
+ if (pivotRes.data.success)
182
+ setPivotRows(pivotRes.data.data || []);
183
+ let cursor = 1;
184
+ if (!targetMeta) {
185
+ const metaRes = results[cursor++];
186
+ if (metaRes.data?.success) {
187
+ setTargetMeta(metaRes.data.data);
188
+ cacheMetadata(references, metaRes.data.data);
189
+ }
190
+ }
191
+ if (!useResolver) {
192
+ const targetRes = results[cursor++];
193
+ if (targetRes.data.success)
194
+ setTargetRows(targetRes.data.data || []);
163
195
  }
164
- const pivotList = pivotRes.data;
165
- if (pivotList.success)
166
- setPivotRows(pivotList.data || []);
167
- const targetList = targetRes.data;
168
- if (targetList.success)
169
- setTargetRows(targetList.data || []);
170
196
  }
171
197
  catch (err) {
172
198
  console.error('DynamicRelation m2m fetch error', err);
@@ -174,16 +200,22 @@ function ManyToManyRelation({ kind, through, references, foreignKey, referencesK
174
200
  finally {
175
201
  setLoading(false);
176
202
  }
177
- }, [api, pivotPath, targetPath, foreignKey, parentId, references, targetMeta, cacheMetadata]);
178
- useEffect(() => { fetchAll(); }, [fetchAll]);
203
+ }, [api, pivotPath, foreignKey, parentId, references, targetMeta, cacheMetadata, useResolver, legacyTargetPath]);
204
+ useEffect(() => { fetchPivotAndMeta(); }, [fetchPivotAndMeta]);
179
205
  const options = useMemo(() => {
206
+ if (useResolver) {
207
+ return resolved.options.map((o) => ({
208
+ value: String(o.id),
209
+ label: o.label,
210
+ }));
211
+ }
180
212
  return targetRows
181
213
  .filter(r => r && r.id !== undefined && r.id !== null && r.id !== '')
182
214
  .map(r => ({
183
215
  value: String(r.id),
184
216
  label: pickOptionLabel(r, displayKey, targetMeta?.columns),
185
217
  }));
186
- }, [targetRows, displayKey, targetMeta]);
218
+ }, [useResolver, resolved.options, targetRows, displayKey, targetMeta]);
187
219
  const selectedIds = useMemo(() => extractSelectedTargetIds(pivotRows, refKey), [pivotRows, refKey]);
188
220
  const pivotIndex = useMemo(() => buildPivotRowIndex(pivotRows, refKey), [pivotRows, refKey]);
189
221
  const handleChange = useCallback(async (next) => {
@@ -212,7 +244,12 @@ function ManyToManyRelation({ kind, through, references, foreignKey, referencesK
212
244
  if (!res.data?.success)
213
245
  throw new Error('detach failed');
214
246
  }
215
- await fetchAll();
247
+ await fetchPivotAndMeta();
248
+ // Refresh resolver-driven options when active so newly attached
249
+ // targets reflect immediately. Refetching the pivot rows alone
250
+ // is enough when the resolver branch is off.
251
+ if (useResolver)
252
+ resolved.refetch();
216
253
  onChange?.();
217
254
  }
218
255
  catch (err) {
@@ -221,6 +258,6 @@ function ManyToManyRelation({ kind, through, references, foreignKey, referencesK
221
258
  finally {
222
259
  setSyncing(false);
223
260
  }
224
- }, [api, canCreate, canDelete, fetchAll, foreignKey, onChange, parentId, pivotIndex, pivotPath, refKey, selectedIds, syncing]);
225
- return (_jsxs("div", { className: className, "data-relation-kind": kind, "data-relation-through": through, "data-relation-references": references, children: [labels.title && (_jsx("div", { className: "pb-3", children: _jsx("h3", { className: "text-sm font-medium", children: labels.title }) })), loading ? (_jsx(Skeleton, { className: "h-10 w-full" })) : options.length === 0 ? (_jsx("div", { className: "text-center text-sm text-muted-foreground py-8 border rounded-md bg-muted/30", children: labels.emptyState })) : (_jsx(MultiSelect, { options: options, selected: selectedIds, onChange: handleChange, placeholder: labels.selectPlaceholder, searchPlaceholder: labels.selectSearchPlaceholder, emptyMessage: labels.selectEmpty }))] }));
261
+ }, [api, canCreate, canDelete, fetchPivotAndMeta, useResolver, resolved, foreignKey, onChange, parentId, pivotIndex, pivotPath, refKey, selectedIds, syncing]);
262
+ return (_jsxs("div", { className: className, "data-relation-kind": kind, "data-relation-through": through, "data-relation-references": references, children: [labels.title && (_jsx("div", { className: "pb-3", children: _jsx("h3", { className: "text-sm font-medium", children: labels.title }) })), (loading || (useResolver && resolved.loading)) ? (_jsx(Skeleton, { className: "h-10 w-full" })) : options.length === 0 ? (_jsx("div", { className: "text-center text-sm text-muted-foreground py-8 border rounded-md bg-muted/30", children: labels.emptyState })) : (_jsx(MultiSelect, { options: options, selected: selectedIds, onChange: handleChange, placeholder: labels.selectPlaceholder, searchPlaceholder: labels.selectSearchPlaceholder, emptyMessage: labels.selectEmpty }))] }));
226
263
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AA+B9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AASnF,UAAU,iBAAiB;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;CACxC;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,aAAoB,EACpB,aAAkB,EAClB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,GAC/C,EAAE,iBAAiB,2CA8rBnB"}
1
+ {"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AA+B9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAUnF,UAAU,iBAAiB;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;CACxC;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,aAAoB,EACpB,aAAkB,EAClB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,GAC/C,EAAE,iBAAiB,2CA+sBnB"}
@@ -27,6 +27,7 @@ import { useApi, useCurrentBranch } from './api-context';
27
27
  import { defaultGetDynamicColumns } from './dynamic-columns';
28
28
  import { OptionsContext } from './options-context';
29
29
  import { ActionModalDispatcher } from './action-modal-dispatcher';
30
+ import { getSearchableColumnKeys } from './column-visibility';
30
31
  import { DynamicRecordDialog } from './dialogs/dynamic-record';
31
32
  import { ExportDialog } from './dialogs/export';
32
33
  import { ImportDialog } from './dialogs/import';
@@ -253,14 +254,27 @@ export function DynamicTable({ model, endpoint, enableUrlSync = true, hiddenColu
253
254
  };
254
255
  initMetadataAndOptions();
255
256
  }, [model]); // eslint-disable-line react-hooks/exhaustive-deps
257
+ // Derived from `metadata.columns[].searchable`. `null` means the kernel
258
+ // didn't emit the flag for any column → preserve legacy "search every
259
+ // column" behaviour by not narrowing the request. An empty array means
260
+ // every column was explicitly opted out → skip sending `search` at all.
261
+ const searchableKeys = useMemo(() => (metadata ? getSearchableColumnKeys(metadata) : null), [metadata]);
256
262
  const buildFilterParams = useCallback(() => {
257
263
  const params = {};
258
264
  if (sorting.length > 0) {
259
265
  params.sortBy = sorting[0].id;
260
266
  params.order = sorting[0].desc ? 'desc' : 'asc';
261
267
  }
262
- if (globalFilter)
263
- params.search = globalFilter;
268
+ if (globalFilter) {
269
+ if (searchableKeys === null) {
270
+ params.search = globalFilter;
271
+ }
272
+ else if (searchableKeys.length > 0) {
273
+ params.search = globalFilter;
274
+ params.search_columns = searchableKeys.join(',');
275
+ }
276
+ // searchableKeys === [] → drop the search request entirely
277
+ }
264
278
  columnFilters.forEach((filter) => { params[`f_${filter.id}`] = filter.value; });
265
279
  if (defaultFilters)
266
280
  Object.entries(defaultFilters).forEach(([key, value]) => { params[`f_${key}`] = value; });
@@ -286,7 +300,7 @@ export function DynamicTable({ model, endpoint, enableUrlSync = true, hiddenColu
286
300
  params['f_created_at'] = `${startDate}_${endDate}`;
287
301
  }
288
302
  return params;
289
- }, [sorting, globalFilter, columnFilters, defaultFilters, dynamicFilters, dateRange]);
303
+ }, [sorting, globalFilter, columnFilters, defaultFilters, dynamicFilters, dateRange, searchableKeys]);
290
304
  const hasActiveFilters = useMemo(() => {
291
305
  if (globalFilter)
292
306
  return true;
package/dist/index.d.ts CHANGED
@@ -19,4 +19,8 @@ export { ImportDialog } from './dialogs/import';
19
19
  export { DynamicCRUDPage, type DynamicCRUDPageProps, type DynamicCRUDPageStrings, type DynamicCRUDPageClasses, } from './dynamic-crud-page';
20
20
  export { DynamicRelation, type DynamicRelationProps, type DynamicRelationStrings, type DynamicRelationKind, buildRelationFilterParams, buildCreatePayload, deriveRelationFormFields, relationRowKey, } from './dynamic-relation';
21
21
  export { registerModelExtension, getModelExtension, clearModelExtensions, type ModelExtension, type ModelExtensionProps, } from './model-extension-registry';
22
+ export { isColumnVisibleInTable, getSearchableColumnKeys, } from './column-visibility';
23
+ export { useOptionsResolver, projectOption, type ResolvedOption, type OptionsMeta, type UseOptionsResolverArgs, type UseOptionsResolverResult, } from './use-options-resolver';
24
+ export { setOrgConfigBridge, getOrgConfigBridge, resolveValidatorToken, type OrgConfigBridge, } from './use-org-config-bridge';
25
+ export { registerValidator } from './dynamic-form-schema';
22
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAA;AACvB,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,qBAAqB,EACrB,KAAK,gBAAgB,GACxB,MAAM,2BAA2B,CAAA;AAClC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,YAAY,EACR,kBAAkB,EAClB,YAAY,IAAI,yBAAyB,EACzC,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,KAAK,qBAAqB,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC9B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GAC3B,MAAM,4BAA4B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAA;AACvB,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,qBAAqB,EACrB,KAAK,gBAAgB,GACxB,MAAM,2BAA2B,CAAA;AAClC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,YAAY,EACR,kBAAkB,EAClB,YAAY,IAAI,yBAAyB,EACzC,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,KAAK,qBAAqB,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC9B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GAC3B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACH,sBAAsB,EACtB,uBAAuB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA"}
package/dist/index.js CHANGED
@@ -23,3 +23,7 @@ export { ImportDialog } from './dialogs/import';
23
23
  export { DynamicCRUDPage, } from './dynamic-crud-page';
24
24
  export { DynamicRelation, buildRelationFilterParams, buildCreatePayload, deriveRelationFormFields, relationRowKey, } from './dynamic-relation';
25
25
  export { registerModelExtension, getModelExtension, clearModelExtensions, } from './model-extension-registry';
26
+ export { isColumnVisibleInTable, getSearchableColumnKeys, } from './column-visibility';
27
+ export { useOptionsResolver, projectOption, } from './use-options-resolver';
28
+ export { setOrgConfigBridge, getOrgConfigBridge, resolveValidatorToken, } from './use-org-config-bridge';
29
+ export { registerValidator } from './dynamic-form-schema';
package/dist/types.d.ts CHANGED
@@ -26,6 +26,17 @@ export interface FilterDefinition {
26
26
  }[];
27
27
  searchEndpoint?: string;
28
28
  }
29
+ /**
30
+ * Where a column is rendered. Mirrors `manifest.ColumnDef.Visibility` in the
31
+ * kernel:
32
+ * - `''` / `'all'` — visible everywhere (default).
33
+ * - `'table'` — only the list/index page.
34
+ * - `'modal'` — only the create/edit modal.
35
+ * - `'list'` — only API list payloads (omitted from UI).
36
+ * Hosts may extend the union with their own scopes; the SDK only acts on the
37
+ * canonical values above.
38
+ */
39
+ export type ColumnVisibility = 'all' | 'table' | 'modal' | 'list' | (string & {});
29
40
  export interface ColumnDefinition {
30
41
  key: string;
31
42
  label: string;
@@ -33,6 +44,19 @@ export interface ColumnDefinition {
33
44
  sortable: boolean;
34
45
  filterable: boolean;
35
46
  hidden?: boolean;
47
+ /**
48
+ * Scopes where this column is rendered. When `'modal'` (or `'list'`) the
49
+ * column is hidden from the table even if `hidden` is unset. Empty/`'all'`/
50
+ * `'table'` keep the column visible. See `column-visibility.ts`.
51
+ */
52
+ visibility?: ColumnVisibility;
53
+ /**
54
+ * Opts the column into the model's full-text/contains search. Independent
55
+ * of `filterable` (which drives column-level filter chips). When at least
56
+ * one column declares `searchable`, the SDK narrows the global search to
57
+ * those columns; otherwise legacy "search every column" behaviour applies.
58
+ */
59
+ searchable?: boolean;
36
60
  styleConfig?: Record<string, any>;
37
61
  tooltip?: string;
38
62
  description?: string;
@@ -50,6 +74,20 @@ export interface ColumnDefinition {
50
74
  icon?: string;
51
75
  color?: string;
52
76
  }[];
77
+ /**
78
+ * FK target model. When the kernel auto-derives this from a
79
+ * belongs_to relation (or an author sets it explicitly), the SDK
80
+ * resolves the column's options against `/api/options/<ref>?field=id`
81
+ * via `useOptionsResolver`. Wins over `searchEndpoint` for select
82
+ * widgets — `searchEndpoint` stays as the legacy escape hatch.
83
+ */
84
+ ref?: string;
85
+ /**
86
+ * Server-side validation rules the SDK can also pre-flight in the
87
+ * form layer. `custom` may be a literal slug or a $org.<key>
88
+ * reference resolved through the OrgConfigProvider.
89
+ */
90
+ validation?: FieldValidation;
53
91
  }
54
92
  export interface ActionCondition {
55
93
  field: string;
@@ -77,6 +115,12 @@ export interface ActionFieldDef {
77
115
  searchEndpoint?: string;
78
116
  validation?: FieldValidation;
79
117
  widget?: FieldWidget | string;
118
+ /**
119
+ * FK target model — same semantics as ColumnDefinition.ref. When
120
+ * present, DynamicForm resolves the field's options through
121
+ * `useOptionsResolver` against `/api/options/<ref>?field=id`.
122
+ */
123
+ ref?: string;
80
124
  }
81
125
  export interface ActionDefinition {
82
126
  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,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;CACf;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;CACvB;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;CACvB"}