Skip to content
This repository was archived by the owner on Oct 26, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .changeset/25762-duration-keys-carry-unit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
'@object-ui/types': minor
'@object-ui/components': minor
'@object-ui/plugin-chatbot': minor
'@object-ui/plugin-report': minor
---

Clause-②: yes
Metadata-protocol: added

Nine duration keys now carry their unit in their name (objectstack#25762). Each one said its unit only in its description, so `timeout: 300` read as either milliseconds or seconds. After objectui merges into objectstack, `@objectstack/spec`'s `check:duration-unit-keys` judges these schemas too, and the maintainer chose to rename the keys rather than exempt them. The renames follow objectstack's own (`…Ms` / `…Seconds`, the unit each description already stated). The value and its unit do not change, only the key name. This is breaking for a document that still writes an old name; it is marked `minor` under this repository's version policy.

| Node / schema | FROM | TO | Unit |
|---|---|---|---|
| `carousel` (`CarouselSchema`) | `autoPlay` | `autoPlayMs` | milliseconds |
| `chatbot`, `chatbot-enhanced`, `chatbot-floating` | `autoResponseDelay` | `autoResponseDelayMs` | milliseconds |
| `ActionSchema` | `timeout` | `timeoutMs` | milliseconds |
| `ActionSchema.retry` | `delay` | `delayMs` | milliseconds |
| `toast` (`ToastSchema`) | `duration` | `durationMs` | milliseconds |
| `tooltip` (`TooltipSchema`) | `delayDuration` | `delayDurationMs` | milliseconds |
| `hover-card` (`HoverCardSchema`) | `openDelay` | `openDelayMs` | milliseconds |
| `hover-card` (`HoverCardSchema`) | `closeDelay` | `closeDelayMs` | milliseconds |
| `report` (`ReportComponentSchema`) | `refreshInterval` | `refreshIntervalSeconds` | seconds |

What an author sees with an old name:

- **zod (`@object-ui/types/zod`).** The old key is still declared, as a tombstone, so it is refused at its own path with code `invalid_type`. The message names the new key: "`timeout` is now `timeoutMs` … the value (milliseconds) is unchanged." Without the tombstone, `.passthrough()` would keep the value and nothing would read it.
- **TypeScript.** The old member is `?: never` with `@deprecated`, so a typed literal that writes it fails to compile.
- **Renderers.** `toast`, `tooltip`, `hover-card`, the three chatbot registrations and `ReportViewer` read the new key. Their registration `inputs` and `defaultProps` use the new name too. The `useObjectChat` hook option `autoResponseDelay` is a programmatic API, not a schema key, and keeps its name.

objectui has no conversion registry: ADR-0087's D2 table lives in `@objectstack/spec`. The conversion is this table plus the refusal message. To migrate, rename each key as the table shows and keep the value.
4 changes: 2 additions & 2 deletions content/docs/api/schema-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ A powerful action definition supporting API calls, confirmations, dialogs, chain
"condition": "${data.items.length > 0}",
"retry": {
"maxAttempts": 3,
"delay": 1000
"delayMs": 1000
}
}
```
Expand All @@ -689,7 +689,7 @@ A powerful action definition supporting API calls, confirmations, dialogs, chain
| `successMessage` / `errorMessage` | `string` | Toast messages on success/failure. |
| `reload` | `boolean` | Reload data after action completes. |
| `redirect` | `string` | URL to navigate to after action. |
| `retry` | `object` | Retry config with `maxAttempts` and `delay`. |
| `retry` | `object` | Retry config with `maxAttempts` and `delayMs` (milliseconds; renamed from `delay`, objectstack#25762). |

**Related:** [DetailSchema](#detailschema), [ButtonSchema](#buttonschema)

Expand Down
4 changes: 2 additions & 2 deletions content/docs/components/feedback/toast.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The Toast component displays brief notifications to users that appear temporaril
## Basic Usage

A `toast` node renders its own trigger button. Clicking the button raises the toast the
node declares — the title, description, variant and duration are all read off the node
node declares — the title, description, variant and `durationMs` are all read off the node
itself, so the whole demo is one schema node with no handler to wire up.

<SchemaExample id="components-feedback-toast/basic-toast" />
Expand Down Expand Up @@ -38,7 +38,7 @@ interface ToastSchema {
variant?: 'default' | 'success' | 'warning' | 'error' | 'info';

// Timing
duration?: number; // Auto-dismiss time in ms
durationMs?: number; // Auto-dismiss time in ms
}
```

Expand Down
4 changes: 2 additions & 2 deletions content/docs/components/overlay/hover-card.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ interface HoverCardSchema {
content: SchemaNode | SchemaNode[]; // Card content
side?: 'top' | 'right' | 'bottom' | 'left';
align?: 'start' | 'center' | 'end';
openDelay?: number; // Delay before opening (ms)
closeDelay?: number; // Delay before closing (ms)
openDelayMs?: number; // Delay before opening (ms)
closeDelayMs?: number; // Delay before closing (ms)
className?: string;
}
```
2 changes: 1 addition & 1 deletion content/docs/components/overlay/tooltip.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface TooltipSchema {
children?: SchemaNode | SchemaNode[]; // Rich content — the fallback half
side?: 'top' | 'right' | 'bottom' | 'left';
align?: 'start' | 'center' | 'end';
delayDuration?: number; // Delay before showing (ms)
delayDurationMs?: number; // Delay before showing (ms)
}
```

Expand Down
12 changes: 6 additions & 6 deletions content/docs/core/enhanced-actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ const ajaxAction: ActionSchema = {
- `method` - HTTP method (GET, POST, PUT, DELETE, PATCH)
- `data` - Request body/payload
- `headers` - Custom HTTP headers
- `timeout` - Request timeout in milliseconds
- `retry` - Retry configuration
- `timeoutMs` - Request timeout in milliseconds (renamed from `timeout`)
- `retry` - Retry configuration (`maxAttempts`, `delayMs`)

### Confirm Actions

Expand Down Expand Up @@ -389,11 +389,11 @@ const retryAction: ActionSchema = {
api: '/api/submit',
method: 'POST',

timeout: 30000, // 30 seconds
timeoutMs: 30000, // 30 seconds

retry: {
maxAttempts: 3,
delay: 1000 // 1 second between retries
delayMs: 1000 // 1 second between retries
}
};
```
Expand Down Expand Up @@ -467,10 +467,10 @@ const complexAction: ActionSchema = {
},

// Retry
timeout: 60000,
timeoutMs: 60000,
retry: {
maxAttempts: 3,
delay: 2000
delayMs: 2000
},

// Post-action behavior
Expand Down
2 changes: 1 addition & 1 deletion content/docs/core/report-schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ const comprehensiveReport: ReportComponentSchema = {
showExportButtons: true,
showPrintButton: true,
showScheduleButton: true,
refreshInterval: 300 // Auto-refresh every 5 minutes
refreshIntervalSeconds: 300 // Auto-refresh every 5 minutes
};
```

Expand Down
8 changes: 4 additions & 4 deletions content/docs/plugins/plugin-chatbot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ const schema: ChatbotSchema = {
maxHeight?: string,
autoResponse?: boolean,
autoResponseText?: string,
autoResponseDelay?: number,
autoResponseDelayMs?: number,
onSend?: (content: string, messages: ObjectChatMessage[]) => void,
className?: string,
// AI / service-ai integration fields
Expand Down Expand Up @@ -179,7 +179,7 @@ to apply. They are documented in their own table after this one, under
| `maxHeight` | string | `'500px'` | **`chatbot` and `chatbot-enhanced` only** (declared on `ChatbotSchema` and `ChatbotEnhancedSchema`; `ChatbotFloatingSchema` does not declare it). Maximum height of the chat message container, as a CSS length. `chatbot-floating` does not read it: its panel is sized by `floatingConfig.panelHeight` (a **number** of pixels, default `520`), and the panel pins its inner chat to `maxHeight: '100%'` so it fills that panel - a `maxHeight` authored on a floating node would be overridden even if it were forwarded. Size a floating chatbot with `floatingConfig.panelHeight` instead |
| `autoResponse` | boolean | `false` | Enable auto-response (demo mode, ignored when `api` is set) |
| `autoResponseText` | string | - | Text for auto-response |
| `autoResponseDelay` | number | `1000` | Delay before auto-response (ms) |
| `autoResponseDelayMs` | number | `1000` | Delay before auto-response, in milliseconds (renamed from `autoResponseDelay`, which is now refused with a message naming this key) |
| `onSend` | function | - | Callback when message is sent |
| `className` | string | `''` | Additional Tailwind CSS classes |
| `api` | string | - | Backend SSE endpoint (e.g., `/api/v1/ai/chat`). Enables AI streaming mode |
Expand Down Expand Up @@ -329,7 +329,7 @@ const schema: ChatbotSchema = {
messages: [], // seed with your own ChatMessage values
autoResponse: true,
autoResponseText: 'Thanks!',
autoResponseDelay: 1000,
autoResponseDelayMs: 1000,
};
```

Expand Down Expand Up @@ -554,7 +554,7 @@ const salesBot: ChatbotSchema = {
userAvatarFallback: 'You',
autoResponse: true,
autoResponseText: 'Great choice! Let me show you some options...',
autoResponseDelay: 1200,
autoResponseDelayMs: 1200,
maxHeight: '500px',
className: 'border-2 border-primary rounded-xl'
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"variant": "success",
"title": "Saved Successfully",
"description": "Your changes have been saved.",
"duration": 3000
"durationMs": 3000
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
"showTimestamp": false,
"autoResponse": true,
"autoResponseText": "Thank you for your message! This is an automated response.",
"autoResponseDelay": 1000,
"autoResponseDelayMs": 1000,
"maxHeight": "400px"
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"assistantAvatarFallback": "SA",
"showTimestamp": true,
"autoResponse": true,
"autoResponseDelay": 1500,
"autoResponseDelayMs": 1500,
"autoResponseText": "Let me check that for you...",
"maxHeight": "500px"
}
6 changes: 3 additions & 3 deletions packages/components/src/renderers/feedback/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ComponentRegistry.register('toast',

toastFn(schema.title || 'Notification', {
description: schema.description,
duration: schema.duration,
duration: schema.durationMs,
});
};

Expand All @@ -42,7 +42,7 @@ ComponentRegistry.register('toast',
name: 'variant',
type: 'enum',
enum: ['default', 'success', 'warning', 'error', 'info'] },
{ name: 'duration', type: 'number' },
{ name: 'durationMs', type: 'number' },
{ name: 'buttonLabel', type: 'string' },
{
name: 'buttonVariant',
Expand All @@ -57,7 +57,7 @@ ComponentRegistry.register('toast',
title: 'Notification',
buttonLabel: 'Show Toast',
variant: 'default',
duration: 5000
durationMs: 5000
}
}
);
6 changes: 3 additions & 3 deletions packages/components/src/renderers/overlay/hover-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { renderChildren, renderTriggerSlot } from '../../lib/utils';

ComponentRegistry.register('hover-card',
({ schema, className, ...props }: { schema: HoverCardSchema; className?: string; [key: string]: any }) => (
<HoverCard openDelay={schema.openDelay} closeDelay={schema.closeDelay} {...props}>
<HoverCard openDelay={schema.openDelayMs} closeDelay={schema.closeDelayMs} {...props}>
{renderTriggerSlot(HoverCardTrigger, schema.trigger)}
<HoverCardContent align={schema.align} side={schema.side} className={className}>
{renderChildren(schema.content)}
Expand All @@ -28,8 +28,8 @@ ComponentRegistry.register('hover-card',
namespace: 'ui',
label: 'Hover Card',
inputs: [
{ name: 'openDelay', type: 'number' },
{ name: 'closeDelay', type: 'number' },
{ name: 'openDelayMs', type: 'number' },
{ name: 'closeDelayMs', type: 'number' },
{ name: 'side', type: 'enum', enum: ['top', 'right', 'bottom', 'left'] },
{ name: 'align', type: 'enum', enum: ['start', 'center', 'end'] },
{
Expand Down
6 changes: 3 additions & 3 deletions packages/components/src/renderers/overlay/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { renderChildren, renderTriggerSlot } from '../../lib/utils';

ComponentRegistry.register('tooltip',
({ schema, className, ...props }: { schema: TooltipSchema; className?: string; [key: string]: any }) => (
<TooltipProvider delayDuration={schema.delayDuration}>
<TooltipProvider delayDuration={schema.delayDurationMs}>
<Tooltip {...props}>
{renderTriggerSlot(TooltipTrigger, schema.trigger)}
<TooltipContent side={schema.side} align={schema.align} className={className}>
Expand All @@ -35,7 +35,7 @@ ComponentRegistry.register('tooltip',
namespace: 'ui',
label: 'Tooltip',
inputs: [
{ name: 'delayDuration', type: 'number' },
{ name: 'delayDurationMs', type: 'number' },
{ name: 'side', type: 'enum', enum: ['top', 'right', 'bottom', 'left'] },
{ name: 'align', type: 'enum', enum: ['start', 'center', 'end'] },
{
Expand All @@ -58,7 +58,7 @@ ComponentRegistry.register('tooltip',
defaultProps: {
trigger: [{ type: 'button', label: 'Hover me', variant: 'outline' }],
content: 'Tooltip content',
delayDuration: 700,
delayDurationMs: 700,
side: 'top'
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ describe('chatbot-floating: a sent message renders on the panel (fixed, objectui
messages: [{ id: 'seed', role: 'assistant', content: 'seed-message-marker' }],
autoResponse: true,
autoResponseText: 'auto-reply-marker',
autoResponseDelay: 0,
autoResponseDelayMs: 0,
});

// Before the fix: the raw `{...props}` spread, LAST, put the AUTHORED
Expand Down
20 changes: 10 additions & 10 deletions packages/plugin-chatbot/src/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { toRuntimeMessages } from './chatMessageAdapter';
*
* **Legacy Mode** (when `api` is not set):
* - Local auto-response for demo/playground use
* - Schema fields: autoResponse, autoResponseText, autoResponseDelay
* - Schema fields: autoResponse, autoResponseText, autoResponseDelayMs
*
* Both modes support the `onSend` callback:
* - Signature: `onSend(content: string, messages: ObjectChatMessage[]): void`
Expand Down Expand Up @@ -93,7 +93,7 @@ ComponentRegistry.register('chatbot',
showTimestamp: schema.showTimestamp,
autoResponse: schema.autoResponse,
autoResponseText: schema.autoResponseText,
autoResponseDelay: schema.autoResponseDelay,
autoResponseDelay: schema.autoResponseDelayMs,
onSend: schema.onSend,
});

Expand Down Expand Up @@ -214,7 +214,7 @@ ComponentRegistry.register('chatbot',
name: 'autoResponseText',
type: 'string' },
{
name: 'autoResponseDelay',
name: 'autoResponseDelayMs',
type: 'number' },
{
name: 'className',
Expand All @@ -236,7 +236,7 @@ ComponentRegistry.register('chatbot',
maxHeight: '500px',
autoResponse: true,
autoResponseText: 'Thank you for your message! This is an automated response.',
autoResponseDelay: 1000,
autoResponseDelayMs: 1000,
className: 'w-full max-w-2xl'
}
}
Expand Down Expand Up @@ -281,7 +281,7 @@ ComponentRegistry.register('chatbot-enhanced',
showTimestamp: schema.showTimestamp,
autoResponse: schema.autoResponse,
autoResponseText: schema.autoResponseText,
autoResponseDelay: schema.autoResponseDelay,
autoResponseDelay: schema.autoResponseDelayMs,
onSend: schema.onSend,
});

Expand Down Expand Up @@ -352,7 +352,7 @@ ComponentRegistry.register('chatbot-enhanced',
{ name: 'streamingEnabled', type: 'boolean' },
{ name: 'autoResponse', type: 'boolean' },
{ name: 'autoResponseText', type: 'string' },
{ name: 'autoResponseDelay', type: 'number' },
{ name: 'autoResponseDelayMs', type: 'number' },
{ name: 'className', type: 'string' }
],
defaultProps: {
Expand All @@ -373,7 +373,7 @@ ComponentRegistry.register('chatbot-enhanced',
maxHeight: '500px',
autoResponse: true,
autoResponseText: 'Thank you for your message! This is an automated response.',
autoResponseDelay: 1000,
autoResponseDelayMs: 1000,
className: 'w-full max-w-2xl'
}
}
Expand Down Expand Up @@ -418,7 +418,7 @@ ComponentRegistry.register('chatbot-floating',
showTimestamp: schema.showTimestamp,
autoResponse: schema.autoResponse,
autoResponseText: schema.autoResponseText,
autoResponseDelay: schema.autoResponseDelay,
autoResponseDelay: schema.autoResponseDelayMs,
onSend: schema.onSend,
});

Expand Down Expand Up @@ -504,7 +504,7 @@ ComponentRegistry.register('chatbot-floating',
{ name: 'streamingEnabled', type: 'boolean' },
{ name: 'autoResponse', type: 'boolean' },
{ name: 'autoResponseText', type: 'string' },
{ name: 'autoResponseDelay', type: 'number' },
{ name: 'autoResponseDelayMs', type: 'number' },
{ name: 'className', type: 'string' },
],
defaultProps: {
Expand All @@ -528,7 +528,7 @@ ComponentRegistry.register('chatbot-floating',
enableFileUpload: false,
autoResponse: true,
autoResponseText: 'Thank you for your message! This is an automated response.',
autoResponseDelay: 1000,
autoResponseDelayMs: 1000,
}
}
);
2 changes: 1 addition & 1 deletion packages/plugin-report/src/ReportViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export const ReportViewer: React.FC<ReportViewerProps> = ({ schema, onRefresh })
rule itself lives in the shared print sheet
(`@object-ui/app-shell/styles.css`, objectui#4462). */}
<div className="flex items-center gap-2" data-print-hide>
{report.refreshInterval && (
{report.refreshIntervalSeconds && (
<Button variant="outline" size="sm" onClick={handleRefresh}>
<RefreshCw className="h-4 w-4 mr-2" />
Refresh
Expand Down
Loading
Loading