@cascivo/mcp 0.1.4 → 0.1.6

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "0.0.0",
3
- "generatedAt": "2026-06-22",
3
+ "generatedAt": "2026-06-23",
4
4
  "components": [
5
5
  {
6
6
  "name": "accordion",
@@ -107,6 +107,147 @@
107
107
  }
108
108
  }
109
109
  },
110
+ {
111
+ "name": "action-sheet",
112
+ "type": "component",
113
+ "description": "Bottom-rising sheet of discrete actions (iOS action-sheet pattern) with a Cancel button",
114
+ "category": "overlay",
115
+ "version": "0.0.0",
116
+ "files": [
117
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/action-sheet/action-sheet.tsx",
118
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/action-sheet/action-sheet.module.css"
119
+ ],
120
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
121
+ "tags": ["overlay", "action-sheet", "menu", "mobile", "sheet"],
122
+ "meta": {
123
+ "name": "ActionSheet",
124
+ "description": "Bottom-rising sheet of discrete actions (iOS action-sheet pattern) with a Cancel button",
125
+ "category": "overlay",
126
+ "states": ["open", "closed"],
127
+ "variants": [],
128
+ "sizes": [],
129
+ "props": [
130
+ {
131
+ "name": "open",
132
+ "type": "boolean",
133
+ "required": false
134
+ },
135
+ {
136
+ "name": "defaultOpen",
137
+ "type": "boolean",
138
+ "required": false
139
+ },
140
+ {
141
+ "name": "onOpenChange",
142
+ "type": "(open: boolean) => void",
143
+ "required": false
144
+ },
145
+ {
146
+ "name": "actions",
147
+ "type": "ActionSheetAction[]",
148
+ "required": true,
149
+ "description": "Choices, each with a label, onSelect, and optional destructive/disabled flags"
150
+ },
151
+ {
152
+ "name": "title",
153
+ "type": "React.ReactNode",
154
+ "required": false
155
+ },
156
+ {
157
+ "name": "description",
158
+ "type": "React.ReactNode",
159
+ "required": false
160
+ },
161
+ {
162
+ "name": "showCancel",
163
+ "type": "boolean",
164
+ "required": false,
165
+ "default": "true"
166
+ },
167
+ {
168
+ "name": "labels",
169
+ "type": "{ cancel?: string; label?: string }",
170
+ "required": false
171
+ },
172
+ {
173
+ "name": "className",
174
+ "type": "string",
175
+ "required": false
176
+ }
177
+ ],
178
+ "tokens": [
179
+ "--cascivo-color-surface",
180
+ "--cascivo-color-border",
181
+ "--cascivo-color-accent",
182
+ "--cascivo-color-destructive",
183
+ "--cascivo-color-text",
184
+ "--cascivo-color-text-subtle",
185
+ "--cascivo-color-text-muted",
186
+ "--cascivo-radius-overlay",
187
+ "--cascivo-shadow-overlay",
188
+ "--cascivo-motion-enter",
189
+ "--cascivo-motion-exit",
190
+ "--cascivo-z-overlay"
191
+ ],
192
+ "accessibility": {
193
+ "role": "menu",
194
+ "wcag": "2.2-AA",
195
+ "keyboard": ["ArrowUp", "ArrowDown", "Home", "End", "Enter", "Space", "Escape"]
196
+ },
197
+ "examples": [],
198
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
199
+ "tags": ["overlay", "action-sheet", "menu", "mobile", "sheet"],
200
+ "intent": {
201
+ "whenToUse": [
202
+ "A short list of discrete actions on a touch surface, rising from the bottom",
203
+ "Confirming or choosing among a few operations (e.g. Share, Edit, Delete) on mobile",
204
+ "A mobile-first alternative to an anchored dropdown menu when there is no trigger anchor"
205
+ ],
206
+ "whenNotToUse": [
207
+ "A single yes/no confirmation — use AlertDialog",
208
+ "A form or scrollable content — use BottomSheet or Sheet",
209
+ "A menu anchored to a trigger on desktop — use Menu or Dropdown"
210
+ ],
211
+ "antiPatterns": [
212
+ {
213
+ "bad": "<ActionSheet actions={[{ label: \"OK\", onSelect }]} />",
214
+ "good": "<AlertDialog title=\"Delete item?\" />",
215
+ "why": "A one-action sheet is a confirmation; AlertDialog states the decision clearly"
216
+ }
217
+ ],
218
+ "related": [
219
+ {
220
+ "name": "BottomSheet",
221
+ "relationship": "alternative",
222
+ "reason": "Use BottomSheet for rich/resizable content; ActionSheet is a fixed list of actions"
223
+ },
224
+ {
225
+ "name": "Menu",
226
+ "relationship": "alternative",
227
+ "reason": "Use Menu for a trigger-anchored dropdown on pointer-first surfaces"
228
+ }
229
+ ],
230
+ "a11yRationale": "Renders role=\"menu\" with role=\"menuitem\" buttons under vertical roving focus (Arrow keys, Home/End, wrapping). The title labels the menu via aria-labelledby (or a built-in label otherwise) and the description via aria-describedby. FocusScope traps and restores focus; DismissableLayer handles Escape and outside-pointer dismissal; a separate Cancel button provides an explicit non-destructive exit.",
231
+ "flexibility": [
232
+ {
233
+ "area": "actions",
234
+ "level": "flexible",
235
+ "note": "Any number of actions; each may be destructive or disabled"
236
+ },
237
+ {
238
+ "area": "open state",
239
+ "level": "flexible",
240
+ "note": "Controlled (open/onOpenChange) or uncontrolled (defaultOpen)"
241
+ },
242
+ {
243
+ "area": "cancel",
244
+ "level": "flexible",
245
+ "note": "showCancel toggles the separate Cancel button (Escape/outside press still dismiss)"
246
+ }
247
+ ]
248
+ }
249
+ }
250
+ },
110
251
  {
111
252
  "name": "alert",
112
253
  "type": "component",
@@ -1018,6 +1159,159 @@
1018
1159
  }
1019
1160
  }
1020
1161
  },
1162
+ {
1163
+ "name": "bottom-sheet",
1164
+ "type": "component",
1165
+ "description": "Mobile bottom sheet with drag-to-resize detents, velocity-projected snapping, and drag-to-dismiss",
1166
+ "category": "overlay",
1167
+ "version": "0.0.0",
1168
+ "files": [
1169
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/bottom-sheet/bottom-sheet.tsx",
1170
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/bottom-sheet/bottom-sheet.module.css"
1171
+ ],
1172
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
1173
+ "tags": ["overlay", "sheet", "bottom-sheet", "mobile", "drag", "detent", "gesture"],
1174
+ "meta": {
1175
+ "name": "BottomSheet",
1176
+ "description": "Mobile bottom sheet with drag-to-resize detents, velocity-projected snapping, and drag-to-dismiss",
1177
+ "category": "overlay",
1178
+ "states": ["open", "closed", "dragging"],
1179
+ "variants": [],
1180
+ "sizes": [],
1181
+ "props": [
1182
+ {
1183
+ "name": "open",
1184
+ "type": "boolean",
1185
+ "required": false
1186
+ },
1187
+ {
1188
+ "name": "defaultOpen",
1189
+ "type": "boolean",
1190
+ "required": false
1191
+ },
1192
+ {
1193
+ "name": "onOpenChange",
1194
+ "type": "(open: boolean) => void",
1195
+ "required": false
1196
+ },
1197
+ {
1198
+ "name": "snapPoints",
1199
+ "type": "number[]",
1200
+ "required": false,
1201
+ "default": "[0.5, 0.92]",
1202
+ "description": "Detent heights as ascending fractions of the viewport (0–1)"
1203
+ },
1204
+ {
1205
+ "name": "activeSnap",
1206
+ "type": "number",
1207
+ "required": false
1208
+ },
1209
+ {
1210
+ "name": "defaultSnap",
1211
+ "type": "number",
1212
+ "required": false,
1213
+ "default": "0"
1214
+ },
1215
+ {
1216
+ "name": "onSnapChange",
1217
+ "type": "(index: number) => void",
1218
+ "required": false
1219
+ },
1220
+ {
1221
+ "name": "title",
1222
+ "type": "React.ReactNode",
1223
+ "required": false
1224
+ },
1225
+ {
1226
+ "name": "description",
1227
+ "type": "React.ReactNode",
1228
+ "required": false
1229
+ },
1230
+ {
1231
+ "name": "children",
1232
+ "type": "React.ReactNode",
1233
+ "required": false
1234
+ },
1235
+ {
1236
+ "name": "labels",
1237
+ "type": "{ close?: string; handle?: string }",
1238
+ "required": false
1239
+ },
1240
+ {
1241
+ "name": "className",
1242
+ "type": "string",
1243
+ "required": false
1244
+ }
1245
+ ],
1246
+ "tokens": [
1247
+ "--cascivo-color-surface",
1248
+ "--cascivo-color-border",
1249
+ "--cascivo-radius-overlay",
1250
+ "--cascivo-shadow-overlay",
1251
+ "--cascivo-motion-enter",
1252
+ "--cascivo-motion-exit",
1253
+ "--cascivo-target-min-coarse",
1254
+ "--cascivo-z-overlay"
1255
+ ],
1256
+ "accessibility": {
1257
+ "role": "dialog",
1258
+ "wcag": "2.2-AA",
1259
+ "keyboard": ["Escape", "Tab", "Shift+Tab"]
1260
+ },
1261
+ "examples": [],
1262
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
1263
+ "tags": ["overlay", "sheet", "bottom-sheet", "mobile", "drag", "detent", "gesture"],
1264
+ "intent": {
1265
+ "whenToUse": [
1266
+ "A mobile surface that rises from the bottom and can be resized between detents by dragging",
1267
+ "Showing secondary content, filters, or a form where the user can peek at half height then expand",
1268
+ "A touch-first overlay that dismisses by flinging or dragging it down past the lowest detent"
1269
+ ],
1270
+ "whenNotToUse": [
1271
+ "A short yes/no confirmation — use AlertDialog",
1272
+ "A non-resizable edge panel without gestures — use Drawer or Sheet",
1273
+ "A desktop-first side panel for navigation — use Drawer"
1274
+ ],
1275
+ "antiPatterns": [
1276
+ {
1277
+ "bad": "<BottomSheet title=\"Delete item?\">Are you sure?</BottomSheet>",
1278
+ "good": "<AlertDialog title=\"Delete item?\" />",
1279
+ "why": "A resizable gesture surface is overkill for a focused yes/no decision"
1280
+ }
1281
+ ],
1282
+ "related": [
1283
+ {
1284
+ "name": "Sheet",
1285
+ "relationship": "alternative",
1286
+ "reason": "Use Sheet for a fixed-height panel from any edge; BottomSheet adds resize detents"
1287
+ },
1288
+ {
1289
+ "name": "Drawer",
1290
+ "relationship": "alternative",
1291
+ "reason": "Use Drawer for a plain edge dialog without resize detents"
1292
+ }
1293
+ ],
1294
+ "a11yRationale": "Renders role=\"dialog\" with aria-modal; the title labels it via aria-labelledby and the description via aria-describedby. FocusScope traps Tab focus and restores it on close; DismissableLayer handles Escape and outside-pointer dismissal. The grab handle is a labelled separator and a Close button gives a non-gesture dismissal path so the sheet stays keyboard-operable.",
1295
+ "flexibility": [
1296
+ {
1297
+ "area": "snapPoints",
1298
+ "level": "flexible",
1299
+ "note": "Any ascending list of viewport fractions; the sheet snaps between them"
1300
+ },
1301
+ {
1302
+ "area": "open state",
1303
+ "level": "flexible",
1304
+ "note": "Controlled (open/onOpenChange) or uncontrolled (defaultOpen)"
1305
+ },
1306
+ {
1307
+ "area": "active detent",
1308
+ "level": "flexible",
1309
+ "note": "Controlled (activeSnap/onSnapChange) or uncontrolled (defaultSnap)"
1310
+ }
1311
+ ]
1312
+ }
1313
+ }
1314
+ },
1021
1315
  {
1022
1316
  "name": "breadcrumb",
1023
1317
  "type": "component",
@@ -4741,38 +5035,180 @@
4741
5035
  }
4742
5036
  },
4743
5037
  {
4744
- "name": "field",
5038
+ "name": "fab",
4745
5039
  "type": "component",
4746
- "description": "Form-field wrapper composing label, control, description, and error",
5040
+ "description": "Floating action button anchored to a screen corner, with an optional speed-dial of secondary actions",
4747
5041
  "category": "inputs",
4748
5042
  "version": "0.0.0",
4749
5043
  "files": [
4750
- "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/field/field.tsx",
4751
- "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/field/field.module.css"
5044
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/fab/fab.tsx",
5045
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/fab/fab.module.css"
4752
5046
  ],
4753
5047
  "dependencies": ["@cascivo/core"],
4754
- "tags": ["form", "layout", "validation", "accessibility"],
5048
+ "tags": ["inputs", "fab", "floating-action-button", "mobile", "speed-dial"],
4755
5049
  "meta": {
4756
- "name": "Field",
4757
- "description": "Form-field wrapper composing label, control, description, and error",
5050
+ "name": "Fab",
5051
+ "description": "Floating action button anchored to a screen corner, with an optional speed-dial of secondary actions",
4758
5052
  "category": "inputs",
4759
- "states": ["default", "disabled", "invalid"],
5053
+ "states": ["default", "open", "closed"],
4760
5054
  "variants": [],
4761
5055
  "sizes": [],
4762
5056
  "props": [
5057
+ {
5058
+ "name": "children",
5059
+ "type": "React.ReactNode",
5060
+ "required": true,
5061
+ "description": "The main icon"
5062
+ },
4763
5063
  {
4764
5064
  "name": "label",
4765
- "type": "ReactNode",
4766
- "required": false
5065
+ "type": "string",
5066
+ "required": true,
5067
+ "description": "Accessible name for the button"
4767
5068
  },
4768
5069
  {
4769
- "name": "description",
4770
- "type": "ReactNode",
5070
+ "name": "onClick",
5071
+ "type": "() => void",
4771
5072
  "required": false
4772
5073
  },
4773
5074
  {
4774
- "name": "error",
4775
- "type": "ReactNode",
5075
+ "name": "actions",
5076
+ "type": "FabAction[]",
5077
+ "required": false,
5078
+ "description": "Speed-dial actions; each has a label, icon, onSelect, and optional disabled"
5079
+ },
5080
+ {
5081
+ "name": "position",
5082
+ "type": "'bottom-end' | 'bottom-start'",
5083
+ "required": false,
5084
+ "default": "bottom-end"
5085
+ },
5086
+ {
5087
+ "name": "open",
5088
+ "type": "boolean",
5089
+ "required": false
5090
+ },
5091
+ {
5092
+ "name": "defaultOpen",
5093
+ "type": "boolean",
5094
+ "required": false
5095
+ },
5096
+ {
5097
+ "name": "onOpenChange",
5098
+ "type": "(open: boolean) => void",
5099
+ "required": false
5100
+ },
5101
+ {
5102
+ "name": "className",
5103
+ "type": "string",
5104
+ "required": false
5105
+ }
5106
+ ],
5107
+ "tokens": [
5108
+ "--cascivo-color-accent",
5109
+ "--cascivo-color-accent-content",
5110
+ "--cascivo-color-accent-hover",
5111
+ "--cascivo-color-surface",
5112
+ "--cascivo-color-border",
5113
+ "--cascivo-radius-full",
5114
+ "--cascivo-shadow-overlay",
5115
+ "--cascivo-target-min-coarse",
5116
+ "--cascivo-motion-enter",
5117
+ "--cascivo-motion-exit",
5118
+ "--cascivo-z-dropdown"
5119
+ ],
5120
+ "accessibility": {
5121
+ "role": "button",
5122
+ "wcag": "2.2-AA",
5123
+ "keyboard": ["Enter", "Space", "ArrowUp", "ArrowDown", "Home", "End", "Escape"]
5124
+ },
5125
+ "examples": [],
5126
+ "dependencies": ["@cascivo/core"],
5127
+ "tags": ["inputs", "fab", "floating-action-button", "mobile", "speed-dial"],
5128
+ "intent": {
5129
+ "whenToUse": [
5130
+ "A single, high-emphasis primary action that floats above scrolling content (e.g. Compose, Add)",
5131
+ "A small cluster of related create actions revealed from one corner via a speed-dial",
5132
+ "Touch-first screens where the primary action should stay reachable at the thumb"
5133
+ ],
5134
+ "whenNotToUse": [
5135
+ "Ordinary form or toolbar buttons — use Button or IconButton in the layout flow",
5136
+ "More than a handful of actions — use a Menu, Drawer, or full navigation",
5137
+ "Primary navigation between top-level destinations — use Dock"
5138
+ ],
5139
+ "antiPatterns": [
5140
+ {
5141
+ "bad": "<Fab label=\"Save\"><SaveIcon /></Fab> next to a form submit button",
5142
+ "good": "<Button type=\"submit\">Save</Button>",
5143
+ "why": "A floating button competes with the in-flow submit and hides the action off the form"
5144
+ }
5145
+ ],
5146
+ "related": [
5147
+ {
5148
+ "name": "IconButton",
5149
+ "relationship": "alternative",
5150
+ "reason": "Use IconButton for an in-flow icon control; Fab floats and is high-emphasis"
5151
+ },
5152
+ {
5153
+ "name": "Dock",
5154
+ "relationship": "alternative",
5155
+ "reason": "Use Dock for bottom navigation between destinations rather than a single action"
5156
+ }
5157
+ ],
5158
+ "a11yRationale": "The main button is icon-only and requires a `label` that becomes its aria-label. With a speed-dial it exposes aria-haspopup=\"menu\", aria-expanded, and aria-controls; the dial is a role=\"menu\" of role=\"menuitem\" buttons under vertical roving focus (Arrow keys, Home/End, wrapping). Opening moves focus to the first action and closing (Escape, outside press, or selection via DismissableLayer) returns focus to the button.",
5159
+ "flexibility": [
5160
+ {
5161
+ "area": "actions",
5162
+ "level": "flexible",
5163
+ "note": "Omit for a single-action button, or provide a speed-dial of secondary actions"
5164
+ },
5165
+ {
5166
+ "area": "position",
5167
+ "level": "strict",
5168
+ "note": "Anchored to bottom-end or bottom-start; honours safe-area insets"
5169
+ },
5170
+ {
5171
+ "area": "open state",
5172
+ "level": "flexible",
5173
+ "note": "Speed-dial is controlled (open/onOpenChange) or uncontrolled (defaultOpen)"
5174
+ }
5175
+ ]
5176
+ }
5177
+ }
5178
+ },
5179
+ {
5180
+ "name": "field",
5181
+ "type": "component",
5182
+ "description": "Form-field wrapper composing label, control, description, and error",
5183
+ "category": "inputs",
5184
+ "version": "0.0.0",
5185
+ "files": [
5186
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/field/field.tsx",
5187
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/field/field.module.css"
5188
+ ],
5189
+ "dependencies": ["@cascivo/core"],
5190
+ "tags": ["form", "layout", "validation", "accessibility"],
5191
+ "meta": {
5192
+ "name": "Field",
5193
+ "description": "Form-field wrapper composing label, control, description, and error",
5194
+ "category": "inputs",
5195
+ "states": ["default", "disabled", "invalid"],
5196
+ "variants": [],
5197
+ "sizes": [],
5198
+ "props": [
5199
+ {
5200
+ "name": "label",
5201
+ "type": "ReactNode",
5202
+ "required": false
5203
+ },
5204
+ {
5205
+ "name": "description",
5206
+ "type": "ReactNode",
5207
+ "required": false
5208
+ },
5209
+ {
5210
+ "name": "error",
5211
+ "type": "ReactNode",
4776
5212
  "required": false
4777
5213
  },
4778
5214
  {
@@ -9577,6 +10013,114 @@
9577
10013
  }
9578
10014
  }
9579
10015
  },
10016
+ {
10017
+ "name": "pull-to-refresh",
10018
+ "type": "component",
10019
+ "description": "Wraps a scrollable region and triggers a refresh when pulled down past a threshold at the top",
10020
+ "category": "feedback",
10021
+ "version": "0.0.0",
10022
+ "files": [
10023
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/pull-to-refresh/pull-to-refresh.tsx",
10024
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/pull-to-refresh/pull-to-refresh.module.css"
10025
+ ],
10026
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
10027
+ "tags": ["feedback", "pull-to-refresh", "mobile", "gesture", "scroll", "refresh"],
10028
+ "meta": {
10029
+ "name": "PullToRefresh",
10030
+ "description": "Wraps a scrollable region and triggers a refresh when pulled down past a threshold at the top",
10031
+ "category": "feedback",
10032
+ "states": ["idle", "pulling", "ready", "refreshing"],
10033
+ "variants": [],
10034
+ "sizes": [],
10035
+ "props": [
10036
+ {
10037
+ "name": "onRefresh",
10038
+ "type": "() => Promise<unknown> | unknown",
10039
+ "required": true,
10040
+ "description": "Called when the pull passes the threshold; the spinner shows until it settles"
10041
+ },
10042
+ {
10043
+ "name": "children",
10044
+ "type": "React.ReactNode",
10045
+ "required": true
10046
+ },
10047
+ {
10048
+ "name": "threshold",
10049
+ "type": "number",
10050
+ "required": false,
10051
+ "default": "64"
10052
+ },
10053
+ {
10054
+ "name": "disabled",
10055
+ "type": "boolean",
10056
+ "required": false
10057
+ },
10058
+ {
10059
+ "name": "labels",
10060
+ "type": "{ pull?: string; release?: string; refreshing?: string }",
10061
+ "required": false
10062
+ },
10063
+ {
10064
+ "name": "className",
10065
+ "type": "string",
10066
+ "required": false
10067
+ }
10068
+ ],
10069
+ "tokens": ["--cascivo-color-text-muted", "--cascivo-motion-enter"],
10070
+ "accessibility": {
10071
+ "role": "status",
10072
+ "wcag": "2.2-AA",
10073
+ "keyboard": []
10074
+ },
10075
+ "examples": [],
10076
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
10077
+ "tags": ["feedback", "pull-to-refresh", "mobile", "gesture", "scroll", "refresh"],
10078
+ "intent": {
10079
+ "whenToUse": [
10080
+ "A scrollable list or feed on touch devices that the user refreshes by pulling down from the top",
10081
+ "Mobile screens where a dedicated refresh button would be redundant or out of reach",
10082
+ "Content that updates on demand and benefits from a familiar pull gesture"
10083
+ ],
10084
+ "whenNotToUse": [
10085
+ "Desktop, pointer-first surfaces — provide an explicit Refresh button",
10086
+ "Content that auto-refreshes or paginates on scroll — use infinite scroll instead",
10087
+ "Regions that are not the primary scroll container of the screen"
10088
+ ],
10089
+ "antiPatterns": [
10090
+ {
10091
+ "bad": "Wrapping a non-scrolling element and relying on pull as the only refresh path",
10092
+ "good": "Wrap the scroll container and also expose a Refresh control for non-touch users",
10093
+ "why": "Pull-to-refresh is touch-only; keyboard and pointer users need an explicit control"
10094
+ }
10095
+ ],
10096
+ "related": [
10097
+ {
10098
+ "name": "Spinner",
10099
+ "relationship": "contains",
10100
+ "reason": "Shows the Spinner while the refresh promise settles"
10101
+ },
10102
+ {
10103
+ "name": "ScrollArea",
10104
+ "relationship": "pairs-with",
10105
+ "reason": "Wraps a scrollable region; pair with the app’s scroll container"
10106
+ }
10107
+ ],
10108
+ "a11yRationale": "The gesture is a touch-only enhancement: it arms only at scrollTop 0 and uses touch-action/overscroll containment so normal scrolling and keyboard use are unaffected. A polite aria-live status region announces the pull, release, and refreshing states (strings from the i18n catalog), and the Spinner exposes role=\"status\" while loading. Because pull-to-refresh cannot be performed without a pointer, apps should also offer an explicit refresh control for keyboard users.",
10109
+ "flexibility": [
10110
+ {
10111
+ "area": "threshold",
10112
+ "level": "flexible",
10113
+ "note": "Pull distance required to trigger is configurable (default 64px)"
10114
+ },
10115
+ {
10116
+ "area": "onRefresh",
10117
+ "level": "flexible",
10118
+ "note": "May return a promise; the spinner persists until it settles"
10119
+ }
10120
+ ]
10121
+ }
10122
+ }
10123
+ },
9580
10124
  {
9581
10125
  "name": "qr-code",
9582
10126
  "type": "component",
@@ -12659,36 +13203,42 @@
12659
13203
  }
12660
13204
  },
12661
13205
  {
12662
- "name": "switcher",
13206
+ "name": "swipe-item",
12663
13207
  "type": "component",
12664
- "description": "App/product switcher list lives inside HeaderPanel, renders links with active indicator and optional dividers",
12665
- "category": "navigation",
13208
+ "description": "List row whose leading/trailing actions are revealed by a horizontal swipe, with keyboard parity",
13209
+ "category": "display",
12666
13210
  "version": "0.0.0",
12667
13211
  "files": [
12668
- "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/switcher/switcher.tsx",
12669
- "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/switcher/switcher.module.css"
13212
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/swipe-item/swipe-item.tsx",
13213
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/swipe-item/swipe-item.module.css"
12670
13214
  ],
12671
- "dependencies": ["@cascivo/core", "@cascivo/i18n"],
12672
- "tags": ["navigation", "switcher", "shell", "console", "app-switcher"],
13215
+ "dependencies": ["@cascivo/core"],
13216
+ "tags": ["display", "swipe", "list", "mobile", "gesture", "actions"],
12673
13217
  "meta": {
12674
- "name": "Switcher",
12675
- "description": "App/product switcher list lives inside HeaderPanel, renders links with active indicator and optional dividers",
12676
- "category": "navigation",
12677
- "states": ["default"],
13218
+ "name": "SwipeItem",
13219
+ "description": "List row whose leading/trailing actions are revealed by a horizontal swipe, with keyboard parity",
13220
+ "category": "display",
13221
+ "states": ["closed", "leading", "trailing"],
12678
13222
  "variants": [],
12679
13223
  "sizes": [],
12680
13224
  "props": [
12681
13225
  {
12682
- "name": "items",
12683
- "type": "SwitcherEntry[]",
13226
+ "name": "children",
13227
+ "type": "React.ReactNode",
12684
13228
  "required": true,
12685
- "description": "SwitcherLink ({ label, href, active?, icon? }) or divider ({ divider: true })"
13229
+ "description": "The row content"
12686
13230
  },
12687
13231
  {
12688
- "name": "label",
12689
- "type": "string",
13232
+ "name": "leadingActions",
13233
+ "type": "SwipeAction[]",
12690
13234
  "required": false,
12691
- "default": "Switch application"
13235
+ "description": "Actions revealed by dragging toward the end edge (shown on the start edge)"
13236
+ },
13237
+ {
13238
+ "name": "trailingActions",
13239
+ "type": "SwipeAction[]",
13240
+ "required": false,
13241
+ "description": "Actions revealed by dragging toward the start edge (shown on the end edge)"
12692
13242
  },
12693
13243
  {
12694
13244
  "name": "className",
@@ -12697,57 +13247,158 @@
12697
13247
  }
12698
13248
  ],
12699
13249
  "tokens": [
12700
- "--cascivo-color-text",
12701
- "--cascivo-color-bg-subtle",
13250
+ "--cascivo-color-surface",
12702
13251
  "--cascivo-color-accent",
12703
- "--cascivo-color-accent-subtle",
12704
- "--cascivo-color-border",
12705
- "--cascivo-focus-ring"
13252
+ "--cascivo-color-accent-content",
13253
+ "--cascivo-color-destructive",
13254
+ "--cascivo-color-text-on-destructive",
13255
+ "--cascivo-target-min-coarse",
13256
+ "--cascivo-motion-enter"
12706
13257
  ],
12707
13258
  "accessibility": {
12708
- "role": "list",
13259
+ "role": "group",
12709
13260
  "wcag": "2.2-AA",
12710
- "keyboard": ["Tab", "Enter"]
13261
+ "keyboard": ["Tab", "Enter", "Space", "Escape"]
12711
13262
  },
12712
- "examples": [
12713
- {
12714
- "title": "App switcher",
12715
- "code": "<Switcher\n items={[\n { label: 'Console', href: '/console', active: true },\n { label: 'Billing', href: '/billing' },\n { divider: true },\n { label: 'Docs', href: 'https://docs.example.com' },\n ]}\n/>",
12716
- "description": "Place inside a HeaderPanel opened by a Grid action in ShellHeader"
12717
- }
12718
- ],
12719
- "dependencies": ["@cascivo/core", "@cascivo/i18n"],
12720
- "tags": ["navigation", "switcher", "shell", "console", "app-switcher"],
13263
+ "examples": [],
13264
+ "dependencies": ["@cascivo/core"],
13265
+ "tags": ["display", "swipe", "list", "mobile", "gesture", "actions"],
12721
13266
  "intent": {
12722
13267
  "whenToUse": [
12723
- "Listing sibling apps/products the user can switch between",
12724
- "Rendering switch destinations inside a HeaderPanel opened from the shell header",
12725
- "Grouping switch targets with dividers and marking the active one"
13268
+ "List rows on touch surfaces where secondary actions (archive, delete) should hide until swiped",
13269
+ "Mail/inbox-style rows that reveal contextual actions behind the content",
13270
+ "Compact lists where always-visible action buttons would crowd each row"
12726
13271
  ],
12727
13272
  "whenNotToUse": [
12728
- "Primary in-app navigationuse SideNav",
12729
- "A small action menu attached to a control use Dropdown"
13273
+ "A single primary action per row render it inline as a Button",
13274
+ "Destructive actions that need confirmation pair with an AlertDialog instead of swipe-only",
13275
+ "Non-list, free-form content — swipe-to-reveal is a list-row affordance"
12730
13276
  ],
12731
13277
  "antiPatterns": [
12732
13278
  {
12733
- "bad": "Using Switcher as the main page navigation",
12734
- "good": "<SideNav> for primary navigation; Switcher only for app/product switching",
12735
- "why": "Switcher models cross-app jumps, not navigation within the current app"
13279
+ "bad": "Relying on the swipe gesture as the only way to reach Delete",
13280
+ "good": "Action buttons stay in the DOM and a11y tree; focusing one reveals its side",
13281
+ "why": "Gesture-only actions are unreachable by keyboard and screen-reader users"
12736
13282
  }
12737
13283
  ],
12738
13284
  "related": [
12739
13285
  {
12740
- "name": "HeaderPanel",
13286
+ "name": "ActionSheet",
13287
+ "relationship": "alternative",
13288
+ "reason": "Use an ActionSheet when a row tap should present a fuller list of actions"
13289
+ },
13290
+ {
13291
+ "name": "List",
12741
13292
  "relationship": "contained-by",
12742
- "reason": "Switcher is placed inside a HeaderPanel opened by a ShellHeader action"
13293
+ "reason": "SwipeItem wraps individual rows within a list"
12743
13294
  }
12744
13295
  ],
12745
- "a11yRationale": "role=\"list\" structures the entries; each switch target is a real link with the active destination marked, so keyboard and screen-reader users can identify and reach the current app",
13296
+ "a11yRationale": "The action buttons are always rendered in the DOM and the accessibility tree, never gesture-only. Focusing an action (via keyboard) reveals its side so it is visible, Enter/Space activate it, and Escape closes the row giving full keyboard and screen-reader parity with the swipe gesture. The drag uses touch-action: pan-y so vertical scrolling is unaffected.",
12746
13297
  "flexibility": [
12747
13298
  {
12748
- "area": "dividers",
13299
+ "area": "actions",
12749
13300
  "level": "flexible",
12750
- "note": "Dividers group entries as needed"
13301
+ "note": "Any number of leading and/or trailing actions; each may be destructive"
13302
+ },
13303
+ {
13304
+ "area": "reveal direction",
13305
+ "level": "strict",
13306
+ "note": "Leading reveals on the start edge, trailing on the end edge (physical-axis drag)"
13307
+ }
13308
+ ]
13309
+ }
13310
+ }
13311
+ },
13312
+ {
13313
+ "name": "switcher",
13314
+ "type": "component",
13315
+ "description": "App/product switcher list — lives inside HeaderPanel, renders links with active indicator and optional dividers",
13316
+ "category": "navigation",
13317
+ "version": "0.0.0",
13318
+ "files": [
13319
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/switcher/switcher.tsx",
13320
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/components/src/switcher/switcher.module.css"
13321
+ ],
13322
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
13323
+ "tags": ["navigation", "switcher", "shell", "console", "app-switcher"],
13324
+ "meta": {
13325
+ "name": "Switcher",
13326
+ "description": "App/product switcher list — lives inside HeaderPanel, renders links with active indicator and optional dividers",
13327
+ "category": "navigation",
13328
+ "states": ["default"],
13329
+ "variants": [],
13330
+ "sizes": [],
13331
+ "props": [
13332
+ {
13333
+ "name": "items",
13334
+ "type": "SwitcherEntry[]",
13335
+ "required": true,
13336
+ "description": "SwitcherLink ({ label, href, active?, icon? }) or divider ({ divider: true })"
13337
+ },
13338
+ {
13339
+ "name": "label",
13340
+ "type": "string",
13341
+ "required": false,
13342
+ "default": "Switch application"
13343
+ },
13344
+ {
13345
+ "name": "className",
13346
+ "type": "string",
13347
+ "required": false
13348
+ }
13349
+ ],
13350
+ "tokens": [
13351
+ "--cascivo-color-text",
13352
+ "--cascivo-color-bg-subtle",
13353
+ "--cascivo-color-accent",
13354
+ "--cascivo-color-accent-subtle",
13355
+ "--cascivo-color-border",
13356
+ "--cascivo-focus-ring"
13357
+ ],
13358
+ "accessibility": {
13359
+ "role": "list",
13360
+ "wcag": "2.2-AA",
13361
+ "keyboard": ["Tab", "Enter"]
13362
+ },
13363
+ "examples": [
13364
+ {
13365
+ "title": "App switcher",
13366
+ "code": "<Switcher\n items={[\n { label: 'Console', href: '/console', active: true },\n { label: 'Billing', href: '/billing' },\n { divider: true },\n { label: 'Docs', href: 'https://docs.example.com' },\n ]}\n/>",
13367
+ "description": "Place inside a HeaderPanel opened by a Grid action in ShellHeader"
13368
+ }
13369
+ ],
13370
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
13371
+ "tags": ["navigation", "switcher", "shell", "console", "app-switcher"],
13372
+ "intent": {
13373
+ "whenToUse": [
13374
+ "Listing sibling apps/products the user can switch between",
13375
+ "Rendering switch destinations inside a HeaderPanel opened from the shell header",
13376
+ "Grouping switch targets with dividers and marking the active one"
13377
+ ],
13378
+ "whenNotToUse": [
13379
+ "Primary in-app navigation — use SideNav",
13380
+ "A small action menu attached to a control — use Dropdown"
13381
+ ],
13382
+ "antiPatterns": [
13383
+ {
13384
+ "bad": "Using Switcher as the main page navigation",
13385
+ "good": "<SideNav> for primary navigation; Switcher only for app/product switching",
13386
+ "why": "Switcher models cross-app jumps, not navigation within the current app"
13387
+ }
13388
+ ],
13389
+ "related": [
13390
+ {
13391
+ "name": "HeaderPanel",
13392
+ "relationship": "contained-by",
13393
+ "reason": "Switcher is placed inside a HeaderPanel opened by a ShellHeader action"
13394
+ }
13395
+ ],
13396
+ "a11yRationale": "role=\"list\" structures the entries; each switch target is a real link with the active destination marked, so keyboard and screen-reader users can identify and reach the current app",
13397
+ "flexibility": [
13398
+ {
13399
+ "area": "dividers",
13400
+ "level": "flexible",
13401
+ "note": "Dividers group entries as needed"
12751
13402
  },
12752
13403
  {
12753
13404
  "area": "token names",
@@ -18583,135 +19234,408 @@
18583
19234
  "install": "@cascivo/charts"
18584
19235
  },
18585
19236
  {
18586
- "name": "section/cta",
18587
- "type": "section",
18588
- "description": "Call-to-action bandquiet hairline-bordered section with title, description, and centered actions. Replace demo content before shipping.",
18589
- "category": "layout",
19237
+ "name": "editor/code-editor",
19238
+ "type": "editor",
19239
+ "description": "Lightweight code editor a native textarea overlaid on a syntax-highlighted layer, with line numbers and Tab indent.",
19240
+ "category": "inputs",
18590
19241
  "version": "0.0.0",
18591
- "files": [
18592
- "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/layouts/src/sections/cta/cta.tsx",
18593
- "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/layouts/src/sections/cta/cta.module.css"
18594
- ],
18595
- "dependencies": ["@cascivo/core"],
18596
- "tags": ["section", "cta", "marketing"],
19242
+ "files": [],
19243
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
19244
+ "tags": ["editor", "code", "syntax-highlighting", "textarea", "inputs"],
18597
19245
  "meta": {
18598
- "name": "Cta",
18599
- "description": "Call-to-action bandquiet hairline-bordered section with title, description, and centered actions. Replace demo content before shipping.",
18600
- "category": "layout",
18601
- "states": [],
19246
+ "name": "CodeEditor",
19247
+ "description": "Lightweight code editor a native textarea overlaid on a syntax-highlighted layer, with line numbers and Tab indent.",
19248
+ "category": "inputs",
19249
+ "states": ["default"],
18602
19250
  "variants": [],
18603
19251
  "sizes": [],
18604
19252
  "props": [
18605
19253
  {
18606
- "name": "title",
18607
- "type": "ReactNode",
18608
- "required": true,
18609
- "description": "Primary heading of the CTA band"
19254
+ "name": "value",
19255
+ "type": "string",
19256
+ "required": false,
19257
+ "description": "Controlled value"
18610
19258
  },
18611
19259
  {
18612
- "name": "description",
18613
- "type": "ReactNode",
19260
+ "name": "defaultValue",
19261
+ "type": "string",
18614
19262
  "required": false,
18615
- "description": "Supporting text below the title"
19263
+ "description": "Initial value for uncontrolled use"
18616
19264
  },
18617
19265
  {
18618
- "name": "actions",
18619
- "type": "ReactNode",
19266
+ "name": "onValueChange",
19267
+ "type": "(value: string) => void",
18620
19268
  "required": false,
18621
- "description": "Buttons or links centered below the description"
19269
+ "description": "Called with the new text on every edit"
18622
19270
  },
18623
19271
  {
18624
- "name": "headingLevel",
18625
- "type": "1 | 2 | 3",
19272
+ "name": "language",
19273
+ "type": "string",
19274
+ "required": false,
19275
+ "default": "plaintext",
19276
+ "description": "Grammar name (plaintext/json/javascript/typescript/css/html/markdown/bash)"
19277
+ },
19278
+ {
19279
+ "name": "lineNumbers",
19280
+ "type": "boolean",
19281
+ "required": false,
19282
+ "default": "true",
19283
+ "description": "Show the line-number gutter"
19284
+ },
19285
+ {
19286
+ "name": "tabSize",
19287
+ "type": "number",
18626
19288
  "required": false,
18627
19289
  "default": "2",
18628
- "description": "HTML heading level for document outline control"
19290
+ "description": "Spaces per tab stop"
19291
+ },
19292
+ {
19293
+ "name": "insertSpaces",
19294
+ "type": "boolean",
19295
+ "required": false,
19296
+ "default": "true",
19297
+ "description": "Insert spaces vs a literal tab on Tab"
19298
+ },
19299
+ {
19300
+ "name": "wrap",
19301
+ "type": "boolean",
19302
+ "required": false,
19303
+ "default": "false",
19304
+ "description": "Soft-wrap long lines instead of scrolling horizontally"
19305
+ },
19306
+ {
19307
+ "name": "readOnly",
19308
+ "type": "boolean",
19309
+ "required": false,
19310
+ "default": "false"
19311
+ },
19312
+ {
19313
+ "name": "disabled",
19314
+ "type": "boolean",
19315
+ "required": false,
19316
+ "default": "false"
19317
+ },
19318
+ {
19319
+ "name": "placeholder",
19320
+ "type": "string",
19321
+ "required": false
19322
+ },
19323
+ {
19324
+ "name": "label",
19325
+ "type": "string",
19326
+ "required": false,
19327
+ "description": "Accessible label (defaults to the i18n \"Code editor\")"
19328
+ },
19329
+ {
19330
+ "name": "className",
19331
+ "type": "string",
19332
+ "required": false
18629
19333
  }
18630
19334
  ],
18631
19335
  "tokens": [
18632
- "--cascivo-color-border",
18633
- "--cascivo-surface-subtle",
18634
- "--cascivo-text-2xl",
18635
- "--cascivo-text-base",
18636
- "--cascivo-font-bold",
18637
- "--cascivo-text-secondary",
18638
- "--cascivo-space-*"
19336
+ "--cascivo-editor-bg",
19337
+ "--cascivo-editor-fg",
19338
+ "--cascivo-editor-gutter-bg",
19339
+ "--cascivo-editor-gutter-fg",
19340
+ "--cascivo-editor-current-line",
19341
+ "--cascivo-editor-selection",
19342
+ "--cascivo-editor-border"
18639
19343
  ],
18640
19344
  "accessibility": {
18641
- "role": "region",
19345
+ "role": "textbox",
18642
19346
  "wcag": "2.1-AA",
18643
- "keyboard": []
19347
+ "keyboard": ["Tab (indent)", "Shift+Tab (dedent)", "Standard textarea editing"],
19348
+ "reducedMotion": true,
19349
+ "forcedColors": true
18644
19350
  },
18645
19351
  "examples": [
18646
19352
  {
18647
- "title": "CTA band",
18648
- "code": "<Cta title=\"Ready to ship?\" description=\"Add Cascade to your project in minutes.\" actions={<><Button>Get started</Button><Button variant=\"ghost\">View on GitHub</Button></>} />",
18649
- "description": "Quiet bordered band with centered heading, description, and action buttons"
19353
+ "title": "Basic editor",
19354
+ "code": "import { CodeEditor } from '@cascivo/editor'\nimport '@cascivo/editor/styles.css'\n\n<CodeEditor language=\"typescript\" lineNumbers defaultValue={'const x = 1\\n'} />"
19355
+ },
19356
+ {
19357
+ "title": "Controlled",
19358
+ "code": "<CodeEditor language=\"json\" value={value} onValueChange={setValue} />"
18650
19359
  }
18651
19360
  ],
18652
- "dependencies": ["@cascivo/core"],
18653
- "tags": ["section", "cta", "marketing"],
19361
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
19362
+ "tags": ["editor", "code", "syntax-highlighting", "textarea", "inputs"],
18654
19363
  "intent": {
18655
19364
  "whenToUse": [
18656
- "A call-to-action band with title, description, and centered actions",
18657
- "Prompting conversion between or after marketing sections"
19365
+ "Editing code or config inline — JSON, snippets, web languages — with line numbers and syntax colors",
19366
+ "A lightweight, themeable code field where a full IDE editor (Monaco/CodeMirror) would be overkill"
18658
19367
  ],
18659
19368
  "whenNotToUse": [
18660
- "The primary page intro — use Hero",
18661
- "General content grouping — use Section"
19369
+ "You need IntelliSense/LSP, multi-cursor, folding, a minimap, or diff view — use a full editor framework",
19370
+ "Plain prose or a single-line value — use Textarea or Input"
19371
+ ],
19372
+ "antiPatterns": [
19373
+ {
19374
+ "bad": "Reaching for Monaco to show an editable snippet",
19375
+ "good": "Use CodeEditor for the basic set (line numbers + highlighting) at a fraction of the weight",
19376
+ "why": "The overlay technique keeps the bundle tiny and themes via the cascivo token system"
19377
+ }
18662
19378
  ],
18663
- "antiPatterns": [],
18664
19379
  "related": [
18665
19380
  {
18666
- "name": "Hero",
19381
+ "name": "Highlight",
18667
19382
  "relationship": "pairs-with",
18668
- "reason": "Hero opens the page; CTA reinforces conversion later"
19383
+ "reason": "The read-only renderer sharing the same tokenizer for snippets and docs"
18669
19384
  },
18670
19385
  {
18671
- "name": "Section",
19386
+ "name": "Textarea",
18672
19387
  "relationship": "alternative",
18673
- "reason": "Use the plain section for non-CTA content"
19388
+ "reason": "Use for free-form prose without syntax highlighting"
18674
19389
  }
18675
19390
  ],
18676
- "a11yRationale": "Renders a section with a heading and clearly labeled action controls.",
18677
- "flexibility": []
19391
+ "a11yRationale": "The native <textarea> is the editing surface, so caret, selection, IME, undo, and the a11y tree come from the browser; the highlight layer and gutter are aria-hidden.",
19392
+ "flexibility": [
19393
+ {
19394
+ "area": "languages",
19395
+ "level": "flexible",
19396
+ "note": "Ships a small grammar set; registerGrammar adds custom languages without bundle bloat"
19397
+ }
19398
+ ]
18678
19399
  }
18679
- }
19400
+ },
19401
+ "install": "@cascivo/editor"
18680
19402
  },
18681
19403
  {
18682
- "name": "section/feature-grid",
18683
- "type": "section",
18684
- "description": "Feature sectionAutoGrid of items with optional title, description, and icon slots. Icons are optional; the grid works text-only. Replace demo content before shipping.",
18685
- "category": "layout",
19404
+ "name": "editor/highlight",
19405
+ "type": "editor",
19406
+ "description": "Read-only syntax-highlighted code block the same owned tokenizer as CodeEditor, without the textarea.",
19407
+ "category": "display",
18686
19408
  "version": "0.0.0",
18687
- "files": [
18688
- "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/layouts/src/sections/feature-grid/feature-grid.tsx",
18689
- "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/layouts/src/sections/feature-grid/feature-grid.module.css"
18690
- ],
18691
- "dependencies": ["@cascivo/core"],
18692
- "tags": ["section", "features", "grid"],
19409
+ "files": [],
19410
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
19411
+ "tags": ["editor", "code", "syntax-highlighting", "display", "read-only"],
18693
19412
  "meta": {
18694
- "name": "FeatureGrid",
18695
- "description": "Feature sectionAutoGrid of items with optional title, description, and icon slots. Icons are optional; the grid works text-only. Replace demo content before shipping.",
18696
- "category": "layout",
19413
+ "name": "Highlight",
19414
+ "description": "Read-only syntax-highlighted code block the same owned tokenizer as CodeEditor, without the textarea.",
19415
+ "category": "display",
18697
19416
  "states": [],
18698
19417
  "variants": [],
18699
19418
  "sizes": [],
18700
19419
  "props": [
18701
19420
  {
18702
- "name": "items",
18703
- "type": "FeatureItem[]",
19421
+ "name": "value",
19422
+ "type": "string",
18704
19423
  "required": true,
18705
- "description": "Array of feature items with title, optional description, icon, and href"
19424
+ "description": "Code to render"
18706
19425
  },
18707
19426
  {
18708
- "name": "title",
18709
- "type": "ReactNode",
19427
+ "name": "language",
19428
+ "type": "string",
18710
19429
  "required": false,
18711
- "description": "Section heading above the grid"
19430
+ "default": "plaintext",
19431
+ "description": "Grammar name (plaintext/json/javascript/typescript/css/html/markdown/bash)"
18712
19432
  },
18713
19433
  {
18714
- "name": "description",
19434
+ "name": "lineNumbers",
19435
+ "type": "boolean",
19436
+ "required": false,
19437
+ "default": "false",
19438
+ "description": "Show the line-number gutter"
19439
+ },
19440
+ {
19441
+ "name": "wrap",
19442
+ "type": "boolean",
19443
+ "required": false,
19444
+ "default": "false",
19445
+ "description": "Soft-wrap long lines"
19446
+ },
19447
+ {
19448
+ "name": "tabSize",
19449
+ "type": "number",
19450
+ "required": false,
19451
+ "default": "2",
19452
+ "description": "Spaces per tab stop"
19453
+ },
19454
+ {
19455
+ "name": "label",
19456
+ "type": "string",
19457
+ "required": false,
19458
+ "description": "Accessible label for the code block"
19459
+ },
19460
+ {
19461
+ "name": "className",
19462
+ "type": "string",
19463
+ "required": false
19464
+ }
19465
+ ],
19466
+ "tokens": [
19467
+ "--cascivo-editor-bg",
19468
+ "--cascivo-editor-fg",
19469
+ "--cascivo-editor-gutter-bg",
19470
+ "--cascivo-editor-gutter-fg",
19471
+ "--cascivo-editor-border"
19472
+ ],
19473
+ "accessibility": {
19474
+ "role": "group",
19475
+ "wcag": "2.1-AA",
19476
+ "keyboard": ["Scroll (no interactive controls)"]
19477
+ },
19478
+ "examples": [
19479
+ {
19480
+ "title": "Read-only snippet",
19481
+ "code": "import { Highlight } from '@cascivo/editor'\nimport '@cascivo/editor/styles.css'\n\n<Highlight language=\"json\" value={'{ \"ok\": true }'} />"
19482
+ }
19483
+ ],
19484
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
19485
+ "tags": ["editor", "code", "syntax-highlighting", "display", "read-only"],
19486
+ "intent": {
19487
+ "whenToUse": [
19488
+ "Displaying non-editable code or config with syntax colors — docs, snippets, examples",
19489
+ "A lightweight highlighter that themes via the cascivo token system"
19490
+ ],
19491
+ "whenNotToUse": [
19492
+ "The code must be editable — use CodeEditor",
19493
+ "You need copy-to-clipboard chrome around a snippet — pair with a code-snippet surface"
19494
+ ],
19495
+ "antiPatterns": [],
19496
+ "related": [
19497
+ {
19498
+ "name": "CodeEditor",
19499
+ "relationship": "pairs-with",
19500
+ "reason": "The editable surface sharing the same tokenizer"
19501
+ }
19502
+ ],
19503
+ "a11yRationale": "Renders a read-only <pre><code>; the line-number gutter is aria-hidden and an optional label names the block.",
19504
+ "flexibility": []
19505
+ }
19506
+ },
19507
+ "install": "@cascivo/editor"
19508
+ },
19509
+ {
19510
+ "name": "section/cta",
19511
+ "type": "section",
19512
+ "description": "Call-to-action band — quiet hairline-bordered section with title, description, and centered actions. Replace demo content before shipping.",
19513
+ "category": "layout",
19514
+ "version": "0.0.0",
19515
+ "files": [
19516
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/layouts/src/sections/cta/cta.tsx",
19517
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/layouts/src/sections/cta/cta.module.css"
19518
+ ],
19519
+ "dependencies": ["@cascivo/core"],
19520
+ "tags": ["section", "cta", "marketing"],
19521
+ "meta": {
19522
+ "name": "Cta",
19523
+ "description": "Call-to-action band — quiet hairline-bordered section with title, description, and centered actions. Replace demo content before shipping.",
19524
+ "category": "layout",
19525
+ "states": [],
19526
+ "variants": [],
19527
+ "sizes": [],
19528
+ "props": [
19529
+ {
19530
+ "name": "title",
19531
+ "type": "ReactNode",
19532
+ "required": true,
19533
+ "description": "Primary heading of the CTA band"
19534
+ },
19535
+ {
19536
+ "name": "description",
19537
+ "type": "ReactNode",
19538
+ "required": false,
19539
+ "description": "Supporting text below the title"
19540
+ },
19541
+ {
19542
+ "name": "actions",
19543
+ "type": "ReactNode",
19544
+ "required": false,
19545
+ "description": "Buttons or links centered below the description"
19546
+ },
19547
+ {
19548
+ "name": "headingLevel",
19549
+ "type": "1 | 2 | 3",
19550
+ "required": false,
19551
+ "default": "2",
19552
+ "description": "HTML heading level for document outline control"
19553
+ }
19554
+ ],
19555
+ "tokens": [
19556
+ "--cascivo-color-border",
19557
+ "--cascivo-surface-subtle",
19558
+ "--cascivo-text-2xl",
19559
+ "--cascivo-text-base",
19560
+ "--cascivo-font-bold",
19561
+ "--cascivo-text-secondary",
19562
+ "--cascivo-space-*"
19563
+ ],
19564
+ "accessibility": {
19565
+ "role": "region",
19566
+ "wcag": "2.1-AA",
19567
+ "keyboard": []
19568
+ },
19569
+ "examples": [
19570
+ {
19571
+ "title": "CTA band",
19572
+ "code": "<Cta title=\"Ready to ship?\" description=\"Add Cascade to your project in minutes.\" actions={<><Button>Get started</Button><Button variant=\"ghost\">View on GitHub</Button></>} />",
19573
+ "description": "Quiet bordered band with centered heading, description, and action buttons"
19574
+ }
19575
+ ],
19576
+ "dependencies": ["@cascivo/core"],
19577
+ "tags": ["section", "cta", "marketing"],
19578
+ "intent": {
19579
+ "whenToUse": [
19580
+ "A call-to-action band with title, description, and centered actions",
19581
+ "Prompting conversion between or after marketing sections"
19582
+ ],
19583
+ "whenNotToUse": [
19584
+ "The primary page intro — use Hero",
19585
+ "General content grouping — use Section"
19586
+ ],
19587
+ "antiPatterns": [],
19588
+ "related": [
19589
+ {
19590
+ "name": "Hero",
19591
+ "relationship": "pairs-with",
19592
+ "reason": "Hero opens the page; CTA reinforces conversion later"
19593
+ },
19594
+ {
19595
+ "name": "Section",
19596
+ "relationship": "alternative",
19597
+ "reason": "Use the plain section for non-CTA content"
19598
+ }
19599
+ ],
19600
+ "a11yRationale": "Renders a section with a heading and clearly labeled action controls.",
19601
+ "flexibility": []
19602
+ }
19603
+ }
19604
+ },
19605
+ {
19606
+ "name": "section/feature-grid",
19607
+ "type": "section",
19608
+ "description": "Feature section — AutoGrid of items with optional title, description, and icon slots. Icons are optional; the grid works text-only. Replace demo content before shipping.",
19609
+ "category": "layout",
19610
+ "version": "0.0.0",
19611
+ "files": [
19612
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/layouts/src/sections/feature-grid/feature-grid.tsx",
19613
+ "https://raw.githubusercontent.com/cascivo/cascivo/main/packages/layouts/src/sections/feature-grid/feature-grid.module.css"
19614
+ ],
19615
+ "dependencies": ["@cascivo/core"],
19616
+ "tags": ["section", "features", "grid"],
19617
+ "meta": {
19618
+ "name": "FeatureGrid",
19619
+ "description": "Feature section — AutoGrid of items with optional title, description, and icon slots. Icons are optional; the grid works text-only. Replace demo content before shipping.",
19620
+ "category": "layout",
19621
+ "states": [],
19622
+ "variants": [],
19623
+ "sizes": [],
19624
+ "props": [
19625
+ {
19626
+ "name": "items",
19627
+ "type": "FeatureItem[]",
19628
+ "required": true,
19629
+ "description": "Array of feature items with title, optional description, icon, and href"
19630
+ },
19631
+ {
19632
+ "name": "title",
19633
+ "type": "ReactNode",
19634
+ "required": false,
19635
+ "description": "Section heading above the grid"
19636
+ },
19637
+ {
19638
+ "name": "description",
18715
19639
  "type": "ReactNode",
18716
19640
  "required": false,
18717
19641
  "description": "Subheading below the section title"
@@ -19175,6 +20099,1123 @@
19175
20099
  "flexibility": []
19176
20100
  }
19177
20101
  }
20102
+ },
20103
+ {
20104
+ "name": "flow/flow",
20105
+ "type": "flow",
20106
+ "description": "The declarative, AI-first flow surface — render a node/edge graph from plain serializable data.",
20107
+ "category": "display",
20108
+ "version": "0.0.0",
20109
+ "files": [],
20110
+ "dependencies": ["@cascivo/core"],
20111
+ "tags": ["flow", "graph", "declarative", "diagram", "ai-first"],
20112
+ "meta": {
20113
+ "name": "Flow",
20114
+ "description": "The declarative, AI-first flow surface — render a node/edge graph from plain serializable data.",
20115
+ "category": "display",
20116
+ "states": [],
20117
+ "variants": [],
20118
+ "sizes": [],
20119
+ "props": [
20120
+ {
20121
+ "name": "nodes",
20122
+ "type": "FlowNode[]",
20123
+ "required": true,
20124
+ "description": "Initial nodes (serializable)."
20125
+ },
20126
+ {
20127
+ "name": "edges",
20128
+ "type": "FlowEdge[]",
20129
+ "required": true,
20130
+ "description": "Initial edges (serializable)."
20131
+ },
20132
+ {
20133
+ "name": "onNodesChange",
20134
+ "type": "(nodes: FlowNode[]) => void",
20135
+ "required": false
20136
+ },
20137
+ {
20138
+ "name": "onEdgesChange",
20139
+ "type": "(edges: FlowEdge[]) => void",
20140
+ "required": false
20141
+ },
20142
+ {
20143
+ "name": "onConnect",
20144
+ "type": "(connection: Connection) => void",
20145
+ "required": false
20146
+ },
20147
+ {
20148
+ "name": "nodeTypes",
20149
+ "type": "Record<string, NodeRenderer>",
20150
+ "required": false,
20151
+ "description": "Custom node renderers keyed by node.type."
20152
+ },
20153
+ {
20154
+ "name": "fitView",
20155
+ "type": "boolean",
20156
+ "required": false,
20157
+ "default": "true"
20158
+ },
20159
+ {
20160
+ "name": "background",
20161
+ "type": "boolean | FlowBackgroundProps",
20162
+ "required": false,
20163
+ "default": "false"
20164
+ },
20165
+ {
20166
+ "name": "controls",
20167
+ "type": "boolean",
20168
+ "required": false,
20169
+ "default": "false"
20170
+ },
20171
+ {
20172
+ "name": "minimap",
20173
+ "type": "boolean",
20174
+ "required": false,
20175
+ "default": "false"
20176
+ },
20177
+ {
20178
+ "name": "layout",
20179
+ "type": "'grid' | 'layered' | ((nodes, edges) => FlowNode[])",
20180
+ "required": false,
20181
+ "description": "Optional dependency-free layout."
20182
+ },
20183
+ {
20184
+ "name": "interactive",
20185
+ "type": "boolean",
20186
+ "required": false,
20187
+ "default": "true",
20188
+ "description": "When false (view mode), nodes cannot be selected, dragged, or connected and handles are hidden; pan/zoom still work."
20189
+ },
20190
+ {
20191
+ "name": "className",
20192
+ "type": "string",
20193
+ "required": false
20194
+ }
20195
+ ],
20196
+ "tokens": ["--cascivo-color-bg", "--cascivo-color-surface", "--cascivo-color-accent"],
20197
+ "accessibility": {
20198
+ "role": "application",
20199
+ "wcag": "2.1-AA",
20200
+ "keyboard": [
20201
+ "Tab (focus nodes)",
20202
+ "Enter/Space (select)",
20203
+ "Drag (pan/move)",
20204
+ "Wheel (zoom)"
20205
+ ]
20206
+ },
20207
+ "examples": [
20208
+ {
20209
+ "title": "Declarative pipeline",
20210
+ "description": "A flow from plain serializable data, with background, controls, and an animated edge.",
20211
+ "code": "() => (\n <Flow\n style={{ height: 280 }}\n background\n controls\n nodes={[\n { id: 'a', position: { x: 0, y: 60 }, data: { label: 'Client' } },\n { id: 'b', position: { x: 240, y: 60 }, data: { label: 'Gateway' } },\n { id: 'c', position: { x: 480, y: 60 }, data: { label: 'Service' } },\n ]}\n edges={[\n { id: 'ab', source: 'a', target: 'b', animated: true, label: 'request' },\n { id: 'bc', source: 'b', target: 'c' },\n ]}\n />\n)"
20212
+ },
20213
+ {
20214
+ "title": "Layered layout",
20215
+ "description": "Let the dependency-free layered layout arrange a small DAG.",
20216
+ "code": "() => (\n <Flow\n style={{ height: 300 }}\n layout=\"layered\"\n background\n minimap\n nodes={[\n { id: 'a', position: { x: 0, y: 0 }, data: { label: 'Ingest' } },\n { id: 'b', position: { x: 0, y: 0 }, data: { label: 'Transform' } },\n { id: 'c', position: { x: 0, y: 0 }, data: { label: 'Validate' } },\n { id: 'd', position: { x: 0, y: 0 }, data: { label: 'Load' } },\n ]}\n edges={[\n { id: 'ab', source: 'a', target: 'b' },\n { id: 'ac', source: 'a', target: 'c' },\n { id: 'bd', source: 'b', target: 'd' },\n { id: 'cd', source: 'c', target: 'd' },\n ]}\n />\n)"
20217
+ }
20218
+ ],
20219
+ "dependencies": ["@cascivo/core"],
20220
+ "tags": ["flow", "graph", "declarative", "diagram", "ai-first"],
20221
+ "intent": {
20222
+ "whenToUse": [
20223
+ "Rendering a graph from data — the common case and the agent-emittable surface",
20224
+ "Flowcharts, DAGs, pipelines, and mind-maps from plain nodes/edges arrays"
20225
+ ],
20226
+ "whenNotToUse": [
20227
+ "A scripted, sequenced walkthrough — use FlowStory",
20228
+ "Heavy graph editing (undo/redo, resize/rotate) — out of scope"
20229
+ ],
20230
+ "antiPatterns": [
20231
+ {
20232
+ "bad": "Imperatively building the graph with graph.addNode(...)",
20233
+ "good": "<Flow nodes={…} edges={…} />",
20234
+ "why": "Declarative serializable data is what an agent can emit and what stays in sync with props."
20235
+ }
20236
+ ],
20237
+ "related": [
20238
+ {
20239
+ "name": "FlowStory",
20240
+ "relationship": "alternative",
20241
+ "reason": "Scripted, captioned storyline animation."
20242
+ },
20243
+ {
20244
+ "name": "FlowNode",
20245
+ "relationship": "contains",
20246
+ "reason": "Renders a node per entry."
20247
+ },
20248
+ {
20249
+ "name": "FlowEdge",
20250
+ "relationship": "contains",
20251
+ "reason": "Renders an edge per entry."
20252
+ }
20253
+ ],
20254
+ "a11yRationale": "role=\"application\" canvas; nodes are focusable groups; controls are real i18n-labeled buttons.",
20255
+ "flexibility": [
20256
+ {
20257
+ "area": "rendering",
20258
+ "level": "flexible",
20259
+ "note": "Custom node renderers via nodeTypes."
20260
+ },
20261
+ {
20262
+ "area": "layout",
20263
+ "level": "flexible",
20264
+ "note": "grid | layered | bring-your-own positions."
20265
+ },
20266
+ {
20267
+ "area": "chrome",
20268
+ "level": "flexible",
20269
+ "note": "Optional background / controls / minimap."
20270
+ }
20271
+ ]
20272
+ }
20273
+ },
20274
+ "install": "@cascivo/flow"
20275
+ },
20276
+ {
20277
+ "name": "flow/flow-background",
20278
+ "type": "flow",
20279
+ "description": "Decorative dots / grid / cross canvas background, drawn purely in CSS gradients.",
20280
+ "category": "display",
20281
+ "version": "0.0.0",
20282
+ "files": [],
20283
+ "dependencies": ["@cascivo/core"],
20284
+ "tags": ["flow", "background", "grid", "dots", "canvas"],
20285
+ "meta": {
20286
+ "name": "FlowBackground",
20287
+ "description": "Decorative dots / grid / cross canvas background, drawn purely in CSS gradients.",
20288
+ "category": "display",
20289
+ "states": [],
20290
+ "variants": ["dots", "grid", "cross"],
20291
+ "sizes": [],
20292
+ "props": [
20293
+ {
20294
+ "name": "variant",
20295
+ "type": "'dots' | 'grid' | 'cross'",
20296
+ "required": false,
20297
+ "default": "dots",
20298
+ "description": "Pattern style."
20299
+ },
20300
+ {
20301
+ "name": "gap",
20302
+ "type": "number",
20303
+ "required": false,
20304
+ "default": "20",
20305
+ "description": "Cell spacing (px)."
20306
+ },
20307
+ {
20308
+ "name": "size",
20309
+ "type": "number",
20310
+ "required": false,
20311
+ "default": "1",
20312
+ "description": "Dot radius / line thickness (px)."
20313
+ },
20314
+ {
20315
+ "name": "color",
20316
+ "type": "string",
20317
+ "required": false,
20318
+ "description": "Pattern color (defaults to the border token)."
20319
+ },
20320
+ {
20321
+ "name": "className",
20322
+ "type": "string",
20323
+ "required": false
20324
+ }
20325
+ ],
20326
+ "tokens": ["--cascivo-color-border"],
20327
+ "accessibility": {
20328
+ "role": "presentation",
20329
+ "wcag": "2.1-AA",
20330
+ "keyboard": []
20331
+ },
20332
+ "examples": [
20333
+ {
20334
+ "title": "Dotted background",
20335
+ "description": "A dotted grid behind a flow canvas.",
20336
+ "code": "() => (\n <div style={{ position: 'relative', height: 220, overflow: 'hidden' }}>\n <FlowBackground variant=\"dots\" gap={24} />\n </div>\n)"
20337
+ },
20338
+ {
20339
+ "title": "Grid and cross",
20340
+ "description": "The grid and cross variants.",
20341
+ "code": "() => (\n <div style={{ display: 'grid', gap: 16, gridTemplateColumns: '1fr 1fr' }}>\n <div style={{ position: 'relative', height: 180, overflow: 'hidden' }}>\n <FlowBackground variant=\"grid\" gap={28} />\n </div>\n <div style={{ position: 'relative', height: 180, overflow: 'hidden' }}>\n <FlowBackground variant=\"cross\" gap={28} size={4} />\n </div>\n </div>\n)"
20342
+ }
20343
+ ],
20344
+ "dependencies": ["@cascivo/core"],
20345
+ "tags": ["flow", "background", "grid", "dots", "canvas"],
20346
+ "intent": {
20347
+ "whenToUse": [
20348
+ "Giving a flow canvas a sense of space and scale with a dotted or grid backdrop",
20349
+ "Reinforcing pan/zoom by letting the pattern move and scale with the viewport"
20350
+ ],
20351
+ "whenNotToUse": [
20352
+ "As a page background — this is a flow-canvas decoration, not a general surface"
20353
+ ],
20354
+ "antiPatterns": [
20355
+ {
20356
+ "bad": "Rendering a DOM node per grid cell",
20357
+ "good": "A single CSS gradient layer",
20358
+ "why": "Per-cell DOM is needlessly expensive; one repeating gradient costs nothing."
20359
+ }
20360
+ ],
20361
+ "related": [
20362
+ {
20363
+ "name": "FlowCanvas",
20364
+ "relationship": "contained-by",
20365
+ "reason": "Lives inside the canvas pane."
20366
+ }
20367
+ ],
20368
+ "a11yRationale": "Purely decorative — marked aria-hidden and presentation, never in the a11y tree.",
20369
+ "flexibility": [
20370
+ {
20371
+ "area": "pattern",
20372
+ "level": "flexible",
20373
+ "note": "dots | grid | cross with configurable gap/size."
20374
+ }
20375
+ ]
20376
+ }
20377
+ },
20378
+ "install": "@cascivo/flow"
20379
+ },
20380
+ {
20381
+ "name": "flow/flow-controls",
20382
+ "type": "flow",
20383
+ "description": "Zoom in / out / fit-view controls for a flow canvas — real, i18n-labeled buttons.",
20384
+ "category": "display",
20385
+ "version": "0.0.0",
20386
+ "files": [],
20387
+ "dependencies": ["@cascivo/core"],
20388
+ "tags": ["flow", "controls", "zoom", "chrome"],
20389
+ "meta": {
20390
+ "name": "FlowControls",
20391
+ "description": "Zoom in / out / fit-view controls for a flow canvas — real, i18n-labeled buttons.",
20392
+ "category": "display",
20393
+ "states": [],
20394
+ "variants": [],
20395
+ "sizes": [],
20396
+ "props": [
20397
+ {
20398
+ "name": "position",
20399
+ "type": "'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'",
20400
+ "required": false,
20401
+ "default": "bottom-left"
20402
+ },
20403
+ {
20404
+ "name": "showZoom",
20405
+ "type": "boolean",
20406
+ "required": false,
20407
+ "default": "true"
20408
+ },
20409
+ {
20410
+ "name": "showFitView",
20411
+ "type": "boolean",
20412
+ "required": false,
20413
+ "default": "true"
20414
+ },
20415
+ {
20416
+ "name": "onZoomIn",
20417
+ "type": "() => void",
20418
+ "required": false
20419
+ },
20420
+ {
20421
+ "name": "onZoomOut",
20422
+ "type": "() => void",
20423
+ "required": false
20424
+ },
20425
+ {
20426
+ "name": "onFitView",
20427
+ "type": "() => void",
20428
+ "required": false
20429
+ },
20430
+ {
20431
+ "name": "labels",
20432
+ "type": "FlowControlsLabels",
20433
+ "required": false
20434
+ },
20435
+ {
20436
+ "name": "className",
20437
+ "type": "string",
20438
+ "required": false
20439
+ }
20440
+ ],
20441
+ "tokens": [
20442
+ "--cascivo-color-surface",
20443
+ "--cascivo-color-border",
20444
+ "--cascivo-target-min-coarse"
20445
+ ],
20446
+ "accessibility": {
20447
+ "role": "group",
20448
+ "wcag": "2.1-AA",
20449
+ "keyboard": ["Tab (focus)", "Enter/Space (activate)"]
20450
+ },
20451
+ "examples": [
20452
+ {
20453
+ "title": "Canvas controls",
20454
+ "code": "() => (\n <div style={{ position: 'relative', height: 200, border: '1px solid var(--cascivo-color-border)' }}>\n <FlowControls onZoomIn={() => {}} onZoomOut={() => {}} onFitView={() => {}} />\n </div>\n)"
20455
+ }
20456
+ ],
20457
+ "dependencies": ["@cascivo/core"],
20458
+ "tags": ["flow", "controls", "zoom", "chrome"],
20459
+ "intent": {
20460
+ "whenToUse": ["Giving users explicit zoom/fit controls on a flow canvas"],
20461
+ "whenNotToUse": ["When the canvas is static/non-interactive"],
20462
+ "antiPatterns": [],
20463
+ "related": [
20464
+ {
20465
+ "name": "FlowCanvas",
20466
+ "relationship": "pairs-with",
20467
+ "reason": "Calls its viewport actions."
20468
+ },
20469
+ {
20470
+ "name": "FlowMiniMap",
20471
+ "relationship": "pairs-with",
20472
+ "reason": "Complementary navigation chrome."
20473
+ }
20474
+ ],
20475
+ "a11yRationale": "Real <button>s with i18n-defaulted aria-labels; ≥44px coarse targets.",
20476
+ "flexibility": [
20477
+ {
20478
+ "area": "position",
20479
+ "level": "flexible",
20480
+ "note": "Four corners."
20481
+ },
20482
+ {
20483
+ "area": "buttons",
20484
+ "level": "flexible",
20485
+ "note": "Zoom / fit toggleable."
20486
+ }
20487
+ ]
20488
+ }
20489
+ },
20490
+ "install": "@cascivo/flow"
20491
+ },
20492
+ {
20493
+ "name": "flow/flow-edge",
20494
+ "type": "flow",
20495
+ "description": "An SVG edge with bezier/straight/smoothstep paths, an arrowhead, an optional label, and animation.",
20496
+ "category": "display",
20497
+ "version": "0.0.0",
20498
+ "files": [],
20499
+ "dependencies": ["@cascivo/core"],
20500
+ "tags": ["flow", "edge", "connector", "animated", "svg"],
20501
+ "meta": {
20502
+ "name": "FlowEdge",
20503
+ "description": "An SVG edge with bezier/straight/smoothstep paths, an arrowhead, an optional label, and animation.",
20504
+ "category": "display",
20505
+ "states": ["default", "selected", "animated"],
20506
+ "variants": ["bezier", "straight", "smoothstep"],
20507
+ "sizes": [],
20508
+ "props": [
20509
+ {
20510
+ "name": "sourceX",
20511
+ "type": "number",
20512
+ "required": true,
20513
+ "description": "Source anchor x (flow coords)."
20514
+ },
20515
+ {
20516
+ "name": "sourceY",
20517
+ "type": "number",
20518
+ "required": true
20519
+ },
20520
+ {
20521
+ "name": "targetX",
20522
+ "type": "number",
20523
+ "required": true
20524
+ },
20525
+ {
20526
+ "name": "targetY",
20527
+ "type": "number",
20528
+ "required": true
20529
+ },
20530
+ {
20531
+ "name": "type",
20532
+ "type": "'bezier' | 'straight' | 'smoothstep'",
20533
+ "required": false,
20534
+ "default": "bezier"
20535
+ },
20536
+ {
20537
+ "name": "animated",
20538
+ "type": "boolean",
20539
+ "required": false,
20540
+ "default": "false"
20541
+ },
20542
+ {
20543
+ "name": "label",
20544
+ "type": "ReactNode",
20545
+ "required": false
20546
+ },
20547
+ {
20548
+ "name": "selected",
20549
+ "type": "boolean",
20550
+ "required": false,
20551
+ "default": "false"
20552
+ },
20553
+ {
20554
+ "name": "markerStart",
20555
+ "type": "boolean",
20556
+ "required": false,
20557
+ "default": "false",
20558
+ "description": "Arrowhead at the source (points back toward the source) — set both for bidirectional."
20559
+ },
20560
+ {
20561
+ "name": "markerEnd",
20562
+ "type": "boolean",
20563
+ "required": false,
20564
+ "default": "true",
20565
+ "description": "Arrowhead at the target. Set false for an undirected line."
20566
+ },
20567
+ {
20568
+ "name": "className",
20569
+ "type": "string",
20570
+ "required": false
20571
+ }
20572
+ ],
20573
+ "tokens": [
20574
+ "--cascivo-color-border-strong",
20575
+ "--cascivo-color-accent",
20576
+ "--cascivo-color-surface"
20577
+ ],
20578
+ "accessibility": {
20579
+ "role": "presentation",
20580
+ "wcag": "2.1-AA",
20581
+ "keyboard": [],
20582
+ "reducedMotion": true
20583
+ },
20584
+ "examples": [
20585
+ {
20586
+ "title": "Edge path types",
20587
+ "description": "Bezier, straight, smoothstep, and an animated edge.",
20588
+ "code": "() => (\n <div style={{ position: 'relative', height: 220 }}>\n <FlowEdge sourceX={20} sourceY={30} targetX={260} targetY={30} type=\"bezier\" label=\"bezier\" />\n <FlowEdge sourceX={20} sourceY={90} targetX={260} targetY={90} type=\"smoothstep\" label=\"step\" />\n <FlowEdge sourceX={20} sourceY={150} targetX={260} targetY={150} animated label=\"animated\" />\n </div>\n)"
20589
+ },
20590
+ {
20591
+ "title": "Arrow direction",
20592
+ "description": "Forward (default), backward, bidirectional, or undirected — via markerStart/markerEnd.",
20593
+ "code": "() => (\n <div style={{ position: 'relative', height: 260 }}>\n <FlowEdge sourceX={20} sourceY={30} targetX={260} targetY={30} label=\"forward\" />\n <FlowEdge sourceX={20} sourceY={90} targetX={260} targetY={90} markerEnd={false} markerStart label=\"backward\" />\n <FlowEdge sourceX={20} sourceY={150} targetX={260} targetY={150} markerStart label=\"both\" />\n <FlowEdge sourceX={20} sourceY={210} targetX={260} targetY={210} markerEnd={false} label=\"undirected\" />\n </div>\n)"
20594
+ }
20595
+ ],
20596
+ "dependencies": ["@cascivo/core"],
20597
+ "tags": ["flow", "edge", "connector", "animated", "svg"],
20598
+ "intent": {
20599
+ "whenToUse": [
20600
+ "Connecting two nodes with a directed path and arrowhead",
20601
+ "Animating flow direction along a connection (\"marching ants\")"
20602
+ ],
20603
+ "whenNotToUse": [
20604
+ "For undirected relationships where an arrowhead would mislead — set markerEnd={false}"
20605
+ ],
20606
+ "antiPatterns": [
20607
+ {
20608
+ "bad": "A requestAnimationFrame loop to animate the dash",
20609
+ "good": "A CSS stroke-dashoffset keyframe",
20610
+ "why": "The compositor animates CSS for free; a JS loop re-renders every frame."
20611
+ }
20612
+ ],
20613
+ "related": [
20614
+ {
20615
+ "name": "FlowNode",
20616
+ "relationship": "pairs-with",
20617
+ "reason": "Edges connect nodes."
20618
+ },
20619
+ {
20620
+ "name": "FlowStory",
20621
+ "relationship": "pairs-with",
20622
+ "reason": "Storylines animate edges in sequence."
20623
+ }
20624
+ ],
20625
+ "a11yRationale": "Decorative SVG (aria-hidden); animation is disabled under prefers-reduced-motion.",
20626
+ "flexibility": [
20627
+ {
20628
+ "area": "path",
20629
+ "level": "flexible",
20630
+ "note": "bezier | straight | smoothstep."
20631
+ },
20632
+ {
20633
+ "area": "animation",
20634
+ "level": "flexible",
20635
+ "note": "Optional, reduced-motion-safe."
20636
+ }
20637
+ ]
20638
+ }
20639
+ },
20640
+ "install": "@cascivo/flow"
20641
+ },
20642
+ {
20643
+ "name": "flow/flow-handle",
20644
+ "type": "flow",
20645
+ "description": "A connection port on a node edge — where edges attach and interactive connect starts.",
20646
+ "category": "display",
20647
+ "version": "0.0.0",
20648
+ "files": [],
20649
+ "dependencies": ["@cascivo/core"],
20650
+ "tags": ["flow", "handle", "port", "connect"],
20651
+ "meta": {
20652
+ "name": "FlowHandle",
20653
+ "description": "A connection port on a node edge — where edges attach and interactive connect starts.",
20654
+ "category": "display",
20655
+ "states": ["default", "hover", "focus"],
20656
+ "variants": ["source", "target"],
20657
+ "sizes": [],
20658
+ "props": [
20659
+ {
20660
+ "name": "type",
20661
+ "type": "'source' | 'target'",
20662
+ "required": true
20663
+ },
20664
+ {
20665
+ "name": "position",
20666
+ "type": "'top' | 'right' | 'bottom' | 'left'",
20667
+ "required": false,
20668
+ "description": "Edge of the node (defaults: source→right, target→left)."
20669
+ },
20670
+ {
20671
+ "name": "id",
20672
+ "type": "string",
20673
+ "required": false,
20674
+ "description": "Handle id for multi-handle nodes."
20675
+ },
20676
+ {
20677
+ "name": "isConnectable",
20678
+ "type": "boolean",
20679
+ "required": false,
20680
+ "default": "true"
20681
+ },
20682
+ {
20683
+ "name": "className",
20684
+ "type": "string",
20685
+ "required": false
20686
+ }
20687
+ ],
20688
+ "tokens": [
20689
+ "--cascivo-color-accent",
20690
+ "--cascivo-color-surface",
20691
+ "--cascivo-target-min-coarse"
20692
+ ],
20693
+ "accessibility": {
20694
+ "role": "button",
20695
+ "wcag": "2.1-AA",
20696
+ "keyboard": ["Tab (focus the port)"]
20697
+ },
20698
+ "examples": [
20699
+ {
20700
+ "title": "Source and target ports",
20701
+ "code": "() => (\n <div style={{ position: 'relative', height: 160 }}>\n <FlowNode id=\"api\" defaultPosition={{ x: 70, y: 55 }}>\n API\n <FlowHandle type=\"target\" position=\"left\" />\n <FlowHandle type=\"source\" position=\"right\" />\n </FlowNode>\n </div>\n)"
20702
+ }
20703
+ ],
20704
+ "dependencies": ["@cascivo/core"],
20705
+ "tags": ["flow", "handle", "port", "connect"],
20706
+ "intent": {
20707
+ "whenToUse": [
20708
+ "Marking where edges connect to a node",
20709
+ "Enabling interactive connect (drag from a source to a target)"
20710
+ ],
20711
+ "whenNotToUse": ["On nodes that are never connected"],
20712
+ "antiPatterns": [],
20713
+ "related": [
20714
+ {
20715
+ "name": "FlowNode",
20716
+ "relationship": "contained-by",
20717
+ "reason": "Ports live inside a node."
20718
+ },
20719
+ {
20720
+ "name": "FlowEdge",
20721
+ "relationship": "pairs-with",
20722
+ "reason": "Edges anchor to handles."
20723
+ }
20724
+ ],
20725
+ "a11yRationale": "Focusable with a ≥44px coarse-pointer hit area around the visible dot.",
20726
+ "flexibility": [
20727
+ {
20728
+ "area": "position",
20729
+ "level": "flexible",
20730
+ "note": "top | right | bottom | left."
20731
+ }
20732
+ ]
20733
+ }
20734
+ },
20735
+ "install": "@cascivo/flow"
20736
+ },
20737
+ {
20738
+ "name": "flow/flow-minimap",
20739
+ "type": "flow",
20740
+ "description": "A scaled SVG overview of the graph with a draggable viewport rectangle.",
20741
+ "category": "display",
20742
+ "version": "0.0.0",
20743
+ "files": [],
20744
+ "dependencies": ["@cascivo/core"],
20745
+ "tags": ["flow", "minimap", "overview", "chrome"],
20746
+ "meta": {
20747
+ "name": "FlowMiniMap",
20748
+ "description": "A scaled SVG overview of the graph with a draggable viewport rectangle.",
20749
+ "category": "display",
20750
+ "states": [],
20751
+ "variants": [],
20752
+ "sizes": [],
20753
+ "props": [
20754
+ {
20755
+ "name": "nodes",
20756
+ "type": "FlowNode[]",
20757
+ "required": true
20758
+ },
20759
+ {
20760
+ "name": "viewport",
20761
+ "type": "Viewport",
20762
+ "required": true
20763
+ },
20764
+ {
20765
+ "name": "containerWidth",
20766
+ "type": "number",
20767
+ "required": false
20768
+ },
20769
+ {
20770
+ "name": "containerHeight",
20771
+ "type": "number",
20772
+ "required": false
20773
+ },
20774
+ {
20775
+ "name": "width",
20776
+ "type": "number",
20777
+ "required": false,
20778
+ "default": "200"
20779
+ },
20780
+ {
20781
+ "name": "height",
20782
+ "type": "number",
20783
+ "required": false,
20784
+ "default": "150"
20785
+ },
20786
+ {
20787
+ "name": "position",
20788
+ "type": "'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'",
20789
+ "required": false,
20790
+ "default": "bottom-right"
20791
+ },
20792
+ {
20793
+ "name": "onViewportChange",
20794
+ "type": "(viewport: Viewport) => void",
20795
+ "required": false
20796
+ },
20797
+ {
20798
+ "name": "className",
20799
+ "type": "string",
20800
+ "required": false
20801
+ }
20802
+ ],
20803
+ "tokens": [
20804
+ "--cascivo-color-surface",
20805
+ "--cascivo-color-border-strong",
20806
+ "--cascivo-color-accent"
20807
+ ],
20808
+ "accessibility": {
20809
+ "role": "img",
20810
+ "wcag": "2.1-AA",
20811
+ "keyboard": []
20812
+ },
20813
+ "examples": [
20814
+ {
20815
+ "title": "Graph overview",
20816
+ "code": "() => (\n <FlowMiniMap\n nodes={[\n { id: 'a', position: { x: 0, y: 0 } },\n { id: 'b', position: { x: 220, y: 120 } },\n { id: 'c', position: { x: 440, y: 0 } },\n ]}\n viewport={{ x: 0, y: 0, zoom: 1 }}\n containerWidth={400}\n containerHeight={300}\n />\n)"
20817
+ }
20818
+ ],
20819
+ "dependencies": ["@cascivo/core"],
20820
+ "tags": ["flow", "minimap", "overview", "chrome"],
20821
+ "intent": {
20822
+ "whenToUse": [
20823
+ "Orienting users in a large graph",
20824
+ "Letting users jump around by dragging the view rect"
20825
+ ],
20826
+ "whenNotToUse": ["Tiny graphs that fit on screen"],
20827
+ "antiPatterns": [],
20828
+ "related": [
20829
+ {
20830
+ "name": "FlowControls",
20831
+ "relationship": "pairs-with",
20832
+ "reason": "Complementary navigation chrome."
20833
+ }
20834
+ ],
20835
+ "a11yRationale": "role=\"img\" with an i18n-defaulted label describing the overview.",
20836
+ "flexibility": [
20837
+ {
20838
+ "area": "size",
20839
+ "level": "flexible",
20840
+ "note": "Configurable width/height."
20841
+ }
20842
+ ]
20843
+ }
20844
+ },
20845
+ "install": "@cascivo/flow"
20846
+ },
20847
+ {
20848
+ "name": "flow/flow-node",
20849
+ "type": "flow",
20850
+ "description": "An HTML node box positioned in the viewport pane — draggable, selectable, with arbitrary children.",
20851
+ "category": "display",
20852
+ "version": "0.0.0",
20853
+ "files": [],
20854
+ "dependencies": ["@cascivo/core"],
20855
+ "tags": ["flow", "node", "draggable", "graph"],
20856
+ "meta": {
20857
+ "name": "FlowNode",
20858
+ "description": "An HTML node box positioned in the viewport pane — draggable, selectable, with arbitrary children.",
20859
+ "category": "display",
20860
+ "states": ["default", "dragging", "selected", "focus"],
20861
+ "variants": [],
20862
+ "sizes": [],
20863
+ "props": [
20864
+ {
20865
+ "name": "id",
20866
+ "type": "string",
20867
+ "required": true,
20868
+ "description": "Stable node id."
20869
+ },
20870
+ {
20871
+ "name": "position",
20872
+ "type": "{ x: number; y: number }",
20873
+ "required": false,
20874
+ "description": "Position in flow coords (controllable)."
20875
+ },
20876
+ {
20877
+ "name": "onPositionChange",
20878
+ "type": "(position: XYPosition) => void",
20879
+ "required": false,
20880
+ "description": "Fired while dragging."
20881
+ },
20882
+ {
20883
+ "name": "zoom",
20884
+ "type": "number",
20885
+ "required": false,
20886
+ "default": "1",
20887
+ "description": "Current zoom (drag deltas are divided by it)."
20888
+ },
20889
+ {
20890
+ "name": "selected",
20891
+ "type": "boolean",
20892
+ "required": false,
20893
+ "default": "false"
20894
+ },
20895
+ {
20896
+ "name": "draggable",
20897
+ "type": "boolean",
20898
+ "required": false,
20899
+ "default": "true"
20900
+ },
20901
+ {
20902
+ "name": "interactive",
20903
+ "type": "boolean",
20904
+ "required": false,
20905
+ "default": "true",
20906
+ "description": "When false, the node is view-only: not draggable, selectable, or focusable."
20907
+ },
20908
+ {
20909
+ "name": "onSelect",
20910
+ "type": "(id: string) => void",
20911
+ "required": false
20912
+ },
20913
+ {
20914
+ "name": "children",
20915
+ "type": "ReactNode",
20916
+ "required": false,
20917
+ "description": "Any cascivo content."
20918
+ },
20919
+ {
20920
+ "name": "className",
20921
+ "type": "string",
20922
+ "required": false
20923
+ }
20924
+ ],
20925
+ "tokens": [
20926
+ "--cascivo-color-surface",
20927
+ "--cascivo-color-border",
20928
+ "--cascivo-color-accent",
20929
+ "--cascivo-radius-md",
20930
+ "--cascivo-shadow-sm"
20931
+ ],
20932
+ "accessibility": {
20933
+ "role": "group",
20934
+ "wcag": "2.1-AA",
20935
+ "keyboard": ["Tab (focus)", "Enter/Space (select)"]
20936
+ },
20937
+ "examples": [
20938
+ {
20939
+ "title": "A draggable node",
20940
+ "code": "() => (\n <div style={{ position: 'relative', height: 160 }}>\n <FlowNode id=\"a\" defaultPosition={{ x: 40, y: 50 }}>Service A</FlowNode>\n </div>\n)"
20941
+ }
20942
+ ],
20943
+ "dependencies": ["@cascivo/core"],
20944
+ "tags": ["flow", "node", "draggable", "graph"],
20945
+ "intent": {
20946
+ "whenToUse": [
20947
+ "Representing a unit in a graph that holds arbitrary themed content",
20948
+ "When you hand-compose a flow and need draggable, selectable boxes"
20949
+ ],
20950
+ "whenNotToUse": ["For the common case — the declarative <Flow> renders nodes for you"],
20951
+ "antiPatterns": [
20952
+ {
20953
+ "bad": "Rendering node content into an SVG",
20954
+ "good": "HTML node boxes",
20955
+ "why": "HTML nodes inherit the data-theme scope and can contain any cascivo component."
20956
+ }
20957
+ ],
20958
+ "related": [
20959
+ {
20960
+ "name": "FlowHandle",
20961
+ "relationship": "contains",
20962
+ "reason": "Connection ports live inside a node."
20963
+ },
20964
+ {
20965
+ "name": "FlowEdge",
20966
+ "relationship": "pairs-with",
20967
+ "reason": "Edges route between nodes."
20968
+ }
20969
+ ],
20970
+ "a11yRationale": "Focusable group; Enter/Space select. Visual states (hover/focus/selected) are CSS.",
20971
+ "flexibility": [
20972
+ {
20973
+ "area": "content",
20974
+ "level": "flexible",
20975
+ "note": "Renders any children."
20976
+ },
20977
+ {
20978
+ "area": "position",
20979
+ "level": "flexible",
20980
+ "note": "Controllable; draggable toggleable."
20981
+ }
20982
+ ]
20983
+ }
20984
+ },
20985
+ "install": "@cascivo/flow"
20986
+ },
20987
+ {
20988
+ "name": "flow/flow-panel",
20989
+ "type": "flow",
20990
+ "description": "An absolutely-positioned slot for custom flow-canvas UI (legend, toolbar).",
20991
+ "category": "display",
20992
+ "version": "0.0.0",
20993
+ "files": [],
20994
+ "dependencies": ["@cascivo/core"],
20995
+ "tags": ["flow", "panel", "slot", "chrome"],
20996
+ "meta": {
20997
+ "name": "FlowPanel",
20998
+ "description": "An absolutely-positioned slot for custom flow-canvas UI (legend, toolbar).",
20999
+ "category": "display",
21000
+ "states": [],
21001
+ "variants": [],
21002
+ "sizes": [],
21003
+ "props": [
21004
+ {
21005
+ "name": "position",
21006
+ "type": "'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'",
21007
+ "required": false,
21008
+ "default": "top-right"
21009
+ },
21010
+ {
21011
+ "name": "children",
21012
+ "type": "ReactNode",
21013
+ "required": false
21014
+ },
21015
+ {
21016
+ "name": "className",
21017
+ "type": "string",
21018
+ "required": false
21019
+ }
21020
+ ],
21021
+ "tokens": ["--cascivo-space-3"],
21022
+ "accessibility": {
21023
+ "role": "group",
21024
+ "wcag": "2.1-AA",
21025
+ "keyboard": []
21026
+ },
21027
+ "examples": [
21028
+ {
21029
+ "title": "A legend panel",
21030
+ "code": "() => (\n <div style={{ position: 'relative', height: 160, border: '1px solid var(--cascivo-color-border)' }}>\n <FlowPanel position=\"top-right\">Legend</FlowPanel>\n </div>\n)"
21031
+ }
21032
+ ],
21033
+ "dependencies": ["@cascivo/core"],
21034
+ "tags": ["flow", "panel", "slot", "chrome"],
21035
+ "intent": {
21036
+ "whenToUse": ["Overlaying custom UI (a legend, a toolbar) on a flow canvas"],
21037
+ "whenNotToUse": ["For zoom/fit controls — use FlowControls"],
21038
+ "antiPatterns": [],
21039
+ "related": [
21040
+ {
21041
+ "name": "FlowControls",
21042
+ "relationship": "alternative",
21043
+ "reason": "Purpose-built zoom/fit chrome."
21044
+ }
21045
+ ],
21046
+ "a11yRationale": "A plain positioned container; semantics come from its children.",
21047
+ "flexibility": [
21048
+ {
21049
+ "area": "position",
21050
+ "level": "flexible",
21051
+ "note": "Six anchor positions."
21052
+ }
21053
+ ]
21054
+ }
21055
+ },
21056
+ "install": "@cascivo/flow"
21057
+ },
21058
+ {
21059
+ "name": "flow/flow-story",
21060
+ "type": "flow",
21061
+ "description": "A scripted, sequenced, looping flow animation — walks a graph step by step with fade-in captions.",
21062
+ "category": "display",
21063
+ "version": "0.0.0",
21064
+ "files": [],
21065
+ "dependencies": ["@cascivo/core"],
21066
+ "tags": ["flow", "animation", "storyline", "walkthrough", "sequence"],
21067
+ "meta": {
21068
+ "name": "FlowStory",
21069
+ "description": "A scripted, sequenced, looping flow animation — walks a graph step by step with fade-in captions.",
21070
+ "category": "display",
21071
+ "states": ["playing", "paused"],
21072
+ "variants": [],
21073
+ "sizes": [],
21074
+ "props": [
21075
+ {
21076
+ "name": "nodes",
21077
+ "type": "FlowNode[]",
21078
+ "required": true
21079
+ },
21080
+ {
21081
+ "name": "edges",
21082
+ "type": "FlowEdge[]",
21083
+ "required": true
21084
+ },
21085
+ {
21086
+ "name": "script",
21087
+ "type": "StoryStep[]",
21088
+ "required": true,
21089
+ "description": "Ordered steps: { from, to, label? } or { edge, reverse? }."
21090
+ },
21091
+ {
21092
+ "name": "loop",
21093
+ "type": "boolean",
21094
+ "required": false,
21095
+ "default": "true"
21096
+ },
21097
+ {
21098
+ "name": "stepDuration",
21099
+ "type": "number",
21100
+ "required": false,
21101
+ "default": "1500"
21102
+ },
21103
+ {
21104
+ "name": "stepGap",
21105
+ "type": "number",
21106
+ "required": false,
21107
+ "default": "0",
21108
+ "description": "Extra pause after each step before advancing (ms) — makes the story easier to follow."
21109
+ },
21110
+ {
21111
+ "name": "playing",
21112
+ "type": "boolean",
21113
+ "required": false
21114
+ },
21115
+ {
21116
+ "name": "currentStep",
21117
+ "type": "number",
21118
+ "required": false
21119
+ },
21120
+ {
21121
+ "name": "onStepChange",
21122
+ "type": "(step: number) => void",
21123
+ "required": false
21124
+ },
21125
+ {
21126
+ "name": "controls",
21127
+ "type": "boolean",
21128
+ "required": false,
21129
+ "default": "true"
21130
+ },
21131
+ {
21132
+ "name": "autoPlay",
21133
+ "type": "boolean",
21134
+ "required": false,
21135
+ "default": "true"
21136
+ },
21137
+ {
21138
+ "name": "interactive",
21139
+ "type": "boolean",
21140
+ "required": false,
21141
+ "default": "false",
21142
+ "description": "A storyline is a view by default — set true to allow selecting/dragging/connecting."
21143
+ },
21144
+ {
21145
+ "name": "className",
21146
+ "type": "string",
21147
+ "required": false
21148
+ }
21149
+ ],
21150
+ "tokens": [
21151
+ "--cascivo-color-surface",
21152
+ "--cascivo-color-accent",
21153
+ "--cascivo-color-text-muted"
21154
+ ],
21155
+ "accessibility": {
21156
+ "role": "group",
21157
+ "wcag": "2.1-AA",
21158
+ "keyboard": ["Tab (focus controls)", "Enter/Space (play/pause, prev, next)"],
21159
+ "reducedMotion": true
21160
+ },
21161
+ "examples": [
21162
+ {
21163
+ "title": "A request/response storyboard",
21164
+ "description": "A<->B-->C: animate A→B, B→A, A→B, B→C, looping — each step fades in its caption.",
21165
+ "code": "() => (\n <FlowStory\n style={{ height: 340 }}\n nodes={[\n { id: 'A', position: { x: 0, y: 100 }, data: { label: 'Client' } },\n { id: 'B', position: { x: 240, y: 100 }, data: { label: 'Gateway' } },\n { id: 'C', position: { x: 480, y: 100 }, data: { label: 'Service' } },\n ]}\n edges={[\n { id: 'ab', source: 'A', target: 'B' },\n { id: 'bc', source: 'B', target: 'C' },\n ]}\n script={[\n { from: 'A', to: 'B', label: 'Request sent' },\n { from: 'B', to: 'A', label: 'Acknowledged' },\n { from: 'A', to: 'B', label: 'Payload streamed' },\n { from: 'B', to: 'C', label: 'Forwarded to Service' },\n ]}\n loop\n />\n)"
21166
+ },
21167
+ {
21168
+ "title": "A linear pipeline",
21169
+ "description": "Each stage animates and is captioned in turn.",
21170
+ "code": "() => (\n <FlowStory\n style={{ height: 320 }}\n nodes={[\n { id: 'ingest', position: { x: 0, y: 100 }, data: { label: 'Ingest' } },\n { id: 'transform', position: { x: 240, y: 100 }, data: { label: 'Transform' } },\n { id: 'load', position: { x: 480, y: 100 }, data: { label: 'Load' } },\n ]}\n edges={[\n { id: 'it', source: 'ingest', target: 'transform' },\n { id: 'tl', source: 'transform', target: 'load' },\n ]}\n script={[\n { from: 'ingest', to: 'transform', label: 'Records ingested', description: 'Raw events read from the source' },\n { from: 'transform', to: 'load', label: 'Transformed', description: 'Cleaned and enriched' },\n ]}\n />\n)"
21171
+ }
21172
+ ],
21173
+ "dependencies": ["@cascivo/core"],
21174
+ "tags": ["flow", "animation", "storyline", "walkthrough", "sequence"],
21175
+ "intent": {
21176
+ "whenToUse": [
21177
+ "Explaining how a flow works step by step, not just showing a static diagram",
21178
+ "Onboarding, architecture walkthroughs, and request/response narratives"
21179
+ ],
21180
+ "whenNotToUse": [
21181
+ "A static or freely-explorable graph — use <Flow>",
21182
+ "A single always-on animated edge — set animated on a FlowEdge"
21183
+ ],
21184
+ "antiPatterns": [
21185
+ {
21186
+ "bad": "A requestAnimationFrame loop to sequence steps",
21187
+ "good": "A currentStep signal advanced by a timer in useSignalEffect",
21188
+ "why": "CLAUDE.md bans the useEffect-style loop; the signal+timer idiom is deterministic + testable."
21189
+ }
21190
+ ],
21191
+ "related": [
21192
+ {
21193
+ "name": "Flow",
21194
+ "relationship": "contains",
21195
+ "reason": "Renders the graph the storyline animates."
21196
+ },
21197
+ {
21198
+ "name": "FlowEdge",
21199
+ "relationship": "pairs-with",
21200
+ "reason": "Reuses the animated-edge keyframe per step."
21201
+ }
21202
+ ],
21203
+ "a11yRationale": "The caption is an aria-live region announced each step; play/pause/prev/next make it keyboard-operable; travel motion is disabled under prefers-reduced-motion while captions are preserved.",
21204
+ "flexibility": [
21205
+ {
21206
+ "area": "script",
21207
+ "level": "flexible",
21208
+ "note": "Serializable steps — { from, to } or { edge, reverse }."
21209
+ },
21210
+ {
21211
+ "area": "playback",
21212
+ "level": "flexible",
21213
+ "note": "Controllable playing/currentStep; loop + per-step duration."
21214
+ }
21215
+ ]
21216
+ }
21217
+ },
21218
+ "install": "@cascivo/flow"
19178
21219
  }
19179
21220
  ],
19180
21221
  "blocks": [