@devalok/shilp-sutra 0.23.3 → 0.25.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/dist/_chunks/framer.js +946 -672
- package/dist/_chunks/keybinding.js +19 -0
- package/dist/_chunks/stat-row.js +455 -0
- package/dist/_chunks/tiptap.js +1 -1
- package/dist/_chunks/vendor-client.js +1 -1
- package/dist/_chunks/vendor-utils.js +1311 -1168
- package/dist/ai/ai-command-provider.d.ts +23 -0
- package/dist/ai/ai-command-provider.d.ts.map +1 -0
- package/dist/ai/ai-command-provider.js +20 -0
- package/dist/ai/block-renderer.d.ts +12 -0
- package/dist/ai/block-renderer.d.ts.map +1 -0
- package/dist/ai/block-renderer.js +54 -0
- package/dist/ai/blocks/block-table.d.ts +6 -0
- package/dist/ai/blocks/block-table.d.ts.map +1 -0
- package/dist/ai/blocks/confirm.d.ts +6 -0
- package/dist/ai/blocks/confirm.d.ts.map +1 -0
- package/dist/ai/blocks/divider.d.ts +6 -0
- package/dist/ai/blocks/divider.d.ts.map +1 -0
- package/dist/ai/blocks/error.d.ts +6 -0
- package/dist/ai/blocks/error.d.ts.map +1 -0
- package/dist/ai/blocks/index.d.ts +11 -0
- package/dist/ai/blocks/index.d.ts.map +1 -0
- package/dist/ai/blocks/index.js +13 -0
- package/dist/ai/blocks/info.d.ts +8 -0
- package/dist/ai/blocks/info.d.ts.map +1 -0
- package/dist/ai/blocks/loading.d.ts +6 -0
- package/dist/ai/blocks/loading.d.ts.map +1 -0
- package/dist/ai/blocks/stat-row.d.ts +6 -0
- package/dist/ai/blocks/stat-row.d.ts.map +1 -0
- package/dist/ai/blocks/success.d.ts +6 -0
- package/dist/ai/blocks/success.d.ts.map +1 -0
- package/dist/ai/blocks/text.d.ts +8 -0
- package/dist/ai/blocks/text.d.ts.map +1 -0
- package/dist/ai/command-bar.d.ts +40 -0
- package/dist/ai/command-bar.d.ts.map +1 -0
- package/dist/ai/command-bar.js +545 -0
- package/dist/ai/conversation.d.ts +20 -0
- package/dist/ai/conversation.d.ts.map +1 -0
- package/dist/ai/conversation.js +255 -0
- package/dist/ai/devadoot-icon.d.ts +23 -0
- package/dist/ai/devadoot-icon.d.ts.map +1 -0
- package/dist/ai/index.d.ts +22 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +170 -0
- package/dist/ai/types.d.ts +81 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/composed/avatar-group.js +1 -1
- package/dist/composed/command-palette.d.ts +32 -2
- package/dist/composed/command-palette.d.ts.map +1 -1
- package/dist/composed/command-palette.js +176 -140
- package/dist/composed/content-card.js +1 -1
- package/dist/composed/index.d.ts +1 -1
- package/dist/composed/index.d.ts.map +1 -1
- package/dist/composed/priority-indicator.js +1 -1
- package/dist/composed/status-badge.js +1 -1
- package/dist/shell/app-command-palette.d.ts +36 -5
- package/dist/shell/app-command-palette.d.ts.map +1 -1
- package/dist/shell/app-command-palette.js +158 -137
- package/dist/shell/index.d.ts +1 -1
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/tailwind/index.cjs +1 -1
- package/dist/tailwind/preset.js +1 -1
- package/dist/ui/alert.js +1 -1
- package/dist/ui/avatar.js +1 -1
- package/dist/ui/badge.js +1 -1
- package/dist/ui/banner.js +4 -4
- package/dist/ui/button.js +7 -7
- package/dist/ui/card.js +7 -7
- package/dist/ui/chip.js +1 -1
- package/dist/ui/input.js +5 -5
- package/dist/ui/lib/keybinding.d.ts +8 -0
- package/dist/ui/lib/keybinding.d.ts.map +1 -0
- package/dist/ui/lib/motion.d.ts +4 -0
- package/dist/ui/lib/motion.d.ts.map +1 -1
- package/dist/ui/lib/motion.js +18 -14
- package/dist/ui/lib/utils.js +1 -1
- package/dist/ui/progress.js +1 -1
- package/dist/ui/segmented-control.js +1 -1
- package/dist/ui/select.js +1 -1
- package/dist/ui/sheet.js +6 -6
- package/dist/ui/sidebar.js +1 -1
- package/dist/ui/skeleton.js +4 -4
- package/dist/ui/tabs.js +1 -1
- package/dist/ui/text.js +1 -1
- package/dist/ui/textarea.js +1 -1
- package/dist/ui/toggle.js +1 -1
- package/llms-full.txt +1 -1
- package/llms.txt +45 -2
- package/package.json +733 -699
package/dist/ui/lib/motion.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const e = {
|
|
2
2
|
/** Micro-interactions: buttons, hover, form inputs */
|
|
3
3
|
snappy: { type: "spring", stiffness: 500, damping: 30, mass: 0.5 },
|
|
4
4
|
/** Dialogs, sheets, panels, navigation */
|
|
@@ -6,29 +6,33 @@ const s = {
|
|
|
6
6
|
/** Toasts, pop-ins, celebration feedback */
|
|
7
7
|
bouncy: { type: "spring", stiffness: 400, damping: 15, mass: 0.5 },
|
|
8
8
|
/** Collapse/expand, accordion, height changes */
|
|
9
|
-
gentle: { type: "spring", stiffness: 200, damping: 25, mass: 0.8 }
|
|
10
|
-
|
|
9
|
+
gentle: { type: "spring", stiffness: 200, damping: 25, mass: 0.8 },
|
|
10
|
+
/** AI response blocks — snappier than smooth, feels "intelligent" */
|
|
11
|
+
responsive: { type: "spring", stiffness: 350, damping: 28, mass: 0.6 }
|
|
12
|
+
}, n = {
|
|
11
13
|
/** Opacity enter/exit */
|
|
12
14
|
fade: { type: "tween", duration: 0.11, ease: "easeOut" },
|
|
13
15
|
/** Hover color, bg, border transitions */
|
|
14
|
-
colorShift: { type: "tween", duration: 0.07, ease: "easeOut" }
|
|
16
|
+
colorShift: { type: "tween", duration: 0.07, ease: "easeOut" },
|
|
17
|
+
/** Greeting fade, hint crossfade — unhurried, confident */
|
|
18
|
+
elegant: { type: "tween", duration: 0.4, ease: [0.25, 0.1, 0.25, 1] }
|
|
15
19
|
};
|
|
16
|
-
function
|
|
20
|
+
function t(s = 0.04) {
|
|
17
21
|
return {
|
|
18
|
-
visible: { transition: { staggerChildren:
|
|
19
|
-
hidden: { transition: { staggerChildren:
|
|
22
|
+
visible: { transition: { staggerChildren: s } },
|
|
23
|
+
hidden: { transition: { staggerChildren: s } }
|
|
20
24
|
};
|
|
21
25
|
}
|
|
22
|
-
function i(
|
|
23
|
-
return { ...
|
|
26
|
+
function i(s) {
|
|
27
|
+
return { ...s, duration: 0 };
|
|
24
28
|
}
|
|
25
|
-
function r(
|
|
26
|
-
return
|
|
29
|
+
function r(s) {
|
|
30
|
+
return s;
|
|
27
31
|
}
|
|
28
32
|
export {
|
|
29
33
|
r as motionProps,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
e as springs,
|
|
35
|
+
t as stagger,
|
|
36
|
+
n as tweens,
|
|
33
37
|
i as withReducedMotion
|
|
34
38
|
};
|
package/dist/ui/lib/utils.js
CHANGED
package/dist/ui/progress.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsxs as o, jsx as r } from "react/jsx-runtime";
|
|
3
3
|
import * as h from "react";
|
|
4
4
|
import { aQ as d, aR as l } from "../_chunks/primitives.js";
|
|
5
|
-
import {
|
|
5
|
+
import { ay as c } from "../_chunks/vendor-utils.js";
|
|
6
6
|
import { cn as a } from "./lib/utils.js";
|
|
7
7
|
import { springs as w } from "./lib/motion.js";
|
|
8
8
|
import { m as x } from "../_chunks/framer.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as d, jsxs as z } from "react/jsx-runtime";
|
|
3
3
|
import D, { useState as k, useRef as I, useEffect as S, useCallback as R, useId as E } from "react";
|
|
4
|
-
import {
|
|
4
|
+
import { ay as H } from "../_chunks/vendor-utils.js";
|
|
5
5
|
import { cn as w } from "./lib/utils.js";
|
|
6
6
|
import { springs as L } from "./lib/motion.js";
|
|
7
7
|
import { L as T, m as C, A } from "../_chunks/framer.js";
|
package/dist/ui/select.js
CHANGED
|
@@ -3,7 +3,7 @@ import { jsxs as l, jsx as e } from "react/jsx-runtime";
|
|
|
3
3
|
import * as o from "react";
|
|
4
4
|
import { ao as c, ap as w, aq as n, ar as m, as as x, at as p, au as N, av as f, aw as u, ax as v, ay as S, az as h, aA as I, aB as R, aC as C } from "../_chunks/primitives.js";
|
|
5
5
|
import { IconChevronDown as y, IconChevronUp as j, IconCheck as B } from "@tabler/icons-react";
|
|
6
|
-
import {
|
|
6
|
+
import { ay as V } from "../_chunks/vendor-utils.js";
|
|
7
7
|
import { cn as r } from "./lib/utils.js";
|
|
8
8
|
import { tweens as z, springs as T } from "./lib/motion.js";
|
|
9
9
|
import { m as D } from "../_chunks/framer.js";
|
package/dist/ui/sheet.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as r, jsxs as c } from "react/jsx-runtime";
|
|
3
3
|
import * as o from "react";
|
|
4
|
-
import { aa as h, ab as R, ac as u, ad as x, ae as
|
|
5
|
-
import {
|
|
4
|
+
import { aa as h, ab as R, ac as u, ad as x, ae as y, af as b, ag as P, ah as j } from "../_chunks/primitives.js";
|
|
5
|
+
import { ay as T } from "../_chunks/vendor-utils.js";
|
|
6
6
|
import { IconX as A } from "@tabler/icons-react";
|
|
7
7
|
import { cn as a } from "./lib/utils.js";
|
|
8
8
|
import { tweens as M, motionProps as g, springs as z } from "./lib/motion.js";
|
|
@@ -116,23 +116,23 @@ const U = o.forwardRef(
|
|
|
116
116
|
);
|
|
117
117
|
U.displayName = "SheetFooter";
|
|
118
118
|
const X = o.forwardRef(({ className: e, ...s }, t) => /* @__PURE__ */ r(
|
|
119
|
-
|
|
119
|
+
y,
|
|
120
120
|
{
|
|
121
121
|
ref: t,
|
|
122
122
|
className: a("text-ds-lg font-semibold text-surface-fg", e),
|
|
123
123
|
...s
|
|
124
124
|
}
|
|
125
125
|
));
|
|
126
|
-
X.displayName =
|
|
126
|
+
X.displayName = y.displayName;
|
|
127
127
|
const q = o.forwardRef(({ className: e, ...s }, t) => /* @__PURE__ */ r(
|
|
128
|
-
|
|
128
|
+
b,
|
|
129
129
|
{
|
|
130
130
|
ref: t,
|
|
131
131
|
className: a("text-ds-md text-surface-fg-muted", e),
|
|
132
132
|
...s
|
|
133
133
|
}
|
|
134
134
|
));
|
|
135
|
-
q.displayName =
|
|
135
|
+
q.displayName = b.displayName;
|
|
136
136
|
export {
|
|
137
137
|
F as Sheet,
|
|
138
138
|
Y as SheetClose,
|
package/dist/ui/sidebar.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as s, jsxs as h, Fragment as E } from "react/jsx-runtime";
|
|
3
3
|
import { S as v } from "../_chunks/primitives.js";
|
|
4
|
-
import {
|
|
4
|
+
import { ay as T } from "../_chunks/vendor-utils.js";
|
|
5
5
|
import { IconLayoutSidebarLeftCollapse as A } from "@tabler/icons-react";
|
|
6
6
|
import { useIsMobile as D } from "../hooks/use-mobile.js";
|
|
7
7
|
import { springs as O } from "./lib/motion.js";
|
package/dist/ui/skeleton.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as l, jsxs as f } from "react/jsx-runtime";
|
|
2
2
|
import * as o from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { ay as g } from "../_chunks/vendor-utils.js";
|
|
4
4
|
import { cn as r } from "./lib/utils.js";
|
|
5
|
-
const k =
|
|
5
|
+
const k = g("bg-skeleton-base", {
|
|
6
6
|
variants: {
|
|
7
7
|
variant: {
|
|
8
8
|
rectangle: "rounded-ds-md",
|
|
@@ -142,7 +142,7 @@ const I = {
|
|
|
142
142
|
)
|
|
143
143
|
);
|
|
144
144
|
A.displayName = "SkeletonInput";
|
|
145
|
-
const
|
|
145
|
+
const p = [65, 40, 85, 55, 70, 30, 90, 50, 75, 35, 80, 45, 60, 95, 38], B = o.forwardRef(
|
|
146
146
|
({ className: e, bars: s = 7, height: t = "h-40", animation: a = "pulse", ...n }, d) => {
|
|
147
147
|
const m = Math.max(1, s ?? 7);
|
|
148
148
|
return /* @__PURE__ */ l(
|
|
@@ -152,7 +152,7 @@ const g = [65, 40, 85, 55, 70, 30, 90, 50, 75, 35, 80, 45, 60, 95, 38], B = o.fo
|
|
|
152
152
|
className: r("flex items-end gap-ds-02", t, e),
|
|
153
153
|
...n,
|
|
154
154
|
children: Array.from({ length: m }).map((c, h) => {
|
|
155
|
-
const u =
|
|
155
|
+
const u = p[h % p.length];
|
|
156
156
|
return /* @__PURE__ */ l(
|
|
157
157
|
"div",
|
|
158
158
|
{
|
package/dist/ui/tabs.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as s, jsxs as N } from "react/jsx-runtime";
|
|
3
3
|
import { aS as h, aT as v, aU as b, aV as p } from "../_chunks/primitives.js";
|
|
4
4
|
import * as t from "react";
|
|
5
|
-
import {
|
|
5
|
+
import { ay as g } from "../_chunks/vendor-utils.js";
|
|
6
6
|
import { cn as u } from "./lib/utils.js";
|
|
7
7
|
import { springs as m, tweens as T } from "./lib/motion.js";
|
|
8
8
|
import { L as w, m as f } from "../_chunks/framer.js";
|
package/dist/ui/text.js
CHANGED
package/dist/ui/textarea.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as c } from "react/jsx-runtime";
|
|
3
3
|
import * as u from "react";
|
|
4
|
-
import {
|
|
4
|
+
import { ay as l } from "../_chunks/vendor-utils.js";
|
|
5
5
|
import { cn as f } from "./lib/utils.js";
|
|
6
6
|
import { motionProps as m } from "./lib/motion.js";
|
|
7
7
|
import { useFormField as b } from "./form.js";
|
package/dist/ui/toggle.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as i } from "react/jsx-runtime";
|
|
3
3
|
import * as n from "react";
|
|
4
4
|
import { aH as e } from "../_chunks/primitives.js";
|
|
5
|
-
import {
|
|
5
|
+
import { ay as d } from "../_chunks/vendor-utils.js";
|
|
6
6
|
import { springs as m, motionProps as c } from "./lib/motion.js";
|
|
7
7
|
import { cn as f } from "./lib/utils.js";
|
|
8
8
|
import { m as l } from "../_chunks/framer.js";
|
package/llms-full.txt
CHANGED
package/llms.txt
CHANGED
|
@@ -166,6 +166,45 @@ Same pattern for `border-surface-*`, `text-surface-*`, `ring-surface-*`.
|
|
|
166
166
|
|
|
167
167
|
**New hover states**: Checkbox, Radio, Switch track, Select items, DropdownMenu items, Combobox trigger.
|
|
168
168
|
|
|
169
|
+
## AI Command System (v0.25.0+)
|
|
170
|
+
|
|
171
|
+
New `@devalok/shilp-sutra/ai` module — composable AI command interface.
|
|
172
|
+
|
|
173
|
+
**CommandBar** — Unified input (hero/inline/floating variants):
|
|
174
|
+
```tsx
|
|
175
|
+
<CommandBar
|
|
176
|
+
variant="hero"
|
|
177
|
+
onSubmit={(query) => sendToAI(query)} // AI submission
|
|
178
|
+
groups={commandGroups} // optional command palette filtering
|
|
179
|
+
state="idle" // idle | typing | processing | responded
|
|
180
|
+
greeting="Good morning, Mudit."
|
|
181
|
+
hints={['Add member...', 'Check status...']}
|
|
182
|
+
agentName="Devadoot"
|
|
183
|
+
agentIcon={<DevadootIcon state={iconState} />}
|
|
184
|
+
>
|
|
185
|
+
<AIConversation messages={messages} isProcessing={loading} />
|
|
186
|
+
</CommandBar>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**BlockRenderer** — Renders AI response JSON as DS components:
|
|
190
|
+
```tsx
|
|
191
|
+
<BlockRenderer blocks={response.blocks} onAction={handleAction} customBlocks={myBlocks} />
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Block types: `text`, `table`, `confirm`, `success`, `error`, `info`, `loading`, `divider`, `stat_row`.
|
|
195
|
+
|
|
196
|
+
**AICommandProvider** — Optional context wrapper:
|
|
197
|
+
```tsx
|
|
198
|
+
<AICommandProvider customBlocks={karmBlocks} onAction={handle} agent={{ name: 'Devadoot' }}>
|
|
199
|
+
{/* CommandBar + AIConversation auto-wire from context */}
|
|
200
|
+
</AICommandProvider>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**DevadootIcon** — Animated Devalok chakra with gradient state animations:
|
|
204
|
+
```tsx
|
|
205
|
+
<DevadootIcon state="processing" size={20} /> // idle | processing | responded | error
|
|
206
|
+
```
|
|
207
|
+
|
|
169
208
|
## Install & Setup
|
|
170
209
|
|
|
171
210
|
pnpm add @devalok/shilp-sutra
|
|
@@ -185,6 +224,9 @@ import { Button } from '@devalok/shilp-sutra/ui/button'
|
|
|
185
224
|
import { PageHeader } from '@devalok/shilp-sutra/composed/page-header'
|
|
186
225
|
import { TopBar } from '@devalok/shilp-sutra/shell/top-bar'
|
|
187
226
|
|
|
227
|
+
// AI command system (v0.25.0+):
|
|
228
|
+
import { CommandBar, AIConversation, BlockRenderer, AICommandProvider, DevadootIcon } from '@devalok/shilp-sutra/ai'
|
|
229
|
+
|
|
188
230
|
// Toast (imperative, no hook needed):
|
|
189
231
|
import { toast } from '@devalok/shilp-sutra/ui/toast'
|
|
190
232
|
|
|
@@ -320,7 +362,8 @@ NOTIFICATION SELECTION GUIDE:
|
|
|
320
362
|
- 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?(item: MentionItem)
|
|
321
363
|
- RichTextViewer: read-only renderer for RichTextEditor HTML content (renders all above content types)
|
|
322
364
|
- ActivityFeed: items(ActivityItem[]), onLoadMore, loading, hasMore, emptyState, compact, maxInitialItems, groupBy?('time'|'none'), groupLabels?({ today, yesterday, thisWeek, older }). Type: ActivityItem = { id, actor?, action, timestamp, icon?, color?, detail? }. Utility: groupItemsByTime(items, labels) exported.
|
|
323
|
-
- CommandPalette,
|
|
365
|
+
- CommandPalette: open, defaultOpen, onOpenChange (controlled/uncontrolled), keybinding(string|string[]|false), maxHeight, emptyState(ReactNode), footerHints(FooterHint[]|false). CommandItem: label(string|ReactNode), description(string|ReactNode), renderLabel(query=>ReactNode), filterValue(string), shortcut(rendered as keycap badges). Keyboard shortcuts rendered per-key with platform-aware Cmd/Ctrl. Reduced-motion support via MotionProvider.
|
|
366
|
+
- MemberPicker
|
|
324
367
|
- ErrorDisplay, GlobalLoading
|
|
325
368
|
- Loading skeletons: CardSkeleton, TableSkeleton, BoardSkeleton, ListSkeleton
|
|
326
369
|
- Page skeletons: DashboardSkeleton, ProjectListSkeleton, TaskDetailSkeleton (no props, server-safe)
|
|
@@ -342,7 +385,7 @@ NOTIFICATION SELECTION GUIDE:
|
|
|
342
385
|
- BottomNavbar: mobile navigation, user is optional. Types: BottomNavItem = { title, href, icon, exact?, badge? }, BottomNavbarUser = { name, role? }
|
|
343
386
|
- 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 }
|
|
344
387
|
- NotificationPreferences: preferences[], projects[], onSave, onToggleMute, onUpdateTier, onDelete. Types: NotificationPreference = { id, userId?, projectId, channel, minTier, muted }, NotificationProject = { id, title }
|
|
345
|
-
- AppCommandPalette: user, isAdmin, onNavigate, onSearch, searchResults, isSearching, onSearchResultSelect. Types: SearchResult = { id, title, snippet?, entityType, projectId?, metadata? }, AppCommandPaletteUser = { name, role? }
|
|
388
|
+
- AppCommandPalette: user, isAdmin, onNavigate, onSearch, searchResults, searchResultGroups(SearchResultGroup[]), isSearching, onSearchResultSelect (when provided, consumer owns routing — no internal URL computation), searchResultsLabel(string|((count)=>string)), open, defaultOpen, onOpenChange, keybinding, maxHeight, emptyState, footerHints. Types: SearchResult = { id, title, snippet?, entityType, projectId?, metadata?, icon?(ReactNode), rank?(number), shortcut?(string) }, SearchResultGroup = { label, results: SearchResult[] }, AppCommandPaletteUser = { name, role? }
|
|
346
389
|
- LinkProvider: wraps app with router-agnostic Link component — component(ForwardRefComponent), children. useLink() hook returns the Link component.
|
|
347
390
|
|
|
348
391
|
### Motion System (Framer Motion)
|