@close-by/clay 0.2.11 → 0.2.13
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/docs/boot.md +12 -0
- package/docs/elements.md +2 -1
- package/docs/ops-patterns.md +24 -6
- package/package.json +5 -5
- package/src/index.ts +32 -0
package/docs/boot.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
Clay has two entry styles. Prefer **one production path** (library mode) and treat the CLI as a thin dev wrapper so port, CSS, and `clientDir` do not drift.
|
|
4
4
|
|
|
5
|
+
### Dev HTML comments
|
|
6
|
+
|
|
7
|
+
When `dev` is on (default unless `NODE_ENV=production`, or set `ui.run({ dev: true })`), the shell sets `window.__CLAY_DEV__` and the client inserts HTML comments around each wire node:
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<!-- clay:staticTable -->
|
|
11
|
+
…table markup…
|
|
12
|
+
<!-- /clay:staticTable -->
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Pass `dev: false` to disable.
|
|
16
|
+
|
|
5
17
|
## Recommended production path — library mode
|
|
6
18
|
|
|
7
19
|
```typescript
|
package/docs/elements.md
CHANGED
|
@@ -34,7 +34,7 @@ Each factory creates an `Element` with a wire `type` string. The React client ma
|
|
|
34
34
|
| `inputGroup` | `inputGroup` | Input with prefix/suffix addons |
|
|
35
35
|
| `toggle` | `toggle` | Pressed toolbar toggle |
|
|
36
36
|
| `descriptionList` | `descriptionList` | Key-value detail rows |
|
|
37
|
-
| `staticTable` | `staticTable` | Read-only HTML table |
|
|
37
|
+
| `staticTable` | `staticTable` | Read-only HTML table (`bordered`/`hoverable` default on; `density`, `emptyTitle`, column `mono`) |
|
|
38
38
|
| `aspectRatio` | `aspectRatio` | Fixed-ratio child wrapper |
|
|
39
39
|
| `itemList` | `itemList` | Settings / notification rows |
|
|
40
40
|
| `checkboxGroup` | `checkboxGroup` | Multi-select checkboxes |
|
|
@@ -76,6 +76,7 @@ Each factory creates an `Element` with a wire `type` string. The React client ma
|
|
|
76
76
|
| `badge` | `badge` | ShadCN `Badge` |
|
|
77
77
|
| `alert` | `alert` | Bordered alert box |
|
|
78
78
|
| `spinner` | `spinner` | Lucide spinner |
|
|
79
|
+
| `spacer` | `spacer` | Fixed gap (`orientation` default `horizontal`; `size` xs–xl) |
|
|
79
80
|
| `skeleton` | `skeleton` | ShadCN `Skeleton` placeholder |
|
|
80
81
|
| `avatar` | `avatar` | ShadCN `Avatar` (+ fallback) |
|
|
81
82
|
| `progress` | `progress` | ShadCN `Progress` (0–100) |
|
package/docs/ops-patterns.md
CHANGED
|
@@ -39,9 +39,9 @@ const live = ui.state({ selectedId: null as string | null, rows: [] as Row[] });
|
|
|
39
39
|
|
|
40
40
|
ui.auto(() => {
|
|
41
41
|
ui.resizable(
|
|
42
|
-
{ orientation: 'horizontal',
|
|
42
|
+
{ orientation: 'horizontal', fill: 'viewport' },
|
|
43
43
|
(r) => {
|
|
44
|
-
r.panel({ defaultSize: 40, minSize: 28 }, () => {
|
|
44
|
+
r.panel({ defaultSize: 40, minSize: 28, className: 'min-h-0 overflow-hidden' }, () => {
|
|
45
45
|
ui.auto(() => {
|
|
46
46
|
for (const row of live.rows) {
|
|
47
47
|
ui.button(row.id, {
|
|
@@ -54,11 +54,12 @@ ui.auto(() => {
|
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
|
-
r.
|
|
57
|
+
r.handle();
|
|
58
|
+
r.panel({ defaultSize: 60, minSize: 36, className: 'min-h-0 overflow-hidden' }, () => {
|
|
58
59
|
ui.auto(() => {
|
|
59
60
|
const row = live.rows.find((x) => x.id === live.selectedId);
|
|
60
61
|
if (!row) {
|
|
61
|
-
ui.
|
|
62
|
+
ui.empty({ title: 'Select a row', density: 'inline' });
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
64
65
|
// detail…
|
|
@@ -70,7 +71,7 @@ ui.auto(() => {
|
|
|
70
71
|
});
|
|
71
72
|
```
|
|
72
73
|
|
|
73
|
-
Keep **separate** `ui.auto` regions for list vs detail so selection updates do not remount the whole shell. Default panel sizes (`defaultSize` / `minSize`) are percentages.
|
|
74
|
+
Keep **separate** `ui.auto` regions for list vs detail so selection updates do not remount the whole shell. Default panel sizes (`defaultSize` / `minSize`) are percentages. Prefer `fill: 'parent' | 'viewport'` over viewport `calc` height utilities.
|
|
74
75
|
|
|
75
76
|
## Live feed rows (not `ui.list`)
|
|
76
77
|
|
|
@@ -163,7 +164,7 @@ For **`ui.dataTable`**, pass `showFilterChips: true` to surface active search +
|
|
|
163
164
|
```ts
|
|
164
165
|
ui.auto(() => {
|
|
165
166
|
if (live.loadingMore) {
|
|
166
|
-
ui.label('Loading…'
|
|
167
|
+
ui.label('Loading…', { tone: 'muted', size: 'xs' });
|
|
167
168
|
return;
|
|
168
169
|
}
|
|
169
170
|
if (!live.hasMore) return;
|
|
@@ -183,6 +184,23 @@ ui.auto(() => {
|
|
|
183
184
|
|
|
184
185
|
Alternative when you already wrap the list in **`ui.scrollArea`**: use `onNearEnd` on the scroll area (scroll-root is built-in). Prefer one pattern per surface — `viewportEnter` + `nearest-scroll` does **not** require `scrollArea`.
|
|
185
186
|
|
|
187
|
+
## Fewer classes (ops density)
|
|
188
|
+
|
|
189
|
+
Prefer semantic props over Tailwind soup:
|
|
190
|
+
|
|
191
|
+
| Instead of… | Prefer… |
|
|
192
|
+
|-------------|---------|
|
|
193
|
+
| `.classes('text-sm text-muted-foreground')` | `ui.label(…, { tone: 'muted', size: 'sm' })` |
|
|
194
|
+
| Title + subtitle stacks | `ui.pageHeading('Orders', { description: '…' })` |
|
|
195
|
+
| `className: 'flex-row w-[10rem]'` on filters | `ui.select({ inline: true, width: 'sm', … })` |
|
|
196
|
+
| `ui.spinner({ className: 'h-3 w-3' })` | `ui.spinner({ size: 'xs' })` |
|
|
197
|
+
| Feed empty muted label | `ui.empty({ title: '…', density: 'inline' })` |
|
|
198
|
+
| `h-[calc(100%-7rem)]!` on resizable | `ui.resizable({ fill: 'parent' \| 'viewport' }, …)` |
|
|
199
|
+
| `className: 'items-end justify-between'` on rows | `ui.row({ align: 'end', justify: 'between' }, …)` |
|
|
200
|
+
| `className: 'mb-2'` between uneven blocks | Parent `column({ gap })`, or `ui.spacer({ orientation: 'vertical', size: 'md' })` |
|
|
201
|
+
|
|
202
|
+
Prefer even stacks via parent `gap`. Use `ui.spacer` for uneven breaks (`orientation` default **`horizontal`**; `vertical` for column stacks). `className` remains an escape hatch.
|
|
203
|
+
|
|
186
204
|
## Logs / traces — sensitive bodies
|
|
187
205
|
|
|
188
206
|
Structured logs often contain API keys or partner tokens. Scrubbing is the **app’s** job; Clay can still reduce shoulder-surfing:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@close-by/clay",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
4
4
|
"description": "NiceGUI-like ui.* facade for Clay apps",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@close-by/clay-compiler": "0.2.
|
|
41
|
-
"@close-by/clay-core": "0.2.
|
|
42
|
-
"@close-by/clay-components": "0.2.
|
|
43
|
-
"@close-by/clay-server": "0.2.
|
|
40
|
+
"@close-by/clay-compiler": "0.2.13",
|
|
41
|
+
"@close-by/clay-core": "0.2.13",
|
|
42
|
+
"@close-by/clay-components": "0.2.13",
|
|
43
|
+
"@close-by/clay-server": "0.2.13",
|
|
44
44
|
"@tailwindcss/cli": "^4.3.3",
|
|
45
45
|
"tailwindcss": "^4.3.3"
|
|
46
46
|
}
|
package/src/index.ts
CHANGED
|
@@ -34,6 +34,8 @@ import {
|
|
|
34
34
|
pagination as paginationFactory,
|
|
35
35
|
filterBar as filterBarFactory,
|
|
36
36
|
filterChips as filterChipsFactory,
|
|
37
|
+
pageHeading as pageHeadingFactory,
|
|
38
|
+
spacer as spacerFactory,
|
|
37
39
|
numberField as numberFieldFactory,
|
|
38
40
|
phoneInput as phoneInputFactory,
|
|
39
41
|
field as fieldFactory,
|
|
@@ -120,7 +122,10 @@ import {
|
|
|
120
122
|
type ButtonVariant,
|
|
121
123
|
type ButtonSize,
|
|
122
124
|
type LabelProps,
|
|
125
|
+
type LabelTone,
|
|
126
|
+
type LabelSize,
|
|
123
127
|
type InputProps,
|
|
128
|
+
type FieldWidth,
|
|
124
129
|
type CheckboxProps,
|
|
125
130
|
type SwitchProps,
|
|
126
131
|
type SelectProps,
|
|
@@ -144,6 +149,7 @@ import {
|
|
|
144
149
|
type BadgeProps,
|
|
145
150
|
type AlertProps,
|
|
146
151
|
type SpinnerProps,
|
|
152
|
+
type SpinnerSize,
|
|
147
153
|
type ProgressProps,
|
|
148
154
|
type SeparatorProps,
|
|
149
155
|
type IconProps,
|
|
@@ -157,6 +163,11 @@ import {
|
|
|
157
163
|
type ButtonGroupProps,
|
|
158
164
|
type ButtonGroupOrientation,
|
|
159
165
|
type EmptyProps,
|
|
166
|
+
type EmptyDensity,
|
|
167
|
+
type PageHeadingProps,
|
|
168
|
+
type SpacerProps,
|
|
169
|
+
type SpacerSize,
|
|
170
|
+
type SpacerOrientation,
|
|
160
171
|
type PaginationProps,
|
|
161
172
|
type FilterBarProps,
|
|
162
173
|
type FilterChip,
|
|
@@ -181,6 +192,7 @@ import {
|
|
|
181
192
|
type DescriptionListItem,
|
|
182
193
|
type StaticTableProps,
|
|
183
194
|
type StaticTableColumn,
|
|
195
|
+
type StaticTableDensity,
|
|
184
196
|
type AspectRatioProps,
|
|
185
197
|
type ItemListProps,
|
|
186
198
|
type ItemListEntry,
|
|
@@ -253,6 +265,7 @@ import {
|
|
|
253
265
|
type CommandMode,
|
|
254
266
|
type CommandItemOptions,
|
|
255
267
|
type ResizableProps,
|
|
268
|
+
type ResizableFill,
|
|
256
269
|
type ResizableOrientation,
|
|
257
270
|
type ResizablePanelProps,
|
|
258
271
|
type ResizableHandleProps,
|
|
@@ -494,7 +507,10 @@ export type {
|
|
|
494
507
|
ButtonVariant,
|
|
495
508
|
ButtonSize,
|
|
496
509
|
LabelProps,
|
|
510
|
+
LabelTone,
|
|
511
|
+
LabelSize,
|
|
497
512
|
InputProps,
|
|
513
|
+
FieldWidth,
|
|
498
514
|
CheckboxProps,
|
|
499
515
|
BadgeProps,
|
|
500
516
|
LinkProps,
|
|
@@ -555,6 +571,7 @@ export type {
|
|
|
555
571
|
AvatarProps,
|
|
556
572
|
SkeletonProps,
|
|
557
573
|
SpinnerProps,
|
|
574
|
+
SpinnerSize,
|
|
558
575
|
ProgressProps,
|
|
559
576
|
SeparatorProps,
|
|
560
577
|
IconProps,
|
|
@@ -931,6 +948,19 @@ export function empty(props: EmptyProps, footer?: () => void): Element {
|
|
|
931
948
|
return emptyFactory(props, footer);
|
|
932
949
|
}
|
|
933
950
|
|
|
951
|
+
/** Page title + optional description. Prefer over stacked muted labels. */
|
|
952
|
+
export function pageHeading(props: PageHeadingProps, trailing?: () => void): Element {
|
|
953
|
+
return pageHeadingFactory(props, trailing);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Explicit space between siblings. Default orientation is horizontal (width).
|
|
958
|
+
* Prefer parent `gap` for even stacks; use spacer for uneven breaks.
|
|
959
|
+
*/
|
|
960
|
+
export function spacer(props?: SpacerProps): Element {
|
|
961
|
+
return spacerFactory(props);
|
|
962
|
+
}
|
|
963
|
+
|
|
934
964
|
/** Standalone pager. See {@link PaginationProps}. */
|
|
935
965
|
export function pagination(props?: PaginationProps): Element {
|
|
936
966
|
return paginationFactory(props);
|
|
@@ -1789,6 +1819,8 @@ export const ui = {
|
|
|
1789
1819
|
feedList,
|
|
1790
1820
|
buttonGroup,
|
|
1791
1821
|
empty,
|
|
1822
|
+
pageHeading,
|
|
1823
|
+
spacer,
|
|
1792
1824
|
pagination,
|
|
1793
1825
|
filterBar,
|
|
1794
1826
|
filterChips,
|