@colineapp/ui 0.3.1 → 0.4.1

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/AGENTS.md CHANGED
@@ -58,10 +58,9 @@ as `Button`, `Card`, `Input`, `Textarea`, `Badge`, `Dialog`, `Select`,
58
58
  `Checkbox`, `Switch`, `Tabs`, `Table`, `Skeleton`, and `Tooltip`. Check the
59
59
  component source and declaration output before documenting a new prop.
60
60
 
61
- The client bundle is built by Coline. The app submits `main.tsx` and its
62
- source files; it does not submit `node_modules` or install packages in the
63
- sandbox. Keep client imports limited to the scaffold dependencies and app
64
- source.
61
+ The CLI bundles `main.tsx`, installed client dependencies, and imported CSS.
62
+ Coline rebuilds the uploaded artifact; the sandbox does not install packages.
63
+ Browser-compatible npm dependencies can be added to the app package.
65
64
 
66
65
  ## Verification and release
67
66
 
@@ -71,3 +70,45 @@ source.
71
70
  - Update README examples and the scaffold skill when an app-facing contract
72
71
  changes. The generated app must be able to use the documented API after a
73
72
  clean `npm install`.
73
+
74
+ ## SDK 0.4 / CLI 2.4 workflow
75
+
76
+ Run `coline-app check` before pushing: it checks types, the manifest, hosted logic,
77
+ and the React bundle without uploading. `dev --internal` updates one development
78
+ version; install it in the workspace and reload after changes. The CLI bundles
79
+ from the app's installed dependencies and preserves imported CSS and inline assets.
80
+ CLI 2.5 compiles app-specific Tailwind v4 and ordinary CSS automatically.
81
+ Import UI styles, then app.css; use complete class names. Local `preview` uses
82
+ the public test workspace and sandbox bridge, requires no credentials, and can
83
+ capture light/dark/mobile/error states with `--screenshots <directory>`.
84
+
85
+ The starter includes a React home and editor, tree mobile fallback, and a tool.
86
+ Use `coline.tools.invoke` or `actions.invokeTool` to run the same declared tool
87
+ from UI that Kairo runs. Save with `expectedVersion` to detect concurrent edits.
88
+ Homes/editors can write within grants; previews and server render handlers cannot.
89
+ `createTestWorkspace(app).client()` tests the interactive contract and
90
+ `grantedPermissions` simulates revoked consent.
91
+
92
+ New `tasks`, `calendar`, `messages`, and `references` capabilities require their
93
+ explicit manifest permissions and retain the invoking user's workspace access.
94
+ Use `files.list({ scope: "workspace" })` for shared files; document writes stay
95
+ with the owning app. Collections are install-private. Code integration and a
96
+ native mobile React runtime are separate work.
97
+
98
+ `src/live-collection.ts` wraps the SDK's canonical live-record implementation.
99
+ Keep state/conflict/sync logic in the SDK; React owns only subscriptions and
100
+ lifecycle. Inline serializable query objects must not restart the view on each
101
+ render. React Strict Mode cleanup/start must remain supported. Never infer record
102
+ permission from optimistic state or broadcast private fields to an install room.
103
+
104
+ ## UI 0.4.1 defaults
105
+
106
+ Use `Tabs` / `TabsList` / `TabsTrigger` / `TabsContent` for app views. The raised
107
+ sliding selection and content transition are automatic. Do not recreate tab
108
+ buttons or choose the opt-in line variant for standard Coline navigation.
109
+ Use `FilterMenu` for value filters, and `DropdownMenu` for actions. Both use the
110
+ canonical Coline menu surface and highlight. `pnpm check:parity` enforces the
111
+ vendored dropdown implementation; `pnpm sync:platform` refreshes it.
112
+ Keep animation CSS in the package, respect reduced motion, and verify controls
113
+ in a portalled dialog as well as on the page. A form submit button needs explicit
114
+ `type="submit"`. Do not restyle shared controls with app-specific CSS.
package/README.md CHANGED
@@ -64,3 +64,87 @@ Used inside a Coline App's react-tier surface (`{ tier: "react", entry:
64
64
  Full guides at [coline.app/developers/docs](https://coline.app/developers/docs).
65
65
 
66
66
  MIT © Coline
67
+
68
+ ## SDK 0.4 / CLI 2.5 workflow
69
+
70
+ Run `coline-app check` before pushing: it checks types, the manifest, hosted logic,
71
+ and the React bundle without uploading. `dev --internal` updates one development
72
+ version; install it in the workspace and reload after changes. The CLI bundles
73
+ from the app's installed dependencies and preserves imported CSS and inline assets.
74
+ App-specific Tailwind v4 utilities compile automatically with CLI 2.5. Import
75
+ `@colineapp/ui/styles.css` and then `./app.css`; use complete class names.
76
+
77
+ The starter includes a React home and editor, tree mobile fallback, and a tool.
78
+ Use `coline.tools.invoke` or `actions.invokeTool` to run the same declared tool
79
+ from UI that Kairo runs. Save with `expectedVersion` to detect concurrent edits.
80
+ Homes/editors can write within grants; previews and server render handlers cannot.
81
+ `createTestWorkspace(app).client()` tests the interactive contract and
82
+ `grantedPermissions` simulates revoked consent.
83
+
84
+ New `tasks`, `calendar`, `messages`, and `references` capabilities require their
85
+ explicit manifest permissions and retain the invoking user's workspace access.
86
+ Use `files.list({ scope: "workspace" })` for shared files; document writes stay
87
+ with the owning app. Collections are install-private. Code integration and a
88
+ native mobile React runtime are separate work.
89
+
90
+ ### Live data
91
+
92
+ `useLiveCollection<RecordType>("collection", { where, orderBy, limit })` returns
93
+ `records`, `pending`, `status`, `error`, `nextCursor`, `insert`, `update`, `delete`,
94
+ `setAccess`, and `refresh`. Inline query objects are supported. Mutations update
95
+ local UI immediately and reject on conflicts or permission failures; catch their
96
+ promises to present the error. The hook owns subscription cleanup and reconnect
97
+ recovery. Use filtered/paged views (at most 200 records), not an entire workspace
98
+ in one hook. Structured-record sync does not imply CRDT text editing or offline
99
+ write persistence.
100
+
101
+ ## Screen patterns
102
+
103
+ Use `AppPage` and `PageToolbar` for consistent hierarchy, `RecordTable` with
104
+ `SplitView`/`DetailPanel` for queues, `Board`/`BoardColumn`/`BoardCard` for stages,
105
+ and `SettingsSection` for configuration. `EmptyState`, `AppErrorState`,
106
+ `AppLoadingState`, and `StatusBadge` cover common states. Their CSS ships in
107
+ `@colineapp/ui/styles.css`; they require no app-side utility generation.
108
+
109
+ Patterns compose around your domain and capabilities. They do not supply data,
110
+ routing, drag-and-drop, or persistence. `RecordTable` provides a first-cell button
111
+ when `onOpen` is set (don't nest a second control there); secondary columns hide
112
+ at narrow widths. Split details stack on mobile; the app owns focus management.
113
+ See the scaffold's `examples/` for complete interactive references.
114
+
115
+ ## Shared controls and motion (0.4.1)
116
+
117
+ `Tabs` uses the same raised selection as Coline and Upstream. Selection springs
118
+ and content transitions are automatic; no indicator or animation wrapper is
119
+ required. Each tabs group owns its indicator so multiple groups never collide.
120
+ `TabsIndicator` remains available for existing custom compositions.
121
+
122
+ ```tsx
123
+ <Tabs defaultValue="inbox">
124
+ <TabsList aria-label="Views">
125
+ <TabsTrigger value="inbox">Inbox</TabsTrigger>
126
+ <TabsTrigger value="roadmap">Roadmap</TabsTrigger>
127
+ </TabsList>
128
+ <TabsContent value="inbox">{/* Inbox */}</TabsContent>
129
+ <TabsContent value="roadmap">{/* Roadmap */}</TabsContent>
130
+ </Tabs>
131
+ <FilterMenu
132
+ aria-label="Filter by status"
133
+ value={status}
134
+ onValueChange={setStatus}
135
+ options={[{ value: "all", label: "All statuses" }, { value: "planned", label: "Planned" }]}
136
+ />
137
+ ```
138
+
139
+ `FilterMenu` composes the exact Coline `DropdownMenu` radio group, surface, and
140
+ sliding highlight. Use `DropdownMenu` directly for action menus. `PageToolbar`
141
+ is borderless. `RecordTable` uses separated, rounded selection/hover rows.
142
+ Dialogs and menus include their animation CSS; the provider respects reduced
143
+ motion, including portals. Buttons default to `type="button"`; use
144
+ `type="submit"` for a form's submit action.
145
+
146
+ Use component defaults rather than copying their CSS into the app. Custom CSS
147
+ variables scoped to `AppPage` do not reach portalled dialogs/menus. Keep decorative
148
+ app variables at `:root` when they must cross portals, and retain host theme tokens.
149
+ App bundles include their dependencies: upgrade, rebuild and push to adopt a UI
150
+ release. Updating npm does not rewrite already-published app bundles.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  import * as React$1 from 'react';
3
3
  import { SandboxContext } from '@colineapp/app-runtime';
4
- import { ColineCapabilities } from '@colineapp/sdk/v2';
4
+ import * as _colineapp_sdk_v2 from '@colineapp/sdk/v2';
5
+ import { ColineCapabilities, ColineRecordQuery, LiveCollectionOptions } from '@colineapp/sdk/v2';
5
6
  import * as class_variance_authority_types from 'class-variance-authority/types';
6
7
  import { VariantProps } from 'class-variance-authority';
7
8
  import { Checkbox as Checkbox$1, Dialog as Dialog$1, DropdownMenu as DropdownMenu$1, Label as Label$1, Popover as Popover$1, Progress as Progress$1, Select as Select$1, Separator as Separator$1, Slider as Slider$1, Switch as Switch$1, Tabs as Tabs$1, Toggle as Toggle$1, Tooltip as Tooltip$1 } from 'radix-ui';
@@ -10,7 +11,7 @@ declare function cn(...inputs: ClassValue[]): string;
10
11
 
11
12
  declare function ColineAppProvider({ children }: {
12
13
  children: React$1.ReactNode;
13
- }): React$1.JSX.Element | null;
14
+ }): React$1.JSX.Element;
14
15
  declare function useColine(): ColineCapabilities;
15
16
  declare function useColineContext(): SandboxContext;
16
17
  declare function useColorScheme(): "light" | "dark";
@@ -167,21 +168,21 @@ declare function TableHead({ className, ...props }: React$1.ComponentProps<"th">
167
168
  declare function TableCell({ className, ...props }: React$1.ComponentProps<"td">): React$1.JSX.Element;
168
169
  declare function TableCaption({ className, ...props }: React$1.ComponentProps<"caption">): React$1.JSX.Element;
169
170
 
170
- /** Shared spring for tab pill + trigger layout keep in sync wherever `layout` runs alongside `TabsIndicator`. */
171
+ /** Same raised selection and spring as Coline and Upstream navigation. */
171
172
  declare const TABS_LAYOUT_SPRING: {
172
173
  type: "spring";
173
174
  stiffness: number;
174
175
  damping: number;
175
176
  mass: number;
176
177
  };
177
- declare function Tabs({ className, orientation, ...props }: React$1.ComponentProps<typeof Tabs$1.Root>): React$1.JSX.Element;
178
+ declare function Tabs({ className, orientation, value, defaultValue, onValueChange, ...props }: React$1.ComponentProps<typeof Tabs$1.Root>): React$1.JSX.Element;
178
179
  declare const tabsListVariants: (props?: ({
179
180
  variant?: "default" | "line" | null | undefined;
180
181
  } & class_variance_authority_types.ClassProp) | undefined) => string;
181
182
  declare function TabsList({ className, variant, ...props }: React$1.ComponentProps<typeof Tabs$1.List> & VariantProps<typeof tabsListVariants>): React$1.JSX.Element;
182
- declare function TabsTrigger({ className, ...props }: React$1.ComponentProps<typeof Tabs$1.Trigger>): React$1.JSX.Element;
183
- /** Animated sliding pill indicator for TabsList (Apple-style). */
184
- declare function TabsIndicator({ className, layoutId, }: {
183
+ declare function TabsTrigger({ className, children, value, asChild, ...props }: React$1.ComponentProps<typeof Tabs$1.Trigger>): React$1.JSX.Element;
184
+ /** Optional customization; the raised indicator is included automatically. */
185
+ declare function TabsIndicator({ className, layoutId }: {
185
186
  className?: string;
186
187
  layoutId?: string;
187
188
  }): React$1.JSX.Element;
@@ -200,4 +201,113 @@ declare function Tooltip({ ...props }: React$1.ComponentProps<typeof Tooltip$1.R
200
201
  declare function TooltipTrigger({ ...props }: React$1.ComponentProps<typeof Tooltip$1.Trigger>): React$1.JSX.Element;
201
202
  declare function TooltipContent({ className, sideOffset, children, ...props }: React$1.ComponentProps<typeof Tooltip$1.Content>): React$1.JSX.Element;
202
203
 
203
- export { Badge, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, ColineAppProvider, type ColineQueryState, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Input, Label, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, Progress, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Skeleton, Slider, Switch, TABS_LAYOUT_SPRING, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger, Textarea, Toggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants, cn, tabsListVariants, toggleVariants, useColine, useColineContext, useColineQuery, useColorScheme };
204
+ /** Inline query objects are safe: equivalent inputs retain the same live view. */
205
+ declare function useLiveCollection<T extends Record<string, unknown>>(name: string, query?: ColineRecordQuery<T>, options?: LiveCollectionOptions): {
206
+ insert: (data: T, access?: _colineapp_sdk_v2.ColineRecordAccess) => Promise<_colineapp_sdk_v2.ColineRecordEnvelope<T> | null>;
207
+ update: (id: string, patch: Partial<T>) => Promise<_colineapp_sdk_v2.ColineRecordEnvelope<T> | null>;
208
+ delete: (id: string) => Promise<_colineapp_sdk_v2.ColineRecordEnvelope<T> | null>;
209
+ setAccess: (id: string, access: _colineapp_sdk_v2.ColineRecordAccess) => Promise<_colineapp_sdk_v2.ColineRecordEnvelope<T> | null>;
210
+ refresh: () => Promise<void>;
211
+ records: readonly _colineapp_sdk_v2.ColineRecordEnvelope<T>[];
212
+ nextCursor: string | null;
213
+ status: "loading" | "ready" | "syncing" | "error";
214
+ pending: number;
215
+ error: Error | null;
216
+ };
217
+
218
+ declare function AppPage({ title, description, eyebrow, actions, children, width, className, }: {
219
+ title: string;
220
+ description?: React$1.ReactNode;
221
+ eyebrow?: React$1.ReactNode;
222
+ actions?: React$1.ReactNode;
223
+ children: React$1.ReactNode;
224
+ width?: "wide" | "reading";
225
+ className?: string;
226
+ }): React$1.JSX.Element;
227
+ declare function PageToolbar({ children, label, className, }: {
228
+ children: React$1.ReactNode;
229
+ label?: string;
230
+ className?: string;
231
+ }): React$1.JSX.Element;
232
+ declare function EmptyState({ title, description, action, icon, }: {
233
+ title: string;
234
+ description?: React$1.ReactNode;
235
+ action?: React$1.ReactNode;
236
+ icon?: React$1.ReactNode;
237
+ }): React$1.JSX.Element;
238
+ declare function AppErrorState({ message, onRetry }: {
239
+ message: string;
240
+ onRetry?: () => void;
241
+ }): React$1.JSX.Element;
242
+ declare function AppLoadingState({ label, rows, }: {
243
+ label?: string;
244
+ rows?: number;
245
+ }): React$1.JSX.Element;
246
+ declare function StatusBadge({ children, tone, }: {
247
+ children: React$1.ReactNode;
248
+ tone?: "neutral" | "info" | "success" | "warning" | "danger";
249
+ }): React$1.JSX.Element;
250
+ declare function SplitView({ list, detail, label, }: {
251
+ list: React$1.ReactNode;
252
+ detail?: React$1.ReactNode;
253
+ label?: string;
254
+ }): React$1.JSX.Element;
255
+ declare function DetailPanel({ title, subtitle, onClose, children, actions, }: {
256
+ title: string;
257
+ subtitle?: React$1.ReactNode;
258
+ onClose?: () => void;
259
+ children: React$1.ReactNode;
260
+ actions?: React$1.ReactNode;
261
+ }): React$1.JSX.Element;
262
+ interface RecordColumn<T> {
263
+ key: string;
264
+ label: string;
265
+ render: (record: T) => React$1.ReactNode;
266
+ secondary?: boolean;
267
+ align?: "start" | "end";
268
+ }
269
+ declare function RecordTable<T>({ records, columns, rowKey, onOpen, label, empty, }: {
270
+ records: readonly T[];
271
+ columns: readonly RecordColumn<T>[];
272
+ rowKey: (record: T) => string;
273
+ onOpen?: (record: T) => void;
274
+ label?: string;
275
+ empty?: React$1.ReactNode;
276
+ }): React$1.JSX.Element;
277
+ declare function Board({ children, label, }: {
278
+ children: React$1.ReactNode;
279
+ label?: string;
280
+ }): React$1.JSX.Element;
281
+ declare function BoardColumn({ title, count, children, action, }: {
282
+ title: string;
283
+ count?: number;
284
+ children: React$1.ReactNode;
285
+ action?: React$1.ReactNode;
286
+ }): React$1.JSX.Element;
287
+ declare function BoardCard({ title, children, footer, onOpen, }: {
288
+ title: string;
289
+ children?: React$1.ReactNode;
290
+ footer?: React$1.ReactNode;
291
+ onOpen?: () => void;
292
+ }): React$1.JSX.Element;
293
+ declare function SettingsSection({ title, description, children, }: {
294
+ title: string;
295
+ description?: string;
296
+ children: React$1.ReactNode;
297
+ }): React$1.JSX.Element;
298
+
299
+ /** A value picker using the same dropdown and sliding highlight as Coline. */
300
+ declare const FilterMenu: React$1.ForwardRefExoticComponent<{
301
+ value: string;
302
+ options: readonly {
303
+ value: string;
304
+ label: string;
305
+ disabled?: boolean;
306
+ }[];
307
+ onValueChange: (value: string) => void;
308
+ "aria-label": string;
309
+ disabled?: boolean;
310
+ className?: string;
311
+ } & React$1.RefAttributes<HTMLButtonElement>>;
312
+
313
+ export { AppErrorState, AppLoadingState, AppPage, Badge, Board, BoardCard, BoardColumn, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, ColineAppProvider, type ColineQueryState, DetailPanel, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, FilterMenu, Input, Label, PageToolbar, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, Progress, type RecordColumn, RecordTable, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SettingsSection, Skeleton, Slider, SplitView, StatusBadge, Switch, TABS_LAYOUT_SPRING, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger, Textarea, Toggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants, cn, tabsListVariants, toggleVariants, useColine, useColineContext, useColineQuery, useColorScheme, useLiveCollection };