twico-ui 1.3.2 → 1.5.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/README.md +1 -0
- package/dist/index.cjs +1110 -695
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +397 -152
- package/dist/index.d.ts +397 -152
- package/dist/index.mjs +1109 -696
- package/dist/index.mjs.map +1 -1
- package/llms.txt +39 -12
- package/package.json +3 -1
- package/styles/twico-ui.css +15 -5
package/llms.txt
CHANGED
|
@@ -291,6 +291,8 @@ Props:
|
|
|
291
291
|
- `children` — `React.ReactNode` — Main content; fills the remaining space and scrolls independently of the fixed sidebar and header.
|
|
292
292
|
- `height` — `string | number` · default `"100dvh"` — Overall shell height; pass a fixed value to embed the shell inside a smaller region (e.g. a demo).
|
|
293
293
|
- `padded` — `boolean` · default `true` — Pads the scrollable content region with the standard page padding; set false for edge-to-edge content.
|
|
294
|
+
- `sidebarOpen` — `boolean` — Open state of the sidebar's off-canvas drawer on mobile; providing this (or onSidebarOpenChange) makes the shell forward overlay/open/onOpenChange to the sidebar element.
|
|
295
|
+
- `onSidebarOpenChange` — `(open: boolean) => void` — Called when the sidebar drawer requests open or close; wire a Navbar's onMenuClick to () => onSidebarOpenChange(true) for the mobile menu button.
|
|
294
296
|
|
|
295
297
|
```jsx
|
|
296
298
|
import { AppShell, Sidebar, Button } from "twico-ui";
|
|
@@ -1330,14 +1332,16 @@ Props:
|
|
|
1330
1332
|
- `rowKey` — `(row,index)=>key` · default `(r,i)=>r.id??i` — Returns a stable unique key per row, defaulting to the row's id or its index, to keep selection and renders consistent.
|
|
1331
1333
|
- `checkboxSelection` — `boolean` · default `false` — Adds a leading checkbox column for selecting rows, enabling batch actions; off by default.
|
|
1332
1334
|
- `batchActions` — `DatatableBatchAction array` · default `[]` — Defines actions shown in the selection toolbar that operate on the currently selected rows; empty by default.
|
|
1333
|
-
- `density` — `compact|standard|comfortable` · default `
|
|
1335
|
+
- `density` — `compact|standard|comfortable` · default `comfortable` — Sets the row height preset (compact, standard, or comfortable) to trade vertical space for readability, defaulting to comfortable.
|
|
1334
1336
|
- `pageSize` — `number` · default `10` — Sets the initial number of rows shown per page, defaulting to 10; pass 0 to disable pagination.
|
|
1335
1337
|
- `pageSizeOptions` — `number array` · default `[5,10,25,50]` — Lists the selectable rows-per-page values offered in the pagination control, defaulting to [5,10,25,50].
|
|
1336
1338
|
- `height` — `number` · default `440` — Sets the maximum scroll height of the grid body in pixels before rows scroll internally, defaulting to 440.
|
|
1337
1339
|
- `serverMode` — `boolean` · default `false` — Switches to server-side data handling so sorting, filtering, and paging are delegated to your backend; off by default.
|
|
1338
1340
|
- `rowCount` — `number` · default `-` — Tells the grid the total number of server-side rows so pagination can render correctly in serverMode.
|
|
1339
1341
|
- `onServerChange` — `(state)=>void` · default `-` — Fires with the current query state (sort, filter, page) in serverMode so you can fetch the matching rows.
|
|
1340
|
-
- `showExport` — `boolean` · default `
|
|
1342
|
+
- `showExport` — `boolean` · default `false` — Shows the toolbar Export button (CSV split button with a format menu); hidden by default — enable it to expose exporting.
|
|
1343
|
+
- `showDensity` — `boolean` · default `false` — Shows the toolbar density button that cycles compact/standard/comfortable; hidden by default (the density prop still sets the row height).
|
|
1344
|
+
- `showPivot` — `boolean` · default `false` — Shows the toolbar Pivot button; hidden by default, but appears automatically when a pivot model or pivotMode is provided.
|
|
1341
1345
|
- `exportFilename` — `string` · default `export` — Sets the base filename used for exported files, defaulting to "export".
|
|
1342
1346
|
- `aggregationValues` — `object|null` · default `null` — Supplies precomputed footer aggregation values for serverMode, where totals cannot be calculated client-side; null by default.
|
|
1343
1347
|
- `disableColumnReorder` — `boolean` · default `false` — Prevents users from dragging columns into a new order, locking the column arrangement; off by default.
|
|
@@ -1351,7 +1355,7 @@ Props:
|
|
|
1351
1355
|
- `onRowClick` — `(row,key)=>void` · default `-` — Fires with the clicked row and its key, useful for navigation or opening a detail view.
|
|
1352
1356
|
- `onCellClick` — `(value,row,field)=>void` · default `-` — Fires with the clicked cell's value, its row, and the field name when a cell is clicked.
|
|
1353
1357
|
- `onActiveCellChange` — `(cell|null)=>void` · default `-` — Fires when the active cell changes via keyboard or click, receiving the new cell descriptor or null.
|
|
1354
|
-
- `showAggregation` — `boolean` · default `false` — Shows
|
|
1358
|
+
- `showAggregation` — `boolean` · default `false` — Shows the toolbar Aggregation button and starts with the totals row on; hidden by default, so enable it to expose column aggregations.
|
|
1355
1359
|
- `ariaLabel` — `string` · default `Data table` — Sets the grid's accessible aria-label for screen readers, defaulting to "Data table".
|
|
1356
1360
|
- `rowGrouping` — `string array` · default `[]` — Lists the field names to group rows by on initial render, collapsing rows into expandable groups; empty by default.
|
|
1357
1361
|
- `rowPinning` — `boolean` · default `false` — Allows users to pin rows to the top or bottom so they stay visible while scrolling; off by default.
|
|
@@ -1453,6 +1457,8 @@ export default function Example() {
|
|
|
1453
1457
|
onRowUpdate={(updated) => setRows((d) => d.map((r) => (r.id === updated.id ? updated : r)))}
|
|
1454
1458
|
onBatchUpdate={(changed) => setRows((d) => d.map((r) => changed.find((c) => c.id === r.id) || r))}
|
|
1455
1459
|
showAggregation
|
|
1460
|
+
showDensity
|
|
1461
|
+
showExport
|
|
1456
1462
|
rowPinning
|
|
1457
1463
|
pageSize={10}
|
|
1458
1464
|
/>
|
|
@@ -1770,6 +1776,11 @@ Props:
|
|
|
1770
1776
|
- `defaultCollapsed` — `boolean` · default `false` — Initial collapsed state for uncontrolled usage, defaulting to false so the sidebar starts fully expanded.
|
|
1771
1777
|
- `collapsible` — `boolean` · default `true` — Shows the collapse toggle button when true (the default), allowing users to switch to the icon-only rail.
|
|
1772
1778
|
- `onCollapsedChange` — `(collapsed: boolean) => void` — Fires with the new boolean state whenever the collapse toggle is activated, useful for persisting the preference.
|
|
1779
|
+
- `overlay` — `boolean` · default `false` — Renders the sidebar as an off-canvas drawer instead of an in-flow rail: a fixed slide-over panel behind a dismissable backdrop, portaled to the body, with a focus trap, Escape-to-close, and scroll lock.
|
|
1780
|
+
- `open` — `boolean` — Controlled open state of the overlay drawer (only meaningful when overlay is set); the parent owns visibility.
|
|
1781
|
+
- `defaultOpen` — `boolean` · default `false` — Initial open state of the overlay drawer for uncontrolled usage, defaulting to closed.
|
|
1782
|
+
- `onOpenChange` — `(open: boolean) => void` — Fires when the overlay drawer requests open or close (backdrop click or Escape); wire it to your open state.
|
|
1783
|
+
- `navLabel` — `string` · default `"Main"` — Accessible name for the inner nav landmark and the overlay dialog, so assistive tech can distinguish multiple navigations.
|
|
1773
1784
|
|
|
1774
1785
|
```jsx
|
|
1775
1786
|
import { Sidebar } from "twico-ui";
|
|
@@ -2275,7 +2286,7 @@ function Page() {
|
|
|
2275
2286
|
}
|
|
2276
2287
|
```
|
|
2277
2288
|
|
|
2278
|
-
## Hooks (
|
|
2289
|
+
## Hooks (25)
|
|
2279
2290
|
|
|
2280
2291
|
### useIsomorphicLayoutEffect
|
|
2281
2292
|
|
|
@@ -2319,18 +2330,18 @@ export function useDisclosure(initial?: boolean): { open: boolean; onOpen: () =>
|
|
|
2319
2330
|
|
|
2320
2331
|
### useControllableState
|
|
2321
2332
|
|
|
2322
|
-
Controlled/uncontrolled state — the pattern every form component needs.
|
|
2333
|
+
Controlled/uncontrolled state — the pattern every form component needs. Returns `[value, setValue, isControlled]`; the third element reports whether a `value` prop is currently driving the state. In development it warns once if a component switches between controlled and uncontrolled.
|
|
2323
2334
|
|
|
2324
2335
|
```ts
|
|
2325
|
-
export function useControllableState<T>(options?: { value?: T; defaultValue?: T; onChange?: (value: T) => void; }): [T, (next: T | ((prev: T) => T)) => void];
|
|
2336
|
+
export function useControllableState<T>(options?: { value?: T; defaultValue?: T; onChange?: (value: T) => void; }): [T, (next: T | ((prev: T) => T)) => void, boolean];
|
|
2326
2337
|
```
|
|
2327
2338
|
|
|
2328
2339
|
### useMediaQuery
|
|
2329
2340
|
|
|
2330
|
-
Reactively match a media query
|
|
2341
|
+
Reactively match a media query. Returns `defaultValue` on the server and the first client render, then syncs after mount — so hydration never mismatches.
|
|
2331
2342
|
|
|
2332
2343
|
```ts
|
|
2333
|
-
export function useMediaQuery(query: string): boolean;
|
|
2344
|
+
export function useMediaQuery(query: string, options?: UseMediaQueryOptions): boolean;
|
|
2334
2345
|
```
|
|
2335
2346
|
|
|
2336
2347
|
### usePrefersReducedMotion
|
|
@@ -2354,7 +2365,7 @@ export function useColorScheme(options?: UseColorSchemeOptions): { theme: "light
|
|
|
2354
2365
|
Attach an event listener (window by default, or a ref/element) with cleanup.
|
|
2355
2366
|
|
|
2356
2367
|
```ts
|
|
2357
|
-
export function useEventListener( eventName: string, handler: (event: any) => void, element?: React.RefObject<any> | EventTarget | null, options?: boolean | AddEventListenerOptions ): void;
|
|
2368
|
+
export function useEventListener( eventName: string, handler: (event: any) => void, element?: React.RefObject<any | null> | EventTarget | null, options?: boolean | AddEventListenerOptions ): void;
|
|
2358
2369
|
```
|
|
2359
2370
|
|
|
2360
2371
|
### useClickOutside
|
|
@@ -2362,7 +2373,7 @@ export function useEventListener( eventName: string, handler: (event: any) => vo
|
|
|
2362
2373
|
Call `handler` when a pointer/touch event lands outside `ref`.
|
|
2363
2374
|
|
|
2364
2375
|
```ts
|
|
2365
|
-
export function useClickOutside<T extends HTMLElement = HTMLElement>( ref: React.RefObject<T>, handler: (event: Event) => void, events?: string[] ): void;
|
|
2376
|
+
export function useClickOutside<T extends HTMLElement = HTMLElement>( ref: React.RefObject<T | null>, handler: (event: Event) => void, events?: string[] ): void;
|
|
2366
2377
|
```
|
|
2367
2378
|
|
|
2368
2379
|
### useKeyPress
|
|
@@ -2434,7 +2445,7 @@ export function useWindowSize(): { width: number; height: number };
|
|
|
2434
2445
|
`true` while the pointer is over the element referenced by `ref`.
|
|
2435
2446
|
|
|
2436
2447
|
```ts
|
|
2437
|
-
export function useHover<T extends HTMLElement = HTMLElement>(ref: React.RefObject<T>): boolean;
|
|
2448
|
+
export function useHover<T extends HTMLElement = HTMLElement>(ref: React.RefObject<T | null>): boolean;
|
|
2438
2449
|
```
|
|
2439
2450
|
|
|
2440
2451
|
### useIntersectionObserver
|
|
@@ -2442,7 +2453,7 @@ export function useHover<T extends HTMLElement = HTMLElement>(ref: React.RefObje
|
|
|
2442
2453
|
The latest IntersectionObserver entry for the element referenced by `ref`.
|
|
2443
2454
|
|
|
2444
2455
|
```ts
|
|
2445
|
-
export function useIntersectionObserver<T extends HTMLElement = HTMLElement>( ref: React.RefObject<T>, options?: IntersectionObserverInit ): IntersectionObserverEntry | null;
|
|
2456
|
+
export function useIntersectionObserver<T extends HTMLElement = HTMLElement>( ref: React.RefObject<T | null>, options?: IntersectionObserverInit ): IntersectionObserverEntry | null;
|
|
2446
2457
|
```
|
|
2447
2458
|
|
|
2448
2459
|
### useScrollLock
|
|
@@ -2461,6 +2472,22 @@ A stable, SSR-safe unique id (optionally prefixed).
|
|
|
2461
2472
|
export function useId(prefix?: string): string;
|
|
2462
2473
|
```
|
|
2463
2474
|
|
|
2475
|
+
### useFocusTrap
|
|
2476
|
+
|
|
2477
|
+
Trap focus inside the modal region referenced by `ref`. While `active`, focus moves inside on activate, Tab/Shift+Tab cycle within it, and (by default) focus is restored to the previously-focused element on deactivate. Escape is NOT handled — that stays with the component. SSR-safe.
|
|
2478
|
+
|
|
2479
|
+
```ts
|
|
2480
|
+
export function useFocusTrap<T extends HTMLElement = HTMLElement>( ref: React.RefObject<T | null>, active?: boolean, options?: UseFocusTrapOptions ): void;
|
|
2481
|
+
```
|
|
2482
|
+
|
|
2483
|
+
### usePortal
|
|
2484
|
+
|
|
2485
|
+
Returns a stable `render(node)` that portals `node` to `document.body`, or `null` on the server (no document). Centralizes the overlay portal pattern.
|
|
2486
|
+
|
|
2487
|
+
```ts
|
|
2488
|
+
export function usePortal(): (node: React.ReactNode) => React.ReactPortal | React.ReactNode | null;
|
|
2489
|
+
```
|
|
2490
|
+
|
|
2464
2491
|
---
|
|
2465
2492
|
|
|
2466
2493
|
_Generated by `scripts/gen-llms.mjs`. Do not edit by hand — run `npm run gen:llms`. Source of truth: the component `.d.ts` files and `hooks/index.d.ts`._
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "twico-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Twico UI — a free, modern, themeable React + Tailwind-friendly component library. 61 components with dark mode, motion, and accessibility built in.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Twico UI",
|
|
@@ -82,6 +82,8 @@
|
|
|
82
82
|
"gen:llms:check": "node scripts/gen-llms.mjs --check",
|
|
83
83
|
"typecheck": "tsc --noEmit",
|
|
84
84
|
"check:exports": "attw --pack . --profile node16 --exclude-entrypoints styles.css",
|
|
85
|
+
"gen:ds-bundle": "node scripts/gen-ds-bundle.mjs",
|
|
86
|
+
"check:ds-bundle": "node scripts/check-ds-bundle.mjs",
|
|
85
87
|
"test": "vitest",
|
|
86
88
|
"test:run": "vitest run",
|
|
87
89
|
"size": "size-limit",
|
package/styles/twico-ui.css
CHANGED
|
@@ -169,8 +169,9 @@
|
|
|
169
169
|
--color-primary-subtle-fg: var(--brand-700);
|
|
170
170
|
--color-primary-border: var(--brand-200);
|
|
171
171
|
|
|
172
|
-
/* Focus ring
|
|
173
|
-
|
|
172
|
+
/* Focus ring — solid brand so the 3px ring clears WCAG 2.4.11 / 1.4.11 (3:1)
|
|
173
|
+
on light surfaces (a translucent indigo alpha-composited to only ~1.8:1). */
|
|
174
|
+
--color-ring: var(--brand-500);
|
|
174
175
|
|
|
175
176
|
/* Success */
|
|
176
177
|
--color-success: var(--emerald-600);
|
|
@@ -180,7 +181,7 @@
|
|
|
180
181
|
|
|
181
182
|
/* Warning */
|
|
182
183
|
--color-warning: var(--amber-500);
|
|
183
|
-
--color-warning-fg:
|
|
184
|
+
--color-warning-fg: var(--amber-950); /* dark ink on amber-500 = 6.97:1 (white was 2.15:1) */
|
|
184
185
|
--color-warning-subtle: var(--amber-50);
|
|
185
186
|
--color-warning-subtle-fg: var(--amber-600);
|
|
186
187
|
|
|
@@ -193,7 +194,7 @@
|
|
|
193
194
|
|
|
194
195
|
/* Info */
|
|
195
196
|
--color-info: var(--sky-500);
|
|
196
|
-
--color-info-fg:
|
|
197
|
+
--color-info-fg: var(--sky-950); /* dark ink on sky-500 (white was 2.77:1) */
|
|
197
198
|
--color-info-subtle: var(--sky-50);
|
|
198
199
|
--color-info-subtle-fg: var(--sky-600);
|
|
199
200
|
}
|
|
@@ -229,7 +230,7 @@
|
|
|
229
230
|
--color-primary-subtle-fg: var(--brand-300);
|
|
230
231
|
--color-primary-border: rgb(99 102 241 / 0.35);
|
|
231
232
|
|
|
232
|
-
--color-ring:
|
|
233
|
+
--color-ring: var(--brand-400); /* solid brand-400 ≈ 5.7:1 on slate-900 (translucent was ~2.7:1) */
|
|
233
234
|
|
|
234
235
|
--color-success: var(--emerald-500);
|
|
235
236
|
--color-success-fg: #052e1d;
|
|
@@ -564,6 +565,15 @@ textarea:focus-visible,
|
|
|
564
565
|
select:focus-visible {
|
|
565
566
|
box-shadow: none;
|
|
566
567
|
}
|
|
568
|
+
/* Windows High Contrast / forced-colors strips author box-shadows, which would
|
|
569
|
+
erase the box-shadow focus ring entirely. Repaint a real outline in the user's
|
|
570
|
+
system palette (CanvasText) — the designed ring is untouched in normal render. */
|
|
571
|
+
@media (forced-colors: active) {
|
|
572
|
+
:focus-visible {
|
|
573
|
+
outline: 2px solid CanvasText;
|
|
574
|
+
outline-offset: 2px;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
567
577
|
|
|
568
578
|
::selection {
|
|
569
579
|
background: var(--color-primary-subtle);
|