@devalok/shilp-sutra 0.16.1 → 0.17.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/dist/shell/bottom-navbar.js +13 -13
- package/dist/tailwind/index.cjs +1 -1
- package/dist/tailwind/preset.js +1 -1
- package/dist/ui/data-table.d.ts.map +1 -1
- package/dist/ui/data-table.js +193 -188
- package/dist/ui/table.js +13 -13
- package/llms-full.txt +194 -13
- package/llms.txt +29 -14
- package/package.json +1 -1
package/dist/ui/table.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { jsx as o } from "react/jsx-runtime";
|
|
2
2
|
import * as l from "react";
|
|
3
|
-
import { c as
|
|
4
|
-
const
|
|
3
|
+
import { c as s } from "../_chunks/utils.js";
|
|
4
|
+
const r = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ o(
|
|
5
5
|
"table",
|
|
6
6
|
{
|
|
7
7
|
ref: t,
|
|
8
|
-
className:
|
|
8
|
+
className: s("w-full caption-bottom text-ds-md", e),
|
|
9
9
|
...a
|
|
10
10
|
}
|
|
11
11
|
) }));
|
|
12
|
-
|
|
13
|
-
const d = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o("thead", { ref: t, className:
|
|
12
|
+
r.displayName = "Table";
|
|
13
|
+
const d = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o("thead", { ref: t, className: s("", e), ...a }));
|
|
14
14
|
d.displayName = "TableHeader";
|
|
15
15
|
const c = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o(
|
|
16
16
|
"tbody",
|
|
17
17
|
{
|
|
18
18
|
ref: t,
|
|
19
|
-
className:
|
|
19
|
+
className: s("[&_tr:last-child]:border-0", e),
|
|
20
20
|
...a
|
|
21
21
|
}
|
|
22
22
|
));
|
|
@@ -25,7 +25,7 @@ const m = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o(
|
|
|
25
25
|
"tfoot",
|
|
26
26
|
{
|
|
27
27
|
ref: t,
|
|
28
|
-
className:
|
|
28
|
+
className: s(
|
|
29
29
|
"bg-[color-mix(in_srgb,var(--color-layer-02)_50%,transparent)] font-medium [&>tr]:last:border-b-0",
|
|
30
30
|
e
|
|
31
31
|
),
|
|
@@ -37,7 +37,7 @@ const b = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o(
|
|
|
37
37
|
"tr",
|
|
38
38
|
{
|
|
39
39
|
ref: t,
|
|
40
|
-
className:
|
|
40
|
+
className: s(
|
|
41
41
|
"transition-colors hover:bg-layer-02 data-[state=selected]:bg-interactive-selected",
|
|
42
42
|
e
|
|
43
43
|
),
|
|
@@ -50,7 +50,7 @@ const i = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o(
|
|
|
50
50
|
{
|
|
51
51
|
ref: t,
|
|
52
52
|
scope: "col",
|
|
53
|
-
className:
|
|
53
|
+
className: s(
|
|
54
54
|
"h-ds-md px-ds-03 text-left font-medium text-text-secondary [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
55
55
|
e
|
|
56
56
|
),
|
|
@@ -62,8 +62,8 @@ const f = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o(
|
|
|
62
62
|
"td",
|
|
63
63
|
{
|
|
64
64
|
ref: t,
|
|
65
|
-
className:
|
|
66
|
-
"py-ds-03 px-
|
|
65
|
+
className: s(
|
|
66
|
+
"py-ds-03 px-ds-03 [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
67
67
|
e
|
|
68
68
|
),
|
|
69
69
|
...a
|
|
@@ -74,13 +74,13 @@ const n = l.forwardRef(({ className: e, ...a }, t) => /* @__PURE__ */ o(
|
|
|
74
74
|
"caption",
|
|
75
75
|
{
|
|
76
76
|
ref: t,
|
|
77
|
-
className:
|
|
77
|
+
className: s("mt-ds-05 text-ds-md text-text-secondary", e),
|
|
78
78
|
...a
|
|
79
79
|
}
|
|
80
80
|
));
|
|
81
81
|
n.displayName = "TableCaption";
|
|
82
82
|
export {
|
|
83
|
-
|
|
83
|
+
r as Table,
|
|
84
84
|
c as TableBody,
|
|
85
85
|
n as TableCaption,
|
|
86
86
|
f as TableCell,
|
package/llms-full.txt
CHANGED
|
@@ -187,6 +187,7 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
187
187
|
<AvatarImage src={user.photoUrl} alt={user.name} />
|
|
188
188
|
<AvatarFallback>JD</AvatarFallback>
|
|
189
189
|
</Avatar>
|
|
190
|
+
- Type: AvatarStatus = 'online' | 'offline' | 'busy' | 'away'
|
|
190
191
|
- Gotchas:
|
|
191
192
|
- Status dot renders with role="img" and aria-label (accessible, not decorative)
|
|
192
193
|
- Dot size scales automatically with avatar size
|
|
@@ -534,6 +535,7 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
534
535
|
required: boolean
|
|
535
536
|
- Props (FormHelperText):
|
|
536
537
|
state: "helper" | "error" | "warning" | "success" (inherits from FormField context)
|
|
538
|
+
- Type: FormHelperState = 'helper' | 'error' | 'warning' | 'success'
|
|
537
539
|
- Hook: useFormField() => { state, helperTextId, required }
|
|
538
540
|
- Example:
|
|
539
541
|
<FormField state="error">
|
|
@@ -581,9 +583,10 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
581
583
|
## Input
|
|
582
584
|
- Import: @devalok/shilp-sutra/ui/input
|
|
583
585
|
- Server-safe: No
|
|
586
|
+
- Type: InputState = 'default' | 'error' | 'warning' | 'success'
|
|
584
587
|
- Props:
|
|
585
588
|
size: "sm" | "md" | "lg"
|
|
586
|
-
state:
|
|
589
|
+
state: InputState
|
|
587
590
|
startIcon: ReactNode
|
|
588
591
|
endIcon: ReactNode
|
|
589
592
|
(plus all standard HTML input attributes except native "size")
|
|
@@ -814,10 +817,13 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
814
817
|
- Props (SegmentedControl root):
|
|
815
818
|
size: "sm" | "md" | "lg" (REQUIRED) — also accepts legacy "small" | "medium" | "big"
|
|
816
819
|
variant: "filled" | "tonal" (REQUIRED)
|
|
817
|
-
options: SegmentedControlOption[] (REQUIRED)
|
|
820
|
+
options: SegmentedControlOption[] (REQUIRED)
|
|
818
821
|
selectedId: string (REQUIRED)
|
|
819
822
|
onSelect: (id: string) => void (REQUIRED)
|
|
820
823
|
disabled: boolean
|
|
824
|
+
- Type: SegmentedControlOption = { id: string, text: string, icon?: ComponentType<{ className?: string }> }
|
|
825
|
+
- Type: SegmentedControlSize = 'sm' | 'md' | 'lg' | 'small' | 'medium' | 'big' (legacy aliases)
|
|
826
|
+
- Type: SegmentedControlVariant = 'filled' | 'tonal'
|
|
821
827
|
- Defaults: None — size and variant are required
|
|
822
828
|
- Example:
|
|
823
829
|
<SegmentedControl
|
|
@@ -1111,8 +1117,9 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
1111
1117
|
## Text
|
|
1112
1118
|
- Import: @devalok/shilp-sutra/ui/text
|
|
1113
1119
|
- Server-safe: Yes
|
|
1120
|
+
- Type: TextVariant = 'heading-2xl' | 'heading-xl' | 'heading-lg' | 'heading-md' | 'heading-sm' | 'heading-xs' | 'body-lg' | 'body-md' | 'body-sm' | 'body-xs' | 'label-lg' | 'label-md' | 'label-sm' | 'label-xs' | 'caption' | 'overline'
|
|
1114
1121
|
- Props:
|
|
1115
|
-
variant:
|
|
1122
|
+
variant: TextVariant
|
|
1116
1123
|
as: ElementType (override the auto-selected HTML element)
|
|
1117
1124
|
- Defaults: variant="body-md"
|
|
1118
1125
|
- Default element mapping:
|
|
@@ -1481,6 +1488,124 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
1481
1488
|
- Example:
|
|
1482
1489
|
<DateTimePicker value={dateTime} onChange={setDateTime} timeFormat="12h" minuteStep={15} />
|
|
1483
1490
|
|
|
1491
|
+
## TimePicker
|
|
1492
|
+
- Import: @devalok/shilp-sutra/composed/date-picker
|
|
1493
|
+
- Server-safe: No
|
|
1494
|
+
- Props:
|
|
1495
|
+
value: Date | null (time stored as a Date object)
|
|
1496
|
+
onChange: (date: Date) => void
|
|
1497
|
+
format: "12h" | "24h" (default: "12h")
|
|
1498
|
+
minuteStep: number (default: 1) — step interval for minutes column
|
|
1499
|
+
secondStep: number (default: 1) — step interval for seconds column
|
|
1500
|
+
showSeconds: boolean (default: false) — whether to show the seconds column
|
|
1501
|
+
placeholder: string (default: "Pick a time")
|
|
1502
|
+
disabled: boolean (default: false)
|
|
1503
|
+
className: string
|
|
1504
|
+
- Defaults: format="12h", minuteStep=1, secondStep=1, showSeconds=false
|
|
1505
|
+
- Example:
|
|
1506
|
+
<TimePicker value={time} onChange={setTime} format="24h" minuteStep={15} />
|
|
1507
|
+
<TimePicker value={time} onChange={setTime} showSeconds />
|
|
1508
|
+
- Gotchas:
|
|
1509
|
+
- Time is stored inside a Date object — only hours/minutes/seconds are meaningful
|
|
1510
|
+
- Opens as a popover with scrollable columns for hours, minutes, (optional) seconds, and AM/PM
|
|
1511
|
+
- When no value is set, selecting a time part creates a Date from the current date/time
|
|
1512
|
+
|
|
1513
|
+
## CalendarGrid
|
|
1514
|
+
- Import: @devalok/shilp-sutra/composed/date-picker
|
|
1515
|
+
- Server-safe: No
|
|
1516
|
+
- Props:
|
|
1517
|
+
currentMonth: Date (REQUIRED) — which month to display
|
|
1518
|
+
selected: Date | null — single selected date
|
|
1519
|
+
rangeStart: Date | null — range selection start
|
|
1520
|
+
rangeEnd: Date | null — range selection end
|
|
1521
|
+
hoverDate: Date | null — date currently hovered (for range preview)
|
|
1522
|
+
onSelect: (date: Date) => void (REQUIRED) — called when user clicks a date
|
|
1523
|
+
onHover: (date: Date | null) => void — called on mouse enter/leave
|
|
1524
|
+
onMonthChange: (date: Date) => void (REQUIRED) — called for prev/next month navigation
|
|
1525
|
+
onHeaderClick: () => void — called when month/year header is clicked (e.g. to switch to month/year picker view)
|
|
1526
|
+
disabledDates: (date: Date) => boolean
|
|
1527
|
+
minDate: Date
|
|
1528
|
+
maxDate: Date
|
|
1529
|
+
hidePrevNav: boolean — hide previous-month arrow
|
|
1530
|
+
hideNextNav: boolean — hide next-month arrow
|
|
1531
|
+
events: CalendarEvent[] — dot indicators on dates. CalendarEvent: { date: Date, color?: string, label?: string }
|
|
1532
|
+
- Example:
|
|
1533
|
+
<CalendarGrid
|
|
1534
|
+
currentMonth={currentMonth}
|
|
1535
|
+
selected={selectedDate}
|
|
1536
|
+
onSelect={setSelectedDate}
|
|
1537
|
+
onMonthChange={setCurrentMonth}
|
|
1538
|
+
events={[{ date: new Date('2026-03-15'), color: 'var(--color-success)' }]}
|
|
1539
|
+
/>
|
|
1540
|
+
- Gotchas:
|
|
1541
|
+
- This is a low-level building block — prefer DatePicker/DateRangePicker for most use cases
|
|
1542
|
+
- Full keyboard navigation: ArrowLeft/Right/Up/Down, Home/End, Enter/Space
|
|
1543
|
+
- Up to 3 event dots render per day cell
|
|
1544
|
+
|
|
1545
|
+
## YearPicker
|
|
1546
|
+
- Import: @devalok/shilp-sutra/composed/date-picker
|
|
1547
|
+
- Server-safe: No
|
|
1548
|
+
- Props:
|
|
1549
|
+
currentYear: number (REQUIRED) — centers the decade grid
|
|
1550
|
+
selectedYear: number — highlights the selected year
|
|
1551
|
+
onYearSelect: (year: number) => void (REQUIRED)
|
|
1552
|
+
minDate: Date — disables years before this date's year
|
|
1553
|
+
maxDate: Date — disables years after this date's year
|
|
1554
|
+
- Example:
|
|
1555
|
+
<YearPicker currentYear={2026} selectedYear={2026} onYearSelect={handleYear} />
|
|
1556
|
+
- Gotchas:
|
|
1557
|
+
- Displays a 12-year grid (3 columns x 4 rows) based on the decade of currentYear
|
|
1558
|
+
- This is a low-level building block used internally by DatePicker
|
|
1559
|
+
|
|
1560
|
+
## MonthPicker
|
|
1561
|
+
- Import: @devalok/shilp-sutra/composed/date-picker
|
|
1562
|
+
- Server-safe: No
|
|
1563
|
+
- Props:
|
|
1564
|
+
currentYear: number (REQUIRED) — which year's months to display
|
|
1565
|
+
selectedMonth: number (0-11) — highlights the selected month
|
|
1566
|
+
onMonthSelect: (month: number) => void (REQUIRED) — returns 0-11
|
|
1567
|
+
minDate: Date — disables months before this date
|
|
1568
|
+
maxDate: Date — disables months after this date
|
|
1569
|
+
- Example:
|
|
1570
|
+
<MonthPicker currentYear={2026} selectedMonth={2} onMonthSelect={handleMonth} />
|
|
1571
|
+
- Gotchas:
|
|
1572
|
+
- Month values are 0-indexed (Jan=0, Dec=11) — same as JavaScript Date.getMonth()
|
|
1573
|
+
- Displays a 4-column grid of abbreviated month names (Jan, Feb, Mar, ...)
|
|
1574
|
+
- This is a low-level building block used internally by DatePicker
|
|
1575
|
+
|
|
1576
|
+
## Presets (Date Range Presets)
|
|
1577
|
+
- Import: @devalok/shilp-sutra/composed/date-picker
|
|
1578
|
+
- Server-safe: No
|
|
1579
|
+
- Types:
|
|
1580
|
+
PresetKey: 'today' | 'yesterday' | 'last7days' | 'last30days' | 'thisMonth' | 'lastMonth' | 'thisYear'
|
|
1581
|
+
- Props:
|
|
1582
|
+
presets: PresetKey[] (REQUIRED) — which preset buttons to show
|
|
1583
|
+
onSelect: (start: Date, end: Date) => void (REQUIRED) — called with the computed date range
|
|
1584
|
+
className: string
|
|
1585
|
+
- Example:
|
|
1586
|
+
<Presets
|
|
1587
|
+
presets={['today', 'last7days', 'last30days', 'thisMonth']}
|
|
1588
|
+
onSelect={(start, end) => setRange({ start, end })}
|
|
1589
|
+
/>
|
|
1590
|
+
- Gotchas:
|
|
1591
|
+
- Typically used alongside DateRangePicker (pass presets prop to DateRangePicker for built-in sidebar)
|
|
1592
|
+
- Each preset computes start-of-day / end-of-day boundaries using date-fns
|
|
1593
|
+
|
|
1594
|
+
## useCalendar
|
|
1595
|
+
- Import: @devalok/shilp-sutra/composed/date-picker
|
|
1596
|
+
- Hook: useCalendar(initialMonth?: Date)
|
|
1597
|
+
- Returns:
|
|
1598
|
+
currentMonth: Date — the current displayed month
|
|
1599
|
+
setCurrentMonth: (date: Date) => void
|
|
1600
|
+
goToPreviousMonth: () => void
|
|
1601
|
+
goToNextMonth: () => void
|
|
1602
|
+
goToMonth: (month: number) => void — 0-indexed month
|
|
1603
|
+
goToYear: (year: number) => void
|
|
1604
|
+
- Example:
|
|
1605
|
+
const { currentMonth, goToNextMonth, goToPreviousMonth, goToMonth, goToYear } = useCalendar()
|
|
1606
|
+
<CalendarGrid currentMonth={currentMonth} onMonthChange={setCurrentMonth} ... />
|
|
1607
|
+
- Gotchas: This is a convenience hook for managing calendar month state — used internally by DatePicker
|
|
1608
|
+
|
|
1484
1609
|
## EmptyState
|
|
1485
1610
|
- Import: @devalok/shilp-sutra/composed/empty-state
|
|
1486
1611
|
- Server-safe: Yes
|
|
@@ -1513,6 +1638,7 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
1513
1638
|
emptyState: ReactNode — empty state content
|
|
1514
1639
|
compact: boolean — tighter spacing, no avatars, smaller text
|
|
1515
1640
|
maxInitialItems: number — truncate with "Show all (N)" toggle
|
|
1641
|
+
- Type: ActivityItem = { id: string, actor?: { name: string, image?: string }, action: string | ReactNode, timestamp: Date | string, icon?: ReactNode, color?: 'default' | 'success' | 'warning' | 'error' | 'info', detail?: ReactNode }
|
|
1516
1642
|
- Example:
|
|
1517
1643
|
<ActivityFeed
|
|
1518
1644
|
items={[
|
|
@@ -1606,8 +1732,9 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
1606
1732
|
## PriorityIndicator
|
|
1607
1733
|
- Import: @devalok/shilp-sutra/composed/priority-indicator
|
|
1608
1734
|
- Server-safe: Yes
|
|
1735
|
+
- Type: Priority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT' | 'low' | 'medium' | 'high' | 'urgent'
|
|
1609
1736
|
- Props:
|
|
1610
|
-
priority:
|
|
1737
|
+
priority: Priority
|
|
1611
1738
|
display: "compact" | "full" (default: "full")
|
|
1612
1739
|
- Example:
|
|
1613
1740
|
<PriorityIndicator priority="HIGH" />
|
|
@@ -1710,6 +1837,42 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
1710
1837
|
<StatusBadge color="warning" label="In Review" size="sm" />
|
|
1711
1838
|
- Gotchas: When color is set, it takes priority over status for styling
|
|
1712
1839
|
|
|
1840
|
+
## UploadProgress
|
|
1841
|
+
- Import: @devalok/shilp-sutra/composed/upload-progress
|
|
1842
|
+
- Server-safe: No
|
|
1843
|
+
- Types:
|
|
1844
|
+
UploadFile: { id: string, name: string, size: number (bytes), progress?: number (0-100, undefined = indeterminate), status: 'pending' | 'uploading' | 'processing' | 'complete' | 'error', error?: string, previewUrl?: string }
|
|
1845
|
+
- Props:
|
|
1846
|
+
files: UploadFile[] (REQUIRED)
|
|
1847
|
+
onRemove: (fileId: string) => void — called when user cancels/removes a file
|
|
1848
|
+
onRetry: (fileId: string) => void — called when user retries a failed upload
|
|
1849
|
+
onDismissAll: () => void — "Dismiss all" button appears when all files are terminal (complete or error)
|
|
1850
|
+
variant: "default" | "compact" (default: "default") — default = two-line layout with progress bar; compact = single-line layout
|
|
1851
|
+
showSize: boolean (default: true) — show file size (default variant only)
|
|
1852
|
+
className: string
|
|
1853
|
+
- Also exported: formatFileSize(bytes: number) => string — utility to format bytes as human-readable (B, KB, MB, GB)
|
|
1854
|
+
- Defaults: variant="default", showSize=true
|
|
1855
|
+
- Example:
|
|
1856
|
+
<UploadProgress
|
|
1857
|
+
files={[
|
|
1858
|
+
{ id: '1', name: 'report.pdf', size: 1048576, status: 'uploading', progress: 45 },
|
|
1859
|
+
{ id: '2', name: 'photo.jpg', size: 204800, status: 'complete', previewUrl: '/thumb.jpg' },
|
|
1860
|
+
{ id: '3', name: 'data.csv', size: 51200, status: 'error', error: 'Network timeout' },
|
|
1861
|
+
]}
|
|
1862
|
+
onRemove={(id) => removeFile(id)}
|
|
1863
|
+
onRetry={(id) => retryUpload(id)}
|
|
1864
|
+
onDismissAll={() => clearAll()}
|
|
1865
|
+
/>
|
|
1866
|
+
<UploadProgress files={uploads} variant="compact" onRemove={removeFile} />
|
|
1867
|
+
- Gotchas:
|
|
1868
|
+
- Returns null when files array is empty
|
|
1869
|
+
- Summary header shows completion count and error count
|
|
1870
|
+
- Border color changes based on state: green when all complete, red tint when all terminal with errors
|
|
1871
|
+
- File icon auto-detects image files by extension or previewUrl presence
|
|
1872
|
+
- Status 'processing' renders a spinner icon and indeterminate progress
|
|
1873
|
+
- Screen reader announcements via aria-live region for completion/error events
|
|
1874
|
+
- Staggered slide-up animation (30ms delay per file)
|
|
1875
|
+
|
|
1713
1876
|
---
|
|
1714
1877
|
|
|
1715
1878
|
# SHELL COMPONENTS
|
|
@@ -1727,9 +1890,11 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
1727
1890
|
extraGroups: CommandGroup[]
|
|
1728
1891
|
onNavigate: (path: string) => void
|
|
1729
1892
|
onSearch: (query: string) => void
|
|
1730
|
-
searchResults: SearchResult[]
|
|
1893
|
+
searchResults: SearchResult[]
|
|
1731
1894
|
isSearching: boolean (shows loading state while search is in progress)
|
|
1732
1895
|
onSearchResultSelect: (result: SearchResult) => void
|
|
1896
|
+
- Type: SearchResult = { id: string, title: string, snippet?: string, entityType: string, projectId?: string | null, metadata?: Record<string, unknown> }
|
|
1897
|
+
- Type: AppCommandPaletteUser = { name: string, role?: string }
|
|
1733
1898
|
- Example:
|
|
1734
1899
|
<AppCommandPalette
|
|
1735
1900
|
user={{ name: 'John', role: 'admin' }}
|
|
@@ -1749,7 +1914,10 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
1749
1914
|
logo: ReactNode
|
|
1750
1915
|
footerLinks: Array<{ label: string, href: string }>
|
|
1751
1916
|
className: string
|
|
1752
|
-
- NavItem
|
|
1917
|
+
- Type: NavItem = { title: string, href: string, icon: ReactNode, exact?: boolean, badge?: string | number, children?: NavSubItem[], defaultOpen?: boolean }
|
|
1918
|
+
- Type: NavSubItem = { title: string, href: string, icon?: ReactNode, exact?: boolean }
|
|
1919
|
+
- Type: NavGroup = { label: string, items: NavItem[], action?: ReactNode }
|
|
1920
|
+
- Type: SidebarUser = { name: string, email?: string, image?: string | null, designation?: string, role?: string }
|
|
1753
1921
|
- Example:
|
|
1754
1922
|
<AppSidebar
|
|
1755
1923
|
currentPath="/dashboard"
|
|
@@ -1867,10 +2035,12 @@ Deprecated props:
|
|
|
1867
2035
|
- Server-safe: No
|
|
1868
2036
|
- Props:
|
|
1869
2037
|
currentPath: string
|
|
1870
|
-
user: BottomNavbarUser | null (optional)
|
|
1871
|
-
primaryItems: BottomNavItem[] (max 4 recommended)
|
|
2038
|
+
user: BottomNavbarUser | null (optional). Not required to render.
|
|
2039
|
+
primaryItems: BottomNavItem[] (max 4 recommended)
|
|
1872
2040
|
moreItems: BottomNavItem[] (overflow items in "More" menu)
|
|
1873
2041
|
className: string
|
|
2042
|
+
- Type: BottomNavItem = { title: string, href: string, icon: ReactNode, exact?: boolean, badge?: number }
|
|
2043
|
+
- Type: BottomNavbarUser = { name: string, role?: string }
|
|
1874
2044
|
- Example:
|
|
1875
2045
|
<BottomNavbar
|
|
1876
2046
|
currentPath="/dashboard"
|
|
@@ -1899,8 +2069,9 @@ Deprecated props:
|
|
|
1899
2069
|
- Import: @devalok/shilp-sutra/shell/notification-center
|
|
1900
2070
|
- Server-safe: No
|
|
1901
2071
|
- Props:
|
|
1902
|
-
notifications: Notification[]
|
|
1903
|
-
|
|
2072
|
+
notifications: Notification[]
|
|
2073
|
+
- Type: Notification = { id: string, title: string, body?: string | null, tier: 'INFO' | 'IMPORTANT' | 'CRITICAL', isRead: boolean, createdAt: string, entityType?: string | null, entityId?: string | null, projectId?: string | null, project?: { title: string } | null, actions?: NotificationAction[] }
|
|
2074
|
+
- Type: NotificationAction = { label: string, variant?: 'primary' | 'default' | 'danger', onClick: (id: string) => void }
|
|
1904
2075
|
unreadCount: number (derived from notifications if not provided)
|
|
1905
2076
|
open: boolean (controlled mode)
|
|
1906
2077
|
onOpenChange: (open: boolean) => void
|
|
@@ -1934,8 +2105,10 @@ Deprecated props:
|
|
|
1934
2105
|
- Import: @devalok/shilp-sutra/shell/notification-preferences
|
|
1935
2106
|
- Server-safe: No
|
|
1936
2107
|
- Props:
|
|
1937
|
-
preferences: NotificationPreference[]
|
|
1938
|
-
projects: NotificationProject[]
|
|
2108
|
+
preferences: NotificationPreference[]
|
|
2109
|
+
projects: NotificationProject[]
|
|
2110
|
+
- Type: NotificationPreference = { id: string, userId?: string, projectId: string | null, channel: string, minTier: string, muted: boolean }
|
|
2111
|
+
- Type: NotificationProject = { id: string, title: string }
|
|
1939
2112
|
isLoading: boolean
|
|
1940
2113
|
onSave: (preference: { projectId, channel, minTier, muted }) => void | Promise<void>
|
|
1941
2114
|
onToggleMute: (preference: NotificationPreference) => void | Promise<void>
|
|
@@ -1966,7 +2139,8 @@ Deprecated props:
|
|
|
1966
2139
|
notificationSlot: ReactNode (render NotificationCenter here)
|
|
1967
2140
|
userMenuItems?: UserMenuItem[] — custom items between Profile and Dark/Light Mode toggle
|
|
1968
2141
|
className: string
|
|
1969
|
-
-
|
|
2142
|
+
- Type: TopBarUser = { name: string, email?: string, image?: string | null }
|
|
2143
|
+
- Type: UserMenuItem = { label: string, icon?: ReactNode, href?: string, onClick?: () => void, separator?: boolean, color?: string, badge?: string | boolean, disabled?: boolean }
|
|
1970
2144
|
href — navigates via onNavigate callback
|
|
1971
2145
|
onClick — custom action (takes precedence over href)
|
|
1972
2146
|
separator — renders a DropdownMenuSeparator before this item
|
|
@@ -2047,3 +2221,10 @@ Deprecated props:
|
|
|
2047
2221
|
## motion / duration / easings / durations
|
|
2048
2222
|
- Import: @devalok/shilp-sutra (barrel export)
|
|
2049
2223
|
- Design system motion tokens for custom animations
|
|
2224
|
+
- Type: MotionMode = 'productive' | 'expressive'
|
|
2225
|
+
- Type: MotionCategory = 'standard' | 'entrance' | 'exit'
|
|
2226
|
+
- Type: DurationToken = 'instant' | 'fast-01' | 'fast-02' | 'moderate-01' | 'moderate-02' | 'slow-01' | 'slow-02'
|
|
2227
|
+
- Function: motion(category: MotionCategory, mode: MotionMode) => string — returns CSS cubic-bezier string
|
|
2228
|
+
- Function: duration(token: DurationToken) => string — returns CSS duration string (e.g. '150ms')
|
|
2229
|
+
- Object: easings — Record<MotionMode, Record<MotionCategory, string>> — all cubic-bezier values
|
|
2230
|
+
- Object: durations — Record<DurationToken, string> — { instant: '0ms', fast-01: '70ms', fast-02: '110ms', moderate-01: '150ms', moderate-02: '240ms', slow-01: '400ms', slow-02: '700ms' }
|
package/llms.txt
CHANGED
|
@@ -108,7 +108,7 @@ Components with two-axis system: Button, Badge, Alert, Chip, Toast, Banner, Prog
|
|
|
108
108
|
### Inputs & Controls
|
|
109
109
|
- Button: variant(solid|default|outline|ghost|link) color(default|error) size(sm|md|lg|icon) + loading, startIcon, endIcon, asChild
|
|
110
110
|
- IconButton: icon(ReactNode, required) shape(square|circle) size(sm|md|lg) + aria-label required
|
|
111
|
-
- Input: size(sm|md|lg) state(
|
|
111
|
+
- Input: size(sm|md|lg) state(InputState) + startIcon, endIcon. Type: InputState = 'default' | 'error' | 'warning' | 'success'
|
|
112
112
|
- SearchInput: size(sm|md|lg) + loading, onClear
|
|
113
113
|
- NumberInput: value + onValueChange, min, max, step (controlled only)
|
|
114
114
|
- Textarea: size(sm|md|lg) state(default|error|warning|success)
|
|
@@ -119,7 +119,7 @@ Components with two-axis system: Button, Badge, Alert, Chip, Toast, Banner, Prog
|
|
|
119
119
|
- Select > SelectTrigger(size) > SelectValue; SelectContent > SelectItem(value)
|
|
120
120
|
- Toggle: variant(default|outline) size(sm|md|lg)
|
|
121
121
|
- ToggleGroup > ToggleGroupItem (variant/size propagate from root)
|
|
122
|
-
- SegmentedControl > SegmentedControlItem: variant(filled|tonal) size(sm|md|lg)
|
|
122
|
+
- SegmentedControl > SegmentedControlItem: variant(filled|tonal) size(sm|md|lg). Types: SegmentedControlOption = { id, text, icon? }, SegmentedControlSize = 'sm' | 'md' | 'lg', SegmentedControlVariant = 'filled' | 'tonal'
|
|
123
123
|
- Slider: standard Radix slider
|
|
124
124
|
|
|
125
125
|
### Feedback & Notifications
|
|
@@ -137,10 +137,10 @@ NOTIFICATION SELECTION GUIDE:
|
|
|
137
137
|
### Data Display
|
|
138
138
|
- Badge: variant(subtle|solid|outline) color(default|info|success|error|warning|brand|accent + 7 category colors) size(xs|sm|md|lg) + onDismiss
|
|
139
139
|
- Chip: variant(subtle|outline) color(default|primary|success|error|warning|info + 7 category) size(sm|md|lg) label(string, REQUIRED) + onDismiss, onClick
|
|
140
|
-
- Avatar: size(xs|sm|md|lg|xl) shape(circle|square|rounded) status(
|
|
140
|
+
- Avatar: size(xs|sm|md|lg|xl) shape(circle|square|rounded) status(AvatarStatus) > AvatarImage + AvatarFallback. Type: AvatarStatus = 'online' | 'offline' | 'busy' | 'away'
|
|
141
141
|
- Card: variant(default|elevated|outline|flat) interactive(boolean) > CardHeader > CardTitle, CardDescription; CardContent; CardFooter
|
|
142
142
|
- Table > TableHeader > TableRow > TableHead; TableBody > TableRow > TableCell; TableFooter; TableCaption
|
|
143
|
-
- Text: variant(heading-2xl|heading-xl|heading-lg|heading-md|heading-sm|heading-xs|body-lg|body-md|body-sm|body-xs|label-lg|label-md|label-sm|label-xs|caption|overline
|
|
143
|
+
- Text: variant(TextVariant) as(element). Type: TextVariant = 'heading-2xl' | 'heading-xl' | 'heading-lg' | 'heading-md' | 'heading-sm' | 'heading-xs' | 'body-lg' | 'body-md' | 'body-sm' | 'body-xs' | 'label-lg' | 'label-md' | 'label-sm' | 'label-xs' | 'caption' | 'overline'
|
|
144
144
|
- Code: variant(inline|block)
|
|
145
145
|
- Skeleton: variant(rectangle|circle|text) animation(pulse|shimmer|none)
|
|
146
146
|
- StatCard: title, value, description, trend, icon
|
|
@@ -171,7 +171,7 @@ NOTIFICATION SELECTION GUIDE:
|
|
|
171
171
|
- Sidebar: complex — see llms-full.txt for complete tree
|
|
172
172
|
|
|
173
173
|
### Form Pattern
|
|
174
|
-
- FormField: state(
|
|
174
|
+
- FormField: state(FormHelperState) > Label + Input + FormHelperText. Type: FormHelperState = 'helper' | 'error' | 'warning' | 'success'
|
|
175
175
|
- useFormField() hook returns { state, helperTextId, required } from FormField context
|
|
176
176
|
- Wire accessibility: const { state, helperTextId } = useFormField(); then aria-describedby={helperTextId}, aria-invalid={state === 'error'}
|
|
177
177
|
- Input/Textarea auto-wire from FormField context (no manual hookup needed). Explicit props override.
|
|
@@ -183,18 +183,27 @@ NOTIFICATION SELECTION GUIDE:
|
|
|
183
183
|
- StatusBadge: DISCRIMINATED UNION — pass status OR color, not both. status(active|pending|approved|rejected|completed|blocked|cancelled|draft) color(success|warning|error|info|neutral) size(sm|md)
|
|
184
184
|
- ContentCard: variant(default|outline|ghost) padding(default|compact|spacious|none)
|
|
185
185
|
- EmptyState: icon(ReactNode or ComponentType), title(required), description, action(ReactNode), compact
|
|
186
|
-
- PriorityIndicator: priority(LOW|MEDIUM|HIGH|URGENT
|
|
186
|
+
- PriorityIndicator: priority(Priority) display(compact|full). Type: Priority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT' | 'low' | 'medium' | 'high' | 'urgent'
|
|
187
187
|
- SimpleTooltip: wraps Tooltip compound into single component
|
|
188
|
-
- DatePicker, DateRangePicker, DateTimePicker
|
|
188
|
+
- DatePicker, DateRangePicker, DateTimePicker
|
|
189
|
+
- TimePicker: standalone time selector — value(Date|null), onChange, format('12h'|'24h'), minuteStep, showSeconds, disabled
|
|
190
|
+
- CalendarGrid: low-level calendar widget — currentMonth, selected, rangeStart/End, onSelect, onMonthChange, events(CalendarEvent[])
|
|
191
|
+
- YearPicker: decade year grid — currentYear, selectedYear, onYearSelect, minDate, maxDate
|
|
192
|
+
- MonthPicker: month grid — currentYear, selectedMonth(0-11), onMonthSelect, minDate, maxDate
|
|
193
|
+
- Presets: date range quick-select buttons — presets(PresetKey[]), onSelect(start, end). Keys: today, yesterday, last7days, last30days, thisMonth, lastMonth, thisYear
|
|
194
|
+
- useCalendar: hook for calendar month state — returns currentMonth, goToPreviousMonth, goToNextMonth, goToMonth, goToYear
|
|
195
|
+
- UploadProgress: file upload tracker — files(UploadFile[]), onRemove, onRetry, onDismissAll, variant(default|compact), showSize. Status: pending|uploading|processing|complete|error. Also exports formatFileSize()
|
|
189
196
|
- RichTextEditor: Tiptap editor — bold/italic/underline/strike/highlight, headings, blockquote, lists (bullet/ordered/task), code, links, images (paste/drop/upload), file attachments, @mentions, emoji picker + :shortcode:, text alignment, HR. Props: onImageUpload?, onFileUpload?, mentions?, onMentionSearch?, onMentionSelect?
|
|
190
197
|
- RichTextViewer: read-only renderer for RichTextEditor HTML content (renders all above content types)
|
|
198
|
+
- ActivityFeed: items(ActivityItem[]), onLoadMore, loading, hasMore, emptyState, compact, maxInitialItems. Type: ActivityItem = { id, actor?, action, timestamp, icon?, color?, detail? }
|
|
191
199
|
- CommandPalette, MemberPicker
|
|
192
200
|
- ErrorDisplay, GlobalLoading
|
|
193
|
-
- Loading skeletons: CardSkeleton, TableSkeleton, BoardSkeleton, ListSkeleton
|
|
201
|
+
- Loading skeletons: CardSkeleton, TableSkeleton, BoardSkeleton, ListSkeleton
|
|
202
|
+
- Page skeletons: DashboardSkeleton, ProjectListSkeleton, TaskDetailSkeleton (no props, server-safe)
|
|
194
203
|
|
|
195
204
|
### Shell Components (app-level layout)
|
|
196
|
-
- TopBar: pageTitle, user, onNavigate, onLogout, notificationSlot, mobileLogo, userMenuItems?(UserMenuItem[]
|
|
197
|
-
- AppSidebar: navigation tree with NavItem[], NavGroup[]
|
|
205
|
+
- TopBar: pageTitle, user, onNavigate, onLogout, notificationSlot, mobileLogo, userMenuItems?(UserMenuItem[]). Types: TopBarUser = { name, email?, image? }, UserMenuItem = { label, icon?, href?, onClick?, separator?, color?, badge?, disabled? }
|
|
206
|
+
- AppSidebar: navigation tree with NavItem[], NavGroup[]. Types: NavItem = { title, href, icon, exact?, badge?, children?, defaultOpen? }, NavSubItem = { title, href, icon?, exact? }, NavGroup = { label, items, action? }, SidebarUser = { name, email?, image?, designation?, role? }
|
|
198
207
|
|
|
199
208
|
### AppSidebar (v0.10.0 additions)
|
|
200
209
|
- NavItem.children?: NavSubItem[] — collapsible sub-list with chevron toggle
|
|
@@ -206,14 +215,20 @@ NOTIFICATION SELECTION GUIDE:
|
|
|
206
215
|
- preFooterSlot?: ReactNode — content between navigation and footer
|
|
207
216
|
- renderItem?: (item, defaultRender) => ReactNode | null — custom item rendering
|
|
208
217
|
|
|
209
|
-
- BottomNavbar: mobile navigation, user is optional
|
|
210
|
-
- NotificationCenter: notifications[], onMarkRead, onMarkAllRead, onNavigate, getNotificationRoute
|
|
211
|
-
-
|
|
218
|
+
- BottomNavbar: mobile navigation, user is optional. Types: BottomNavItem = { title, href, icon, exact?, badge? }, BottomNavbarUser = { name, role? }
|
|
219
|
+
- NotificationCenter: notifications[], onMarkRead, onMarkAllRead, onNavigate, getNotificationRoute?, footerSlot?, emptyState?, headerActions?, popoverClassName?, onDismiss?(id). Types: Notification = { id, title, body?, tier, isRead, createdAt, entityType?, entityId?, projectId?, project?, actions? }, NotificationAction = { label, variant?, onClick }
|
|
220
|
+
- NotificationPreferences: preferences[], projects[], onSave, onToggleMute, onUpdateTier, onDelete. Types: NotificationPreference = { id, userId?, projectId, channel, minTier, muted }, NotificationProject = { id, title }
|
|
221
|
+
- AppCommandPalette: user, isAdmin, onNavigate, onSearch, searchResults, isSearching, onSearchResultSelect. Types: SearchResult = { id, title, snippet?, entityType, projectId?, metadata? }, AppCommandPaletteUser = { name, role? }
|
|
222
|
+
- LinkProvider: wraps app with router-agnostic Link component — component(ForwardRefComponent), children. useLink() hook returns the Link component.
|
|
223
|
+
|
|
224
|
+
### Motion Tokens
|
|
225
|
+
- motion(category, mode) => CSS cubic-bezier string. duration(token) => CSS duration string. easings: Record<MotionMode, Record<MotionCategory, string>>. durations: Record<DurationToken, string> = { instant: '0ms', fast-01: '70ms', fast-02: '110ms', moderate-01: '150ms', moderate-02: '240ms', slow-01: '400ms', slow-02: '700ms' }
|
|
212
226
|
|
|
213
227
|
### Hooks
|
|
214
|
-
- useToast(): returns { toast, toasts, dismiss } — toast({ title, description, color })
|
|
228
|
+
- useToast(): returns { toast, toasts, dismiss } — toast({ title, description, color }). Also: import { toast } from '@devalok/shilp-sutra/hooks/use-toast' for imperative usage without hook
|
|
215
229
|
- useColorMode(): returns { colorMode, setColorMode, toggleColorMode }
|
|
216
230
|
- useMobile(): returns boolean (true if viewport < 768px)
|
|
231
|
+
- useLink(): returns router-agnostic Link component from LinkProvider context (shell/link-context)
|
|
217
232
|
|
|
218
233
|
## Server-Safe Components (no "use client")
|
|
219
234
|
|