@asteby/metacore-runtime-react 13.8.5 → 13.10.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,71 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 13.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - da8139d: feat(dynamic-form,nav): FK→searchable picker, image thumbnails, media→upload, query-aware nav
8
+ - **resolveWidget**: a field that declares an FK target (`ref`, or the
9
+ snake_case `source`/`relation` the kernel may serve) now resolves to
10
+ `dynamic_select` BEFORE the type switch, so any declared relation renders a
11
+ searchable picker instead of a raw text input — regardless of the column's
12
+ SQL type. `image`/`media`/`file` types resolve to the `upload` widget.
13
+ - **DynamicSelectField**: renders the option's `image` as a small thumbnail in
14
+ the trigger (selected option) and in each dropdown row, with a neutral
15
+ placeholder fallback. Thumbnails only appear when the resolved options carry
16
+ images, so image-less relations keep their plain text list. Also tolerates
17
+ the `source`/`relation` ref aliases for option resolution and inline-create.
18
+ - **NavGroup.checkIsActive**: now query-aware. Order-status style items that
19
+ share a path but differ only by a query param (`?status=reception` vs
20
+ `?status=delivery`) light up one at a time instead of all together; an item
21
+ that declares query params must match the current href's query exactly
22
+ (after normalization, with transient `f_` filter params stripped), while
23
+ query-less links keep matching on path alone.
24
+
25
+ ### Patch Changes
26
+
27
+ - Updated dependencies [da8139d]
28
+ - @asteby/metacore-ui@2.1.2
29
+
30
+ ## 13.9.0
31
+
32
+ ### Minor Changes
33
+
34
+ - 27b37f3: feat(dynamic-columns): declarative pro cell renderers for dynamic tables
35
+
36
+ Adds a library of declarative cell renderers so columns are rendered
37
+ beautifully out of the box instead of raw text. Driven by `col.cellStyle`
38
+ (or `col.type`), resolved via the existing `renderAs = col.cellStyle ?? col.type`.
39
+ Config is read from `col.styleConfig`, tolerating both snake_case (kernel) and
40
+ camelCase (compiled models).
41
+
42
+ New cellStyles:
43
+ - `url` / `link` — clickable link with an `ExternalLink` icon. `styleConfig`:
44
+ `{ label_field?, url_field?, icon?, new_tab? }`. Shows `label_field` text or
45
+ the URL hostname; opens in a new tab for external URLs (or `new_tab`);
46
+ prefixes `https://` when the scheme is missing.
47
+ - `email` — `mailto:` link with a `Mail` icon.
48
+ - `currency` — `Intl.NumberFormat` currency formatting, right-aligned.
49
+ Currency from `styleConfig.currency` (default `USD`), decimals from
50
+ `styleConfig.decimals` (default 2). No hardcoded MXN.
51
+ - `number` — thousands-separated number, right-aligned.
52
+ - `percent` / `progress` — progress bar (shadcn `Progress`) + `NN%` label.
53
+ - `badge` (generic) — pills a plain value even without `options`/`searchEndpoint`.
54
+ - `status` — badge with semantic color by value (active/paid→green,
55
+ pending/draft→amber, cancelled/failed→red, else grey); explicit
56
+ `options` colors win.
57
+ - `tags` — array / comma-separated string → row of small badges.
58
+ - `color` — color swatch + hex code.
59
+ - `code` / `truncate-text` — monospaced, truncated (`styleConfig.max_length`)
60
+ with a hover copy button.
61
+ - `creator` / `user` — avatar + name + subtitle, generalising the existing
62
+ `avatar`/`search` renderer (name from `styleConfig.name_field`, photo from a
63
+ sibling `.avatar`/`.photo` or `base_path + value`, initials fallback).
64
+
65
+ Also improves the existing `boolean` cell (green `Check` / muted `Minus` icon)
66
+ without breaking the `avatar`/`search`, `date`, `phone`, `image`,
67
+ `media-gallery`, `badge+options` and `relation-badge-list` renderers.
68
+
3
69
  ## 13.8.5
4
70
 
5
71
  ### Patch Changes
@@ -1 +1 @@
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;AAOD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OAMlE,CAAA;AAmHD;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,OAAO,GAAE,qBAA0B,GACpC,iBAAiB,CAsXnB;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":"AA0CA,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;AAgGD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OAMlE,CAAA;AAuJD;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,OAAO,GAAE,qBAA0B,GACpC,iBAAiB,CAokBnB;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBACL,CAAA"}
@@ -1,8 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // Default `getDynamicColumns` factory used by hosts that don't need a custom
3
3
  // renderer. Supports every cell type produced by kernel/dynamic metadata:
4
- // badge (static + endpoint-loaded options), avatar, phone, date, boolean,
5
- // relation-badge-list, media-gallery, image, plus a generic text fallback.
4
+ // badge (static + endpoint-loaded options), avatar/search, creator/user,
5
+ // phone, date, boolean, relation-badge-list, media-gallery, image, plus the
6
+ // declarative pro renderers url/link, email, currency, number, percent/
7
+ // progress, status, tags, color, code/truncate-text, and a generic text
8
+ // fallback. The renderer resolves `cellStyle ?? type` for each column.
6
9
  //
7
10
  // The implementation was previously duplicated across multiple host apps
8
11
  // (~550 LOC each, drifting). It now lives here so a single fix propagates
@@ -16,11 +19,63 @@ import { MoreHorizontal } from 'lucide-react';
16
19
  import { Avatar, AvatarFallback, AvatarImage, Badge, Button, Checkbox, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@asteby/metacore-ui';
17
20
  import { DataTableColumnHeader, FilterableColumnHeader, } from '@asteby/metacore-ui/data-table';
18
21
  import { generateBadgeStyles, getInitials } from '@asteby/metacore-ui/lib';
22
+ import { Progress } from './dialogs/_primitives';
19
23
  import { OptionsContext } from './options-context';
20
24
  import { DynamicIcon } from './dynamic-icon';
21
25
  import { isColumnVisibleInTable } from './column-visibility';
22
26
  const defaultGetImageUrl = (path) => path;
23
27
  const getNestedValue = (obj, path) => path.split('.').reduce((acc, part) => acc && acc[part], obj);
28
+ /**
29
+ * Reads a styleConfig key tolerating both snake_case (emitted by the kernel)
30
+ * and camelCase (sometimes produced by compiled models). Returns the first
31
+ * defined match, e.g. `cfg('label_field', 'labelField')`.
32
+ */
33
+ const styleCfg = (col, ...keys) => {
34
+ const cfg = col.styleConfig;
35
+ if (!cfg)
36
+ return undefined;
37
+ for (const k of keys) {
38
+ if (cfg[k] !== undefined && cfg[k] !== null)
39
+ return cfg[k];
40
+ }
41
+ return undefined;
42
+ };
43
+ const EmptyCell = () => _jsx("span", { className: "text-muted-foreground", children: "-" });
44
+ /** Resolves the active org currency, defaulting to USD when no override. */
45
+ const resolveCurrency = (col) => styleCfg(col, 'currency') || 'USD';
46
+ const formatNumber = (value, opts, locale) => new Intl.NumberFormat(locale || undefined, opts).format(value);
47
+ /**
48
+ * Semantic status → badge color. Used by the `status` cell when no explicit
49
+ * `options` color is declared. Generic, value-driven mapping.
50
+ */
51
+ const statusColorFor = (value) => {
52
+ const v = value.toLowerCase();
53
+ if (['active', 'enabled', 'paid', 'completed', 'done', 'success', 'approved', 'open']
54
+ .includes(v))
55
+ return '#22c55e';
56
+ if (['pending', 'draft', 'processing', 'in_progress', 'review', 'waiting'].includes(v))
57
+ return '#eab308';
58
+ if (['inactive', 'disabled', 'cancelled', 'canceled', 'failed', 'rejected', 'error', 'closed']
59
+ .includes(v))
60
+ return '#ef4444';
61
+ return '#6b7280';
62
+ };
63
+ /** Copyable monospaced text cell (code/IDs/hashes). */
64
+ const CodeCell = ({ text, maxLength }) => {
65
+ const [copied, setCopied] = React.useState(false);
66
+ const display = maxLength && text.length > maxLength ? `${text.slice(0, maxLength)}…` : text;
67
+ const onCopy = () => {
68
+ try {
69
+ navigator.clipboard?.writeText(text);
70
+ setCopied(true);
71
+ setTimeout(() => setCopied(false), 1200);
72
+ }
73
+ catch {
74
+ /* clipboard unavailable */
75
+ }
76
+ };
77
+ return (_jsxs("div", { className: "group flex items-center gap-1.5", children: [_jsx("code", { className: "rounded bg-muted px-1.5 py-0.5 font-mono text-xs text-foreground/80", title: text, children: display }), _jsx("button", { type: "button", onClick: onCopy, className: "opacity-0 transition-opacity group-hover:opacity-100 text-muted-foreground hover:text-foreground", "aria-label": "Copiar", title: "Copiar", children: copied ? (_jsx(icons.Check, { className: "h-3.5 w-3.5 text-green-500" })) : (_jsx(icons.Copy, { className: "h-3.5 w-3.5" })) })] }));
78
+ };
24
79
  /**
25
80
  * State-machine gate for per-row actions.
26
81
  *
@@ -124,6 +179,13 @@ const BadgeWithEndpointOptions = ({ endpoint, value }) => {
124
179
  return _jsx(OptionBadge, { option: option, fallback: String(value) });
125
180
  return _jsx(Badge, { variant: "outline", children: String(value) });
126
181
  };
182
+ /**
183
+ * Generic avatar-style cell: round/rounded photo (or initials fallback) +
184
+ * primary name + optional subtitle. Backs the `avatar`/`search` columns as
185
+ * well as the `creator`/`user` cellStyles. Paths are parameterised so the same
186
+ * JSX serves every variant.
187
+ */
188
+ const AvatarCell = ({ name, desc, avatarSrc, getImageUrl }) => (_jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [_jsxs(Avatar, { className: "h-8 w-8 rounded-lg ring-1 ring-border/50", children: [_jsx(AvatarImage, { src: avatarSrc ? getImageUrl(avatarSrc) : '', alt: name, className: "object-cover" }), _jsx(AvatarFallback, { className: "text-[10px] font-bold bg-primary/5 text-primary rounded-lg", children: getInitials(name) })] }), _jsxs("div", { className: "flex flex-col min-w-0 overflow-hidden", children: [_jsx("span", { className: "font-medium text-sm truncate leading-none mb-0.5 text-foreground/90", children: name }), desc && (_jsx("span", { className: "text-[11px] text-muted-foreground truncate leading-none", children: desc }))] })] }));
127
189
  /**
128
190
  * Builds the canonical column factory used by `<DynamicTable>` when the host
129
191
  * does not supply its own. Pass `{ getImageUrl, apiBaseUrl }` to wire avatar
@@ -196,7 +258,26 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
196
258
  if (renderAs === 'relation-badge-list') {
197
259
  return renderRelationBadges(value, col);
198
260
  }
199
- switch (col.type) {
261
+ // Generic badge (no options/endpoint) — still pill it.
262
+ if (renderAs === 'badge') {
263
+ if (!value && value !== 0)
264
+ return _jsx(EmptyCell, {});
265
+ return _jsx(Badge, { variant: "outline", children: String(value) });
266
+ }
267
+ // Status — semantic color by value, options color wins.
268
+ if (renderAs === 'status') {
269
+ if (!value && value !== 0)
270
+ return _jsx(EmptyCell, {});
271
+ const sv = String(value);
272
+ const option = col.options?.find((o) => o.value === sv);
273
+ if (option)
274
+ return _jsx(OptionBadge, { option: option, fallback: sv });
275
+ const isDark = typeof document !== 'undefined' &&
276
+ document.documentElement.classList.contains('dark');
277
+ const styles = generateBadgeStyles(statusColorFor(sv), { isDark });
278
+ return (_jsx(Badge, { variant: "outline", className: "border-0 capitalize", style: styles, children: sv }));
279
+ }
280
+ switch (renderAs) {
200
281
  case 'date': {
201
282
  if (!value)
202
283
  return _jsx("span", { className: "text-muted-foreground", children: "-" });
@@ -212,36 +293,143 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
212
293
  }
213
294
  }
214
295
  case 'search':
215
- case 'avatar': {
216
- const namePath = col.tooltip || col.key;
296
+ case 'avatar':
297
+ case 'creator':
298
+ case 'user': {
299
+ // `creator`/`user` resolve the name from an explicit
300
+ // styleConfig.name_field first, then the legacy
301
+ // tooltip/displayField hints, then the column key.
302
+ const namePath = styleCfg(col, 'name_field', 'nameField') ||
303
+ col.tooltip ||
304
+ col.displayField ||
305
+ col.key;
217
306
  const name = getNestedValue(row.original, namePath) || 'N/A';
218
307
  const desc = getNestedValue(row.original, col.description || '');
308
+ const basePath = styleCfg(col, 'base_path', 'basePath') ?? col.basePath ?? '';
219
309
  let avatarSrc;
220
310
  if (col.key.includes('.')) {
311
+ // Look for a sibling `.avatar` or `.photo` field.
221
312
  const parentPath = col.key.split('.').slice(0, -1).join('.');
222
- const avatarPath = `${parentPath}.avatar`;
223
- const possibleAvatar = getNestedValue(row.original, avatarPath);
224
- if (possibleAvatar)
225
- avatarSrc = String(possibleAvatar);
226
- }
227
- else if (value &&
228
- (String(value).startsWith('http') || String(value).startsWith('https'))) {
229
- avatarSrc = String(value);
313
+ const sibling = getNestedValue(row.original, `${parentPath}.avatar`) ||
314
+ getNestedValue(row.original, `${parentPath}.photo`);
315
+ if (sibling)
316
+ avatarSrc = String(sibling);
230
317
  }
231
- else if (value) {
232
- avatarSrc = `${apiBaseUrl}${col.basePath || ''}${value}`;
318
+ if (!avatarSrc && value) {
319
+ if (String(value).startsWith('http')) {
320
+ avatarSrc = String(value);
321
+ }
322
+ else {
323
+ avatarSrc = `${apiBaseUrl}${basePath}${value}`;
324
+ }
233
325
  }
234
- return (_jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [_jsxs(Avatar, { className: "h-8 w-8 rounded-lg ring-1 ring-border/50", children: [_jsx(AvatarImage, { src: getImageUrl(avatarSrc || ''), alt: String(name), className: "object-cover" }), _jsx(AvatarFallback, { className: "text-[10px] font-bold bg-primary/5 text-primary rounded-lg", children: getInitials(String(name)) })] }), _jsxs("div", { className: "flex flex-col min-w-0 overflow-hidden", children: [_jsx("span", { className: "font-medium text-sm truncate leading-none mb-0.5 text-foreground/90", children: String(name) }), desc && (_jsx("span", { className: "text-[11px] text-muted-foreground truncate leading-none", children: String(desc) }))] })] }));
326
+ return (_jsx(AvatarCell, { name: String(name), desc: desc ? String(desc) : undefined, avatarSrc: avatarSrc, getImageUrl: getImageUrl }));
235
327
  }
236
328
  case 'relation-badge-list':
237
329
  return renderRelationBadges(value, col);
330
+ case 'url':
331
+ case 'link': {
332
+ const labelField = styleCfg(col, 'label_field', 'labelField');
333
+ const urlField = styleCfg(col, 'url_field', 'urlField');
334
+ const rawUrl = urlField
335
+ ? getNestedValue(row.original, urlField)
336
+ : value;
337
+ if (!rawUrl)
338
+ return _jsx(EmptyCell, {});
339
+ const urlStr = String(rawUrl);
340
+ const href = /^https?:\/\//i.test(urlStr) ? urlStr : `https://${urlStr}`;
341
+ let label;
342
+ if (labelField) {
343
+ label = String(getNestedValue(row.original, labelField) ?? href);
344
+ }
345
+ else {
346
+ try {
347
+ label = new URL(href).hostname;
348
+ }
349
+ catch {
350
+ label = urlStr;
351
+ }
352
+ }
353
+ const isExternal = !/^https?:\/\/(localhost|127\.)/i.test(href);
354
+ const newTab = styleCfg(col, 'new_tab', 'newTab') === true || isExternal;
355
+ const iconName = styleCfg(col, 'icon') || 'ExternalLink';
356
+ return (_jsxs("a", { href: href, ...(newTab
357
+ ? { target: '_blank', rel: 'noopener noreferrer' }
358
+ : {}), className: "inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline", onClick: (e) => e.stopPropagation(), children: [_jsx(DynamicIcon, { name: iconName, className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "truncate max-w-[260px]", children: label })] }));
359
+ }
360
+ case 'email': {
361
+ if (!value)
362
+ return _jsx(EmptyCell, {});
363
+ const email = String(value);
364
+ return (_jsxs("a", { href: `mailto:${email}`, className: "inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline", onClick: (e) => e.stopPropagation(), children: [_jsx(icons.Mail, { className: "h-3.5 w-3.5 shrink-0 opacity-70" }), _jsx("span", { className: "truncate max-w-[260px]", children: email })] }));
365
+ }
366
+ case 'currency': {
367
+ const num = typeof value === 'number' ? value : Number(value);
368
+ if (value === null || value === undefined || isNaN(num))
369
+ return (_jsx("div", { className: "text-right", children: _jsx(EmptyCell, {}) }));
370
+ const decimals = styleCfg(col, 'decimals') ?? 2;
371
+ return (_jsx("span", { className: "block text-right font-medium tabular-nums", children: formatNumber(num, {
372
+ style: 'currency',
373
+ currency: resolveCurrency(col),
374
+ minimumFractionDigits: decimals,
375
+ maximumFractionDigits: decimals,
376
+ }, currentLanguage) }));
377
+ }
378
+ case 'number': {
379
+ const num = typeof value === 'number' ? value : Number(value);
380
+ if (value === null || value === undefined || isNaN(num))
381
+ return (_jsx("div", { className: "text-right", children: _jsx(EmptyCell, {}) }));
382
+ const decimals = styleCfg(col, 'decimals');
383
+ return (_jsx("span", { className: "block text-right font-medium tabular-nums", children: formatNumber(num, decimals !== undefined
384
+ ? {
385
+ minimumFractionDigits: decimals,
386
+ maximumFractionDigits: decimals,
387
+ }
388
+ : {}, currentLanguage) }));
389
+ }
390
+ case 'percent':
391
+ case 'progress': {
392
+ const num = typeof value === 'number' ? value : Number(value);
393
+ if (value === null || value === undefined || isNaN(num))
394
+ return _jsx(EmptyCell, {});
395
+ const pct = Math.max(0, Math.min(100, num));
396
+ return (_jsxs("div", { className: "flex items-center gap-2 min-w-[120px]", children: [_jsx(Progress, { value: pct, className: "flex-1" }), _jsxs("span", { className: "text-xs font-medium tabular-nums text-muted-foreground w-9 text-right", children: [Math.round(pct), "%"] })] }));
397
+ }
398
+ case 'tags': {
399
+ const list = Array.isArray(value)
400
+ ? value.map(String)
401
+ : value
402
+ ? String(value)
403
+ .split(',')
404
+ .map((s) => s.trim())
405
+ .filter(Boolean)
406
+ : [];
407
+ if (list.length === 0)
408
+ return _jsx(EmptyCell, {});
409
+ return (_jsx("div", { className: "flex flex-wrap gap-1", children: list.map((tag, i) => (_jsx(Badge, { variant: "secondary", className: "px-1.5 py-0 text-[10px]", children: tag }, `${col.key}-${i}`))) }));
410
+ }
411
+ case 'color': {
412
+ if (!value)
413
+ return _jsx(EmptyCell, {});
414
+ const hex = String(value);
415
+ return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "h-4 w-4 rounded border border-border/60 shrink-0", style: { background: hex } }), _jsx("code", { className: "font-mono text-xs text-muted-foreground", children: hex })] }));
416
+ }
417
+ case 'code':
418
+ case 'truncate-text': {
419
+ if (value === null || value === undefined || value === '')
420
+ return _jsx(EmptyCell, {});
421
+ const maxLength = styleCfg(col, 'max_length', 'maxLength');
422
+ return _jsx(CodeCell, { text: String(value), maxLength: maxLength });
423
+ }
238
424
  case 'phone': {
239
425
  if (!value)
240
426
  return _jsx("span", { className: "text-muted-foreground", children: "-" });
241
427
  return _jsx("span", { className: "font-medium text-sm", children: String(value) });
242
428
  }
243
- case 'boolean':
244
- return value ? _jsx(Badge, { children: "S\u00ED" }) : _jsx(Badge, { variant: "secondary", children: "No" });
429
+ case 'boolean': {
430
+ const showText = styleCfg(col, 'show_text', 'showText') !== false;
431
+ return (_jsxs("span", { className: "inline-flex items-center gap-1.5", children: [value ? (_jsx(icons.Check, { className: "h-4 w-4 text-green-500" })) : (_jsx(icons.Minus, { className: "h-4 w-4 text-muted-foreground" })), showText && (_jsx("span", { className: "text-sm text-muted-foreground", children: value ? 'Sí' : 'No' }))] }));
432
+ }
245
433
  case 'media-gallery': {
246
434
  if (!value || (Array.isArray(value) && value.length === 0)) {
247
435
  return _jsx("span", { className: "text-muted-foreground", children: "-" });
@@ -54,6 +54,15 @@ export interface BalanceState {
54
54
  */
55
55
  export declare function evaluateBalance(field: ActionFieldDef, rows: any[] | undefined): BalanceState | undefined;
56
56
  export declare function resolveWidget(field: ActionFieldDef): string;
57
+ /**
58
+ * Resolves a field's FK target, tolerating the camelCase `ref` (authored SDK
59
+ * shape) and the snake_case `source` / `relation` aliases the kernel manifest
60
+ * may serve for a belongs_to column. Returns the trimmed model key, or
61
+ * `undefined` when the field declares no relation.
62
+ */
63
+ export declare function getFieldRef(field: ActionFieldDef): string | undefined;
64
+ /** True when a field declares an FK target the SDK can resolve options against. */
65
+ export declare function fieldHasRef(field: ActionFieldDef): boolean;
57
66
  /**
58
67
  * Normalizes an upload field's config, tolerating both the camelCase authored
59
68
  * SDK shape and the snake_case the kernel serves (`max_size`, `storage_path`).
@@ -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;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,CAgB3D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG;IACpD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB,CAaA"}
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,CA4B3D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAIrE;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG;IACpD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB,CAaA"}
@@ -190,6 +190,13 @@ function fieldToZod(field) {
190
190
  export function resolveWidget(field) {
191
191
  if (field.widget)
192
192
  return field.widget;
193
+ // S1: any field that declares an FK target (`ref`, or the snake_case
194
+ // `source`/`relation` the kernel may serve) renders as an async searchable
195
+ // single-select — NOT a raw text input. This wins over the `type` switch so
196
+ // a declared FK column is a picker regardless of its SQL column type
197
+ // (uuid/text/etc), matching the kernel's option-resolution semantics.
198
+ if (fieldHasRef(field))
199
+ return 'dynamic_select';
193
200
  switch (field.type) {
194
201
  case 'textarea': return 'textarea';
195
202
  case 'select': return 'select';
@@ -202,9 +209,31 @@ export function resolveWidget(field) {
202
209
  // File upload: POSTs to the host upload endpoint and stores the returned
203
210
  // file url/path as the field value. Rendered by `UploadField`.
204
211
  case 'upload': return 'upload';
212
+ // S2: media-bearing types resolve to the upload widget so an `image`
213
+ // (logo/photo) or generic `file`/`media` field gets a real file picker
214
+ // instead of a free-text input.
215
+ case 'image': return 'upload';
216
+ case 'media': return 'upload';
217
+ case 'file': return 'upload';
205
218
  default: return 'text';
206
219
  }
207
220
  }
221
+ /**
222
+ * Resolves a field's FK target, tolerating the camelCase `ref` (authored SDK
223
+ * shape) and the snake_case `source` / `relation` aliases the kernel manifest
224
+ * may serve for a belongs_to column. Returns the trimmed model key, or
225
+ * `undefined` when the field declares no relation.
226
+ */
227
+ export function getFieldRef(field) {
228
+ const ref = field.ref ?? field.source ?? field.relation;
229
+ if (typeof ref === 'string' && ref.trim() !== '')
230
+ return ref.trim();
231
+ return undefined;
232
+ }
233
+ /** True when a field declares an FK target the SDK can resolve options against. */
234
+ export function fieldHasRef(field) {
235
+ return getFieldRef(field) !== undefined;
236
+ }
208
237
  /**
209
238
  * Normalizes an upload field's config, tolerating both the camelCase authored
210
239
  * SDK shape and the snake_case the kernel serves (`max_size`, `storage_path`).
@@ -1 +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,2CAoJrF;AAED,eAAe,kBAAkB,CAAA"}
1
+ {"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAgD7C,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,2CA2KrF;AAED,eAAe,kBAAkB,CAAA"}
@@ -24,8 +24,28 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
24
24
  // case — start empty and never hit this.
25
25
  import { useEffect, useState } from 'react';
26
26
  import { Button, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Popover, PopoverContent, PopoverTrigger, } from '@asteby/metacore-ui/primitives';
27
- import { Check, ChevronsUpDown, Loader2, Plus } from 'lucide-react';
27
+ import { Check, ChevronsUpDown, ImageIcon, Loader2, Plus } from 'lucide-react';
28
28
  import { useOptionsResolver } from './use-options-resolver';
29
+ import { getFieldRef } from './dynamic-form-schema';
30
+ /**
31
+ * Small square thumbnail for an option's `image`. Falls back to a neutral
32
+ * placeholder icon when the option has no image so rows/triggers stay aligned.
33
+ * `size` is in pixels (kept small — 20–24px — so the picker reads as a list,
34
+ * not a gallery). Inline style for the box dimensions: arbitrary Tailwind
35
+ * classes from a federated addon don't always survive the host's class scan.
36
+ */
37
+ function OptionThumb({ image, size = 20 }) {
38
+ const box = { width: size, height: size };
39
+ if (!image) {
40
+ return (_jsx("span", { className: "text-muted-foreground bg-muted flex shrink-0 items-center justify-center rounded-sm", style: box, "aria-hidden": true, children: _jsx(ImageIcon, { className: "size-3 opacity-60" }) }));
41
+ }
42
+ return (_jsx("img", { src: image, alt: "", "aria-hidden": true, loading: "lazy", className: "shrink-0 rounded-sm object-cover", style: box,
43
+ // A broken image url shouldn't leave a torn-icon glyph; collapse to
44
+ // the neutral placeholder background instead.
45
+ onError: (e) => {
46
+ e.currentTarget.style.visibility = 'hidden';
47
+ } }));
48
+ }
29
49
  function useDebounced(value, ms) {
30
50
  const [debounced, setDebounced] = useState(value);
31
51
  useEffect(() => {
@@ -41,22 +61,33 @@ export function DynamicSelectField({ field, value, onChange }) {
41
61
  // Remember the label of the option the user actually picked so the trigger
42
62
  // shows a name (not a UUID) without a round-trip.
43
63
  const [picked, setPicked] = useState(null);
64
+ // Tolerate the snake_case `source`/`relation` aliases the kernel may serve
65
+ // for the FK target, not just camelCase `ref`.
66
+ const fieldRef = getFieldRef(field);
44
67
  const { options, loading } = useOptionsResolver({
45
68
  modelKey: '',
46
69
  fieldKey: 'id',
47
- ref: field.ref,
70
+ ref: fieldRef,
48
71
  // searchEndpoint only drives the URL when there's no ref — ref is the
49
72
  // canonical, kernel-derived path and wins.
50
- endpoint: field.ref ? undefined : field.searchEndpoint,
73
+ endpoint: fieldRef ? undefined : field.searchEndpoint,
51
74
  query: debounced,
52
75
  limit: 20,
53
76
  // Don't fetch until the popover opens (and keep fetching as the query
54
77
  // changes while open).
55
78
  enabled: open,
56
79
  });
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) : '');
80
+ // The currently-selected option, resolved either from what the user picked
81
+ // (cached in `picked`) or from the loaded page. Drives both the trigger
82
+ // label and its thumbnail.
83
+ const selectedOption = (picked && String(picked.id) === String(value) ? picked : null) ??
84
+ options.find((o) => String(o.id) === String(value)) ??
85
+ null;
86
+ const selectedLabel = selectedOption?.label ?? (value ? String(value) : '');
87
+ // Only switch the picker into "with thumbnails" mode when the data actually
88
+ // carries images — a relation whose options have no `image` keeps the plain
89
+ // text list it had before (no empty placeholder column).
90
+ const hasImages = !!selectedOption?.image || options.some((o) => !!o.image);
60
91
  const handlePick = (opt) => {
61
92
  setPicked(opt);
62
93
  onChange(String(opt.id));
@@ -69,11 +100,11 @@ export function DynamicSelectField({ field, value, onChange }) {
69
100
  // hands back the new record and we select it immediately. No host import →
70
101
  // no circular dependency; works for ANY dynamic_select with a `ref`.
71
102
  const openCreate = () => {
72
- if (!field.ref || typeof window === 'undefined')
103
+ if (!fieldRef || typeof window === 'undefined')
73
104
  return;
74
105
  window.dispatchEvent(new CustomEvent('metacore:create-record', {
75
106
  detail: {
76
- model: field.ref,
107
+ model: fieldRef,
77
108
  onCreated: (rec) => {
78
109
  if (rec && rec.id != null) {
79
110
  const id = String(rec.id);
@@ -88,12 +119,12 @@ export function DynamicSelectField({ field, value, onChange }) {
88
119
  // to the cell. Without min-w-0 the combobox+button row sizes to its content
89
120
  // (the long empty-state placeholder) and overflows the column, pushing the
90
121
  // "+" off-screen — it only "fit" once a short value was selected.
91
- return (_jsxs("div", { className: "flex w-full min-w-0 items-center gap-1.5", children: [_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: "min-w-0 flex-1 justify-between font-normal", "data-empty": !value, children: [_jsx("span", { className: 'min-w-0 flex-1 truncate text-left ' + (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",
122
+ return (_jsxs("div", { className: "flex w-full min-w-0 items-center gap-1.5", children: [_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: "min-w-0 flex-1 justify-between font-normal", "data-empty": !value, children: [_jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [hasImages && value ? (_jsx(OptionThumb, { image: selectedOption?.image, size: 20 })) : null, _jsx("span", { className: 'min-w-0 flex-1 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",
92
123
  // Match the trigger width without an arbitrary Tailwind class
93
124
  // (those don't always survive a consuming app's Tailwind scan).
94
125
  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) => {
95
126
  const isSel = String(opt.id) === String(value);
96
- 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)));
97
- }) }))] })] }) })] }), field.ref && (_jsx(Button, { type: "button", variant: "outline", size: "icon", className: "size-9 shrink-0", onClick: openCreate, title: `Crear ${field.label ?? field.ref}`, "aria-label": `Crear ${field.label ?? field.ref}`, children: _jsx(Plus, { className: "size-4" }) }))] }));
127
+ return (_jsxs(CommandItem, { value: String(opt.id), onSelect: () => handlePick(opt), children: [_jsx(Check, { className: 'mr-2 size-4 shrink-0 ' + (isSel ? 'opacity-100' : 'opacity-0') }), hasImages && (_jsx(OptionThumb, { image: opt.image, size: 24 })), _jsxs("div", { className: "ml-2 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)));
128
+ }) }))] })] }) })] }), fieldRef && (_jsx(Button, { type: "button", variant: "outline", size: "icon", className: "size-9 shrink-0", onClick: openCreate, title: `Crear ${field.label ?? fieldRef}`, "aria-label": `Crear ${field.label ?? fieldRef}`, children: _jsx(Plus, { className: "size-4" }) }))] }));
98
129
  }
99
130
  export default DynamicSelectField;
package/dist/types.d.ts CHANGED
@@ -75,7 +75,7 @@ export type ColumnVisibility = 'all' | 'table' | 'modal' | 'list' | (string & {}
75
75
  export interface ColumnDefinition {
76
76
  key: string;
77
77
  label: string;
78
- type: 'text' | 'number' | 'date' | 'select' | 'search' | 'relation-badge-list' | 'avatar' | 'boolean' | 'phone' | 'media-gallery' | 'image';
78
+ type: 'text' | 'number' | 'date' | 'select' | 'search' | 'relation-badge-list' | 'avatar' | 'boolean' | 'phone' | 'media-gallery' | 'image' | 'url' | 'link' | 'email' | 'currency' | 'percent' | 'progress' | 'badge' | 'status' | 'tags' | 'color' | 'code' | 'truncate-text' | 'creator' | 'user';
79
79
  sortable: boolean;
80
80
  filterable: boolean;
81
81
  hidden?: boolean;
@@ -156,6 +156,14 @@ export interface ActionFieldDef {
156
156
  * `useOptionsResolver` against `/api/options/<ref>?field=id`.
157
157
  */
158
158
  ref?: string;
159
+ /**
160
+ * snake_case aliases the kernel manifest may serve for a belongs_to FK
161
+ * target instead of `ref`. Treated as equivalent to `ref` by the SDK so a
162
+ * declared relation renders a searchable picker regardless of which key the
163
+ * backend emits.
164
+ */
165
+ source?: string;
166
+ relation?: string;
159
167
  /**
160
168
  * Columns of a repeatable line-items group. Mirrors the kernel v3
161
169
  * `ActionField.item_fields` (json `item_fields`). Present on a field
@@ -1 +1 @@
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;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,YAAY,EAAE,CAAA;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,IAAI,EAAE,aAAa,GAAG,cAAc,CAAA;IACpC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;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,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;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;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAA;CACxB;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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "13.8.5",
3
+ "version": "13.10.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,7 @@
34
34
  "date-fns": ">=3",
35
35
  "react-day-picker": ">=8",
36
36
  "@asteby/metacore-sdk": "^3.1.0",
37
- "@asteby/metacore-ui": "^2.1.1"
37
+ "@asteby/metacore-ui": "^2.1.2"
38
38
  },
39
39
  "peerDependenciesMeta": {
40
40
  "@tanstack/react-router": {
@@ -61,8 +61,8 @@
61
61
  "typescript": "^6.0.0",
62
62
  "vitest": "^4.0.0",
63
63
  "zustand": "^5.0.0",
64
- "@asteby/metacore-sdk": "3.1.0",
65
- "@asteby/metacore-ui": "2.1.1"
64
+ "@asteby/metacore-ui": "2.1.2",
65
+ "@asteby/metacore-sdk": "3.1.0"
66
66
  },
67
67
  "scripts": {
68
68
  "build": "tsc -p tsconfig.json",