@jini-ai/ui 0.5.4 → 0.5.5
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 +6 -0
- package/dist/features/admin-widgets/components/Select/Select.hooks.d.ts +21 -0
- package/dist/features/admin-widgets/components/Select/Select.hooks.js +24 -2
- package/dist/features/admin-widgets/components/Select/Select.js +4 -3
- package/dist/features/execution/react/hooks/useReasoningControl.d.ts +1 -1
- package/dist/features/execution/react/hooks/useReasoningControl.js +8 -3
- package/dist/features/execution/rules.d.ts +11 -0
- package/dist/features/execution/rules.js +24 -0
- package/dist/features/execution/types.d.ts +2 -0
- package/dist/features/interactive-ui/providers/native/data-table.manifest.d.ts +6 -6
- package/dist/features/interactive-ui/providers/shadcn/data-table.manifest.d.ts +6 -6
- package/dist/renderers/preview-modal-shell/react/components/icons.js +4 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @jini-ai/ui
|
|
2
2
|
|
|
3
|
+
## 0.5.5 — 2026-10-16
|
|
4
|
+
|
|
5
|
+
- `admin-widgets` Select paints group headings and per-option badges (dc770a41) and is pane-aware; image fields name the file (bc1dbf0d).
|
|
6
|
+
- The preview modal's default exit-fullscreen icon draws inward arrows (ef161bf1).
|
|
7
|
+
- `execution`: the Claude Code model picker lists each model once, by name (4b3b894b, 0ae46113).
|
|
8
|
+
|
|
3
9
|
## 0.5.4 — 2026-10-15
|
|
4
10
|
|
|
5
11
|
- `TabBar` re-scrolls the active tab into view once web fonts are ready (06931dfe): fonts that widen tabs after the first measurement no longer leave a deep-linked tab cut off at the strip edge.
|
|
@@ -2,7 +2,20 @@ export { focusableInDomOrder, resolveTabTarget } from '../../../../react/compone
|
|
|
2
2
|
export interface SelectOption {
|
|
3
3
|
value: string;
|
|
4
4
|
label: string;
|
|
5
|
+
/** Heading shown above the first option of each run with this value (e.g. "Pages", "Posts").
|
|
6
|
+
* Callers pass options already ordered by group; search narrows rows, headings follow. */
|
|
7
|
+
group?: string | undefined;
|
|
8
|
+
/** Short state shown as a muted pill after the label (e.g. "draft"); omit for the normal state. */
|
|
9
|
+
badge?: string | undefined;
|
|
10
|
+
/** Muted secondary text after the label, e.g. a slug telling two same-titled rows apart.
|
|
11
|
+
* Search matches it too. */
|
|
12
|
+
detail?: string | undefined;
|
|
5
13
|
}
|
|
14
|
+
/** The group heading to paint before `options[index]`, or null when it continues the previous run. */
|
|
15
|
+
export declare function groupHeadingAt({ options, index }: {
|
|
16
|
+
options: readonly SelectOption[];
|
|
17
|
+
index: number;
|
|
18
|
+
}): string | null;
|
|
6
19
|
export interface PanelPosition {
|
|
7
20
|
top?: number | undefined;
|
|
8
21
|
bottom?: number | undefined;
|
|
@@ -18,6 +31,14 @@ export interface PanelPosition {
|
|
|
18
31
|
export declare function computePosition({ trigger }: {
|
|
19
32
|
trigger: HTMLElement;
|
|
20
33
|
}): PanelPosition;
|
|
34
|
+
/** Top edge (viewport px, never negative) of the nearest scrollable PANE around the trigger, or 0.
|
|
35
|
+
* A pane is an `overflow-y: auto|scroll` ancestor at least half the viewport tall — whether or not
|
|
36
|
+
* it currently overflows (a short form still sits under the app bar), while a small scrolling
|
|
37
|
+
* wrapper such as a table or chip strip does not count and leaves placement as it was.
|
|
38
|
+
* @complexity O(depth) computed-style reads per measurement. */
|
|
39
|
+
export declare function scrollPaneTop({ trigger }: {
|
|
40
|
+
trigger: HTMLElement;
|
|
41
|
+
}, _optional?: Record<string, never>): number;
|
|
21
42
|
export declare function buildOptionId({ listboxId, index }: {
|
|
22
43
|
listboxId: string;
|
|
23
44
|
index: number;
|
|
@@ -13,6 +13,11 @@ const SEARCH_VISIBILITY_THRESHOLD = 8;
|
|
|
13
13
|
// 280px is only a placement heuristic; the panel actual maxHeight and scroll limit use
|
|
14
14
|
// the remaining viewport space so a low trigger does not open a mostly off-screen panel.
|
|
15
15
|
const ESTIMATED_PANEL_HEIGHT = 280;
|
|
16
|
+
/** The group heading to paint before `options[index]`, or null when it continues the previous run. */
|
|
17
|
+
export function groupHeadingAt({ options, index }) {
|
|
18
|
+
const group = options[index]?.group;
|
|
19
|
+
return group && group !== options[index - 1]?.group ? group : null;
|
|
20
|
+
}
|
|
16
21
|
/**
|
|
17
22
|
* Use fixed viewport-relative coordinates to escape scrolling/overflow-hidden ancestors
|
|
18
23
|
* without coupling to their layout. maxHeight uses actual remaining space, not the estimate,
|
|
@@ -23,13 +28,30 @@ export function computePosition({ trigger }) {
|
|
|
23
28
|
const gap = 4;
|
|
24
29
|
const viewportHeight = window.innerHeight;
|
|
25
30
|
const spaceBelow = viewportHeight - rect.bottom;
|
|
26
|
-
|
|
31
|
+
// Space above ends at the trigger's scrolling pane, not the viewport: an app bar above that pane
|
|
32
|
+
// is not room for the panel (owner, 2026-10-15: on a short phone the list flipped up and covered
|
|
33
|
+
// the top bar). With nothing scrolling but the page this is 0 and placement is unchanged.
|
|
34
|
+
const spaceAbove = rect.top - scrollPaneTop({ trigger });
|
|
27
35
|
const openUpward = spaceBelow < ESTIMATED_PANEL_HEIGHT && spaceAbove > spaceBelow;
|
|
28
36
|
if (openUpward) {
|
|
29
37
|
return { bottom: viewportHeight - rect.top + gap, left: rect.left, width: rect.width, maxHeight: Math.max(120, spaceAbove - gap * 2) };
|
|
30
38
|
}
|
|
31
39
|
return { top: rect.bottom + gap, left: rect.left, width: rect.width, maxHeight: Math.max(120, spaceBelow - gap * 2) };
|
|
32
40
|
}
|
|
41
|
+
/** Top edge (viewport px, never negative) of the nearest scrollable PANE around the trigger, or 0.
|
|
42
|
+
* A pane is an `overflow-y: auto|scroll` ancestor at least half the viewport tall — whether or not
|
|
43
|
+
* it currently overflows (a short form still sits under the app bar), while a small scrolling
|
|
44
|
+
* wrapper such as a table or chip strip does not count and leaves placement as it was.
|
|
45
|
+
* @complexity O(depth) computed-style reads per measurement. */
|
|
46
|
+
export function scrollPaneTop({ trigger }, _optional = {}) {
|
|
47
|
+
for (let el = trigger.parentElement; el && el !== document.body && el !== document.documentElement; el = el.parentElement) {
|
|
48
|
+
const overflowY = getComputedStyle(el).overflowY;
|
|
49
|
+
if ((overflowY === "auto" || overflowY === "scroll") && el.clientHeight * 2 >= window.innerHeight) {
|
|
50
|
+
return Math.max(0, el.getBoundingClientRect().top);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
33
55
|
export function buildOptionId({ listboxId, index }) {
|
|
34
56
|
return `${listboxId}-option-${index}`;
|
|
35
57
|
}
|
|
@@ -118,7 +140,7 @@ export function useSelectDropdown({ value, onChange, options, }, { disabled } =
|
|
|
118
140
|
if (!showSearch || !query.trim())
|
|
119
141
|
return options;
|
|
120
142
|
const q = query.trim().toLowerCase();
|
|
121
|
-
return options.filter((o) => o.label.toLowerCase().includes(q));
|
|
143
|
+
return options.filter((o) => o.label.toLowerCase().includes(q) || Boolean(o.detail?.toLowerCase().includes(q)));
|
|
122
144
|
}, [options, query, showSearch]);
|
|
123
145
|
const selectedOption = options.find((o) => o.value === value) ?? null;
|
|
124
146
|
function openPanel() {
|
|
@@ -3,12 +3,13 @@ import { resolveSelectPortalContainer } from '../../../../react/components/selec
|
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
4
|
import { agentHandle } from "@jini-ai/agentic";
|
|
5
5
|
import { buildAgentListHandles } from "@jini-ai/agentic";
|
|
6
|
-
import {
|
|
6
|
+
import { Fragment } from "react";
|
|
7
|
+
import { useSelectDropdown, groupHeadingAt } from "./Select.hooks.js";
|
|
7
8
|
function SelectOptionRow({ option, index, isSelected, isHighlighted, optionId, setOptionRef, onHighlight, onSelect, agentHandle: optionHandle, }) {
|
|
8
|
-
return (_jsxs("li", { ref: (el) => setOptionRef(index, el), id: optionId, role: "option", "aria-selected": isSelected, className: `select-option${isSelected ? " is-selected" : ""}${isHighlighted ? " is-highlighted" : ""}`, onMouseEnter: () => onHighlight(index), onClick: () => onSelect(option), ...(optionHandle ? agentHandle({ handle: optionHandle }, { role: "button", label: option.label }) : {}), children: [_jsx("span", { className: "select-option-label", children: option.label }), isSelected ? (_jsx("svg", { className: "select-option-check", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M3.5 8.5 6.5 11.5 12.5 4.5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) })) : null] }));
|
|
9
|
+
return (_jsxs("li", { ref: (el) => setOptionRef(index, el), id: optionId, role: "option", "aria-selected": isSelected, className: `select-option${isSelected ? " is-selected" : ""}${isHighlighted ? " is-highlighted" : ""}`, onMouseEnter: () => onHighlight(index), onClick: () => onSelect(option), ...(optionHandle ? agentHandle({ handle: optionHandle }, { role: "button", label: option.label }) : {}), children: [_jsx("span", { className: "select-option-label", children: option.label }), option.detail ? _jsx("span", { className: "select-option-detail", children: option.detail }) : null, option.badge ? _jsx("span", { className: "select-option-badge", children: option.badge }) : null, isSelected ? (_jsx("svg", { className: "select-option-check", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M3.5 8.5 6.5 11.5 12.5 4.5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) })) : null] }));
|
|
9
10
|
}
|
|
10
11
|
function SelectPanel({ panelRef, position, showSearch, searchInputRef, query, setQuery, filtered, value, highlightedIndex, listboxId, optionId, setOptionRef, onHighlight, onSelect, onKeyDown, searchHandle, optionHandles, t, }) {
|
|
11
|
-
return (_jsxs("div", { ref: panelRef, className: "select-panel", style: { left: position.left, width: position.width, top: position.top, bottom: position.bottom, maxHeight: position.maxHeight }, tabIndex: -1, onKeyDown: onKeyDown, children: [showSearch ? (_jsx("input", { ref: searchInputRef, type: "text", className: "select-search", "aria-label": t("Search options"), placeholder: t("Search…"), value: query, onChange: (e) => setQuery(e.target.value), ...(searchHandle ? agentHandle({ handle: searchHandle }, { role: "field", label: "Search the option list" }) : {}) })) : null, _jsx("ul", { className: "select-list", role: "listbox", id: listboxId, children: filtered.length === 0 ? (_jsx("li", { className: "select-empty", role: "presentation", children: t("No matches") })) : (filtered.map((option, index) => (_jsx(SelectOptionRow, { option: option, index: index, isSelected: option.value === value, isHighlighted: index === highlightedIndex, optionId: optionId(index), setOptionRef: setOptionRef, onHighlight: onHighlight, onSelect: onSelect, agentHandle: optionHandles?.[index] }, option.value)))) })] }));
|
|
12
|
+
return (_jsxs("div", { ref: panelRef, className: "select-panel", style: { left: position.left, width: position.width, top: position.top, bottom: position.bottom, maxHeight: position.maxHeight }, tabIndex: -1, onKeyDown: onKeyDown, children: [showSearch ? (_jsx("input", { ref: searchInputRef, type: "text", className: "select-search", "aria-label": t("Search options"), placeholder: t("Search…"), value: query, onChange: (e) => setQuery(e.target.value), ...(searchHandle ? agentHandle({ handle: searchHandle }, { role: "field", label: "Search the option list" }) : {}) })) : null, _jsx("ul", { className: "select-list", role: "listbox", id: listboxId, children: filtered.length === 0 ? (_jsx("li", { className: "select-empty", role: "presentation", children: t("No matches") })) : (filtered.map((option, index) => (_jsxs(Fragment, { children: [groupHeadingAt({ options: filtered, index }) ? (_jsx("li", { className: "select-group-label", role: "presentation", children: option.group })) : null, _jsx(SelectOptionRow, { option: option, index: index, isSelected: option.value === value, isHighlighted: index === highlightedIndex, optionId: optionId(index), setOptionRef: setOptionRef, onHighlight: onHighlight, onSelect: onSelect, agentHandle: optionHandles?.[index] })] }, option.value)))) })] }));
|
|
12
13
|
}
|
|
13
14
|
export function resolveSelectTriggerLabel({ selectedOption, placeholder }, { t = (key) => key } = {}) {
|
|
14
15
|
if (selectedOption)
|
|
@@ -54,7 +54,7 @@ export interface UseReasoningControlResult {
|
|
|
54
54
|
knownModelIds: readonly string[];
|
|
55
55
|
/** Whether the custom model input is currently active. */
|
|
56
56
|
customActive: boolean;
|
|
57
|
-
/** Options for the model select: base models for suffix agents, or
|
|
57
|
+
/** Options for the model select: base models for suffix agents, or deduped catalog rows. */
|
|
58
58
|
modelChoices: readonly AgentModelOption[];
|
|
59
59
|
/** Selected value for the model select element. */
|
|
60
60
|
selectValue: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect } from 'react';
|
|
2
2
|
import { CUSTOM_MODEL_SENTINEL } from '../../constants.js';
|
|
3
|
-
import { modelIdForReasoningLevel, reasoningModelGroupFor, reasoningModelGroups, selectedAgentModel, selectedAgentReasoning, shouldShowCustomModelInput, splitReasoningModelId, } from '../../rules.js';
|
|
3
|
+
import { modelIdForReasoningLevel, pickerModelOptions, reasoningModelGroupFor, reasoningModelGroups, selectedAgentModel, selectedAgentReasoning, shouldShowCustomModelInput, splitReasoningModelId, } from '../../rules.js';
|
|
4
4
|
export function useReasoningControl(optionsOrAgent, maybeConfig, maybeExplicitCustomMode) {
|
|
5
5
|
const { agent, config, explicitCustomMode = false, onReasoningChange } = 'agent' in optionsOrAgent && 'config' in optionsOrAgent
|
|
6
6
|
? optionsOrAgent
|
|
@@ -91,12 +91,17 @@ export function useReasoningControl(optionsOrAgent, maybeConfig, maybeExplicitCu
|
|
|
91
91
|
// id. Everything else about the field — search, labels, provenance badge — is unchanged.
|
|
92
92
|
const modelChoices = modelGroups
|
|
93
93
|
? modelGroups.map((group) => ({ id: group.baseId, label: group.label }))
|
|
94
|
-
: models;
|
|
94
|
+
: pickerModelOptions({ models });
|
|
95
|
+
// Persisted aliases stay known in the full catalog above, but the picker selects their concrete
|
|
96
|
+
// row. This is display-only: the saved model and dispatch resolution keep the operator's pick.
|
|
97
|
+
const selectedModel = models.find((model) => model.id === resolvedModel);
|
|
95
98
|
const selectValue = customActive
|
|
96
99
|
? CUSTOM_MODEL_SENTINEL
|
|
97
100
|
: modelGroups
|
|
98
101
|
? (activeGroup?.baseId ?? '')
|
|
99
|
-
:
|
|
102
|
+
: selectedModel?.identityKind === 'alias'
|
|
103
|
+
? (selectedModel.resolvedId || resolvedModel)
|
|
104
|
+
: resolvedModel;
|
|
100
105
|
// While the custom box is open, the text field must show the operator's raw
|
|
101
106
|
// typed text (which may not resolve to anything yet) rather than the
|
|
102
107
|
// resolved-with-fallback value — otherwise every keystroke would show a
|
|
@@ -243,6 +243,17 @@ export declare function agentExecutableRepairState(result: {
|
|
|
243
243
|
usedExecutableSource?: AgentExecutableSource | undefined;
|
|
244
244
|
detectedExecutablePath?: string | undefined;
|
|
245
245
|
}): AgentExecutableRepair | null;
|
|
246
|
+
/**
|
|
247
|
+
* Builds picker rows from catalog evidence without changing the source catalog. Resolved aliases
|
|
248
|
+
* share a concrete row; unresolved aliases and routing modes remain selectable as reported.
|
|
249
|
+
* Keeps the first position and prefers a human label over a raw ID, including the CLI default's
|
|
250
|
+
* raw-label row. No names or context variants are inferred from model IDs.
|
|
251
|
+
* @returns Distinct picker rows in catalog order. No side effects or errors.
|
|
252
|
+
* @complexity O(n) time and space in catalog rows, using insertion-ordered Map keys.
|
|
253
|
+
*/
|
|
254
|
+
export declare function pickerModelOptions({ models }: {
|
|
255
|
+
models: readonly AgentModelOption[];
|
|
256
|
+
}, _optional?: Record<string, never>): AgentModelOption[];
|
|
246
257
|
/**
|
|
247
258
|
* Filters a searchable model list down to what matches the operator's typed
|
|
248
259
|
* query. The currently-selected value's own option is always kept even when
|
|
@@ -476,6 +476,30 @@ export function agentExecutableRepairState(result) {
|
|
|
476
476
|
return null;
|
|
477
477
|
return { detectedPath, canUseDetected: true };
|
|
478
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* Builds picker rows from catalog evidence without changing the source catalog. Resolved aliases
|
|
481
|
+
* share a concrete row; unresolved aliases and routing modes remain selectable as reported.
|
|
482
|
+
* Keeps the first position and prefers a human label over a raw ID, including the CLI default's
|
|
483
|
+
* raw-label row. No names or context variants are inferred from model IDs.
|
|
484
|
+
* @returns Distinct picker rows in catalog order. No side effects or errors.
|
|
485
|
+
* @complexity O(n) time and space in catalog rows, using insertion-ordered Map keys.
|
|
486
|
+
*/
|
|
487
|
+
export function pickerModelOptions({ models }, _optional = {}) {
|
|
488
|
+
const choices = new Map();
|
|
489
|
+
for (const model of models) {
|
|
490
|
+
const resolvedId = model.identityKind === 'alias' ? model.resolvedId : undefined;
|
|
491
|
+
const id = resolvedId || model.id;
|
|
492
|
+
const label = model.label === model.id ? id : model.label;
|
|
493
|
+
const existing = choices.get(id);
|
|
494
|
+
if (!existing) {
|
|
495
|
+
choices.set(id, resolvedId ? { ...model, id, label, identityKind: 'concrete' } : model);
|
|
496
|
+
}
|
|
497
|
+
else if (existing.label === id && label !== id) {
|
|
498
|
+
choices.set(id, { ...existing, label });
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return [...choices.values()];
|
|
502
|
+
}
|
|
479
503
|
/** Case-insensitive substring match against a model's id or label, mirroring
|
|
480
504
|
* the origin's search box. Matches on both fields (not just the visible
|
|
481
505
|
* label) so an operator can search by the raw model id too. */
|
|
@@ -138,6 +138,8 @@ export interface ExecutionConfig {
|
|
|
138
138
|
export interface AgentModelOption {
|
|
139
139
|
id: string;
|
|
140
140
|
label: string;
|
|
141
|
+
identityKind?: 'concrete' | 'alias' | 'routing-mode';
|
|
142
|
+
resolvedId?: string;
|
|
141
143
|
/**
|
|
142
144
|
* The reasoning-effort levels THIS model supports, when the runtime's own catalog reports them
|
|
143
145
|
* per model rather than uniformly across the agent. Mirrors `@jini-ai/agent-runtime`'s
|
|
@@ -19,11 +19,11 @@ export declare const nativeDataTablePropsSchema: z.ZodObject<{
|
|
|
19
19
|
key: z.ZodString;
|
|
20
20
|
label: z.ZodString;
|
|
21
21
|
}, "strict", z.ZodTypeAny, {
|
|
22
|
-
key: string;
|
|
23
22
|
label: string;
|
|
24
|
-
}, {
|
|
25
23
|
key: string;
|
|
24
|
+
}, {
|
|
26
25
|
label: string;
|
|
26
|
+
key: string;
|
|
27
27
|
}>, "many">;
|
|
28
28
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
29
29
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
@@ -31,11 +31,11 @@ export declare const nativeDataTablePropsSchema: z.ZodObject<{
|
|
|
31
31
|
key: z.ZodString;
|
|
32
32
|
label: z.ZodString;
|
|
33
33
|
}, "strict", z.ZodTypeAny, {
|
|
34
|
-
key: string;
|
|
35
34
|
label: string;
|
|
36
|
-
}, {
|
|
37
35
|
key: string;
|
|
36
|
+
}, {
|
|
38
37
|
label: string;
|
|
38
|
+
key: string;
|
|
39
39
|
}>, "many">;
|
|
40
40
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
41
41
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
@@ -43,11 +43,11 @@ export declare const nativeDataTablePropsSchema: z.ZodObject<{
|
|
|
43
43
|
key: z.ZodString;
|
|
44
44
|
label: z.ZodString;
|
|
45
45
|
}, "strict", z.ZodTypeAny, {
|
|
46
|
-
key: string;
|
|
47
46
|
label: string;
|
|
48
|
-
}, {
|
|
49
47
|
key: string;
|
|
48
|
+
}, {
|
|
50
49
|
label: string;
|
|
50
|
+
key: string;
|
|
51
51
|
}>, "many">;
|
|
52
52
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
53
53
|
}, z.ZodTypeAny, "passthrough">>;
|
|
@@ -12,11 +12,11 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
|
|
|
12
12
|
key: z.ZodString;
|
|
13
13
|
label: z.ZodString;
|
|
14
14
|
}, "strict", z.ZodTypeAny, {
|
|
15
|
-
key: string;
|
|
16
15
|
label: string;
|
|
17
|
-
}, {
|
|
18
16
|
key: string;
|
|
17
|
+
}, {
|
|
19
18
|
label: string;
|
|
19
|
+
key: string;
|
|
20
20
|
}>, "many">;
|
|
21
21
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
22
22
|
sortable: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -26,11 +26,11 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
|
|
|
26
26
|
key: z.ZodString;
|
|
27
27
|
label: z.ZodString;
|
|
28
28
|
}, "strict", z.ZodTypeAny, {
|
|
29
|
-
key: string;
|
|
30
29
|
label: string;
|
|
31
|
-
}, {
|
|
32
30
|
key: string;
|
|
31
|
+
}, {
|
|
33
32
|
label: string;
|
|
33
|
+
key: string;
|
|
34
34
|
}>, "many">;
|
|
35
35
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
36
36
|
sortable: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -40,11 +40,11 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
|
|
|
40
40
|
key: z.ZodString;
|
|
41
41
|
label: z.ZodString;
|
|
42
42
|
}, "strict", z.ZodTypeAny, {
|
|
43
|
-
key: string;
|
|
44
43
|
label: string;
|
|
45
|
-
}, {
|
|
46
44
|
key: string;
|
|
45
|
+
}, {
|
|
47
46
|
label: string;
|
|
47
|
+
key: string;
|
|
48
48
|
}>, "many">;
|
|
49
49
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
50
50
|
sortable: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -6,6 +6,9 @@ export const DEFAULT_PREVIEW_MODAL_ICONS = {
|
|
|
6
6
|
close: () => (_jsxs(Svg, { children: [_jsx("path", { d: "M18 6 6 18" }), _jsx("path", { d: "M6 6l12 12" })] })),
|
|
7
7
|
'chevron-down': () => (_jsx(Svg, { children: _jsx("path", { d: "m6 9 6 6 6-6" }) })),
|
|
8
8
|
fullscreen: () => (_jsx(Svg, { width: 15, height: 15, children: _jsx("path", { d: "M3 9V3h6M3 3l6 6M21 15v6h-6M21 21l-6-6" }) })),
|
|
9
|
-
|
|
9
|
+
// The same two diagonals as `fullscreen`, arrowheads moved to the inner ends so they point in.
|
|
10
|
+
// The old path joined each corner's two ends ("M3 9l6-6"), drawing a tiny closed triangle that
|
|
11
|
+
// read as a speck once expanded (a host's screenshot, 2026-10-15).
|
|
12
|
+
'fullscreen-exit': () => (_jsx(Svg, { width: 15, height: 15, children: _jsx("path", { d: "M9 3v6H3M3 3l6 6M15 21v-6h6M21 21l-6-6" }) })),
|
|
10
13
|
};
|
|
11
14
|
//# sourceMappingURL=icons.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/ui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Generic, product-neutral React UI primitives and feature domains. Framework-free types, decision rules, catalogs, and host port contracts live behind ./core (no React, no DOM). The Excalidraw and Lexical editors live behind ./sketch-editor and ./lexical-rich-text-editor; the GrapesJS-backed inline HTML editor lives behind ./html-editor.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -244,12 +244,12 @@
|
|
|
244
244
|
"tailwind-merge": "^2.6.0",
|
|
245
245
|
"zod": "^3.25.76",
|
|
246
246
|
"@jini-ai/integrations": "^0.4.2",
|
|
247
|
-
"@jini-ai/
|
|
248
|
-
"@jini-ai/
|
|
249
|
-
"@jini-ai/
|
|
247
|
+
"@jini-ai/core": "^0.4.7",
|
|
248
|
+
"@jini-ai/agentic": "^0.4.4",
|
|
249
|
+
"@jini-ai/platform": "^0.5.9"
|
|
250
250
|
},
|
|
251
251
|
"dependencies": {
|
|
252
|
-
"@jini-ai/core": "^0.4.
|
|
252
|
+
"@jini-ai/core": "^0.4.7"
|
|
253
253
|
},
|
|
254
254
|
"peerDependencies": {
|
|
255
255
|
"@jini-ai/integrations": "^0.4.2",
|